room101/SPANNER.HPP

123 lines
3.2 KiB
C++

#ifndef __SPANNER_H
#define __SPANNER_H
typedef struct
{
int x1, x2;
} Span;
typedef struct
{
int nspans;
Span spans[100];
} SpanLine;
typedef struct
{
int width;
int height;
int ngaps;
SpanLine* lines;
} Spanner;
/*******************************************************************************
** InvalidateSpanArray
*******************************************************************************/
inline void
InvalidateSpanArray(SpanLine* dst, int x1, int x2)
{
dst->nspans = 1;
dst->spans[0].x1 = x1;
dst->spans[0].x2 = x2;
}
/*******************************************************************************
** ValidateSpanArray
*******************************************************************************/
inline void
ValidateSpanArray(SpanLine* array, int x1, int x2)
{
Span* span = array->spans;
Span* newspan = &array->spans[array->nspans];
for (int n = array->nspans; n--; span++)
{
if (x1 < span->x2 && x2 > span->x1)
{
if (x1 > span->x1)
{
if (x2 < span->x2)
{
newspan->x1 = x2;
newspan->x2 = span->x2;
newspan++;
array->nspans++;
}
span->x2 = x1;
}
else
{
if (x2 < span->x2)
{
span->x1 = x2;
}
else
{
for (Span* s = span; s != newspan; s[0] = s[1], s++);
newspan--;
span--;
array->nspans--;
}
}
}
}
assert(array->nspans >= 0 && array->nspans < 60);
}
/*******************************************************************************
** SpannerInvalidate
*******************************************************************************/
inline void
SpannerInvalidate(Spanner* spanner)
{
spanner->ngaps = spanner->height;
for (int i = 0; i < spanner->height; i++)
{
InvalidateSpanArray(&spanner->lines[i], 0, spanner->width);
}
}
/*******************************************************************************
** SpannerValidate
*******************************************************************************/
inline void
SpannerValidate(Spanner* spanner, int x1, int y1, int x2, int y2)
{
for (int i = y1; i < y2; i++)
{
ValidateSpanArray(&spanner->lines[i], x1, x2);
if (spanner->lines[i].nspans == 0) spanner->ngaps--;
}
}
/*******************************************************************************
** SpannerCreate
*******************************************************************************/
inline void
SpannerCreate(Spanner* spanner, int width, int height)
{
memset(spanner, 0, sizeof(Spanner));
spanner->width = width;
spanner->height = height;
spanner->lines = (SpanLine*) calloc(height, sizeof(SpanLine));
}
/*******************************************************************************
** SpannerDelete
*******************************************************************************/
inline void
SpannerDelete(Spanner* spanner)
{
free(spanner->lines);
}
#endif