diff options
Diffstat (limited to 'libXmu/src/Clip.c')
-rw-r--r-- | libXmu/src/Clip.c | 3233 |
1 files changed, 1616 insertions, 1617 deletions
diff --git a/libXmu/src/Clip.c b/libXmu/src/Clip.c index 121a69f23..67f8a51c1 100644 --- a/libXmu/src/Clip.c +++ b/libXmu/src/Clip.c @@ -1,1617 +1,1616 @@ -/* - * Copyright (c) 1998 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Except as contained in this notice, the name of the XFree86 Project shall - * not be used in advertising or otherwise to promote the sale, use or other - * dealings in this Software without prior written authorization from the - * XFree86 Project. - */ -/* $XFree86: xc/lib/Xmu/Clip.c,v 1.1 1998/08/16 10:25:03 dawes Exp $ */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdlib.h> - -#include <X11/IntrinsicP.h> -#include <X11/Xmu/Xmu.h> - -#define XmuMax(a, b) ((a) > (b) ? (a) : (b)) -#define XmuMin(a, b) ((a) < (b) ? (a) : (b)) - -/* - * Function: - * XmuNewArea - * - * Parameters: - * x1 - Coordinates of the rectangle - * y1 - "" - * x2 - "" - * y2 - "" - * - * Description: - * Creates a new rectangular clipping area - */ -XmuArea * -XmuNewArea(int x1, int y1, int x2, int y2) -{ - XmuArea *area; - - area = (XmuArea *)XtMalloc(sizeof(XmuArea)); - if (x2 > x1 && y2 > y1) - { - area->scanline = XmuNewScanline(y1, x1, x2); - area->scanline->next = XmuNewScanline(y2, 0, 0); - } - else - area->scanline = (XmuScanline *)NULL; - - return (area); -} - -/* - * Function: - * XmuAreaDup - * - * Parameters: - * area - Area to copy - * - * Description: - * Returns a copy of its argument - */ -XmuArea * -XmuAreaDup(XmuArea *area) -{ - XmuArea *dst; - - if (!area) - return ((XmuArea *)NULL); - - dst = XmuCreateArea(); - XmuAreaCopy(dst, area); - return (dst); -} - -/* - * Function: - * XmuAreaCopy - * - * Parameters: - * dst - destination area - * src - source area - * - * Description: - * Minimizes memory alocation, trying to use already alocated memory - * in dst, freeing what is not required anymore. - */ -XmuArea * -XmuAreaCopy(XmuArea *dst, XmuArea *src) -{ - XmuScanline *z, *p, *Z; - - if (!dst || !src || dst == src) - return (dst); - - z = p = dst->scanline; - Z = src->scanline; - - /*CONSTCOND*/ - while (1) - { - if (!Z) - { - if (z == dst->scanline) - { - XmuDestroyScanlineList(dst->scanline); - dst->scanline = (XmuScanline *)NULL; - } - else - { - XmuDestroyScanlineList(p->next); - p->next = (XmuScanline *)NULL; - } - return (dst); - } - if (z) - { - XmuScanlineCopy(z, Z); - z->y = Z->y; - } - else - { - z = XmuNewScanline(Z->y, 0, 0); - XmuScanlineCopy(z, Z); - if (p == dst->scanline && !dst->scanline) - p = dst->scanline = z; - else - p->next = z; - } - p = z; - z = z->next; - Z = Z->next; - } - - return (dst); -} - -/* - * Function: - * XmuAreaNot - * - * Parameters: - * area - area to operate - * x1 - retangle to clip the result against - * y1 - "" - * x2 - "" - * y2 - "" - * - * Description: - * (Input) - * (x1, y1) (x2, y1) - * +-------------+ - * +------------+ +----+ - * | +--------------+ - * +----------------+ - * (x1, y2) (x2, y2) - * - * (Output) - * (x1, y1) (x2, y1) - * +--------------+ +--------------------------+ - * | +------------+ +----+ | - * | | +--------------+ | - * +-+ +------------------------------------+ - * (x1, y2) (x2, y2) - */ -XmuArea * -XmuAreaNot(XmuArea *area, int x1, int y1, int x2, int y2) -{ - XmuScanline *z; - XmuArea *and; - - if (!area) - return (area); - - if (x1 > x2) - { - x1 ^= x2; x2 ^= x1; x1 ^= x2; - } - if (y1 > y2) - { - y1 ^= y2; y2 ^= y1; y1 ^= y2; - } - if (!area->scanline) - { - if ((area->scanline = XmuNewScanline(y1, x1, x2)) != NULL) - area->scanline->next = XmuNewScanline(y2, 0, 0); - return (area); - } - and = XmuNewArea(x1, y1, x2, y2); - XmuAreaAnd(area, and); - XmuDestroyArea(and); - z = area->scanline; - if (z->y != y1) - { - XmuScanline *q = XmuNewScanline(y1, x1, x2); - q->next = z; - area->scanline = q; - } - else - { - area->scanline = area->scanline->next; - XmuDestroyScanline(z); - XmuOptimizeArea(area); - if((z = area->scanline) == (XmuScanline *)NULL) - return (area); - } - - /* CONSTCOND */ - while (1) - { - XmuScanlineNot(z, x1, x2); - if (!z->next) - { - z->next = XmuNewScanline(y2, 0, 0); - break; - } - if (z->next->y == y2) - { - XmuDestroyScanlineList(z->next); - z->next = XmuNewScanline(y2, 0, 0); - break; - } - z = z->next; - } - - return (area); -} - -/* - * Function: - * XmuAreaOrXor - * - * Parameters: - * dst - destination area - * src - source area - * or - or operation if true, else xor operation - * - * Description: - * Executes Or (Union) or Xor (Reverse intesection) of the areas - */ -XmuArea * -XmuAreaOrXor(XmuArea *dst, XmuArea *src, Bool or) -{ - XmuScanline *z, *p, *Z, *P, *ins, *top; - - if (!dst || !src) - return (dst); - - if (dst == src) - { - if (or) - return (dst); - XmuDestroyScanlineList(dst->scanline); - dst->scanline = (XmuScanline *)NULL; - return (dst); - } - if (!XmuValidArea(src)) - return (dst); - if (!XmuValidArea(dst)) - { - XmuAreaCopy(dst, src); - return (dst); - } - - p = z = dst->scanline; - P = Z = src->scanline; - ins = XmuNewScanline(dst->scanline->y, 0, 0); - top = XmuNewScanline(dst->scanline->y, 0, 0); - XmuScanlineCopy(ins, dst->scanline); - XmuScanlineCopy(top, dst->scanline); - - /*CONSTCOND*/ - while (1) - { - if (!Z) - break; - else if (Z->y < z->y) - { - XmuScanline *q = XmuNewScanline(Z->y, 0, 0); - XmuScanlineCopy(q, Z); - - if (z == dst->scanline) - { - dst->scanline = p = q; - q->next = z; - } - else - { - p->next = q; - q->next = z; - if (Z->y >= p->y) - { - if (ins->y >= top->y - && (p->y != P->y || !XmuScanlineEqu(p, P) - || (ins->y <= P->y && !XmuScanlineEqu(ins, P)))) - { - if (or) - XmuScanlineOr(q, ins); - else - XmuScanlineXor(q, ins); - } - else if (Z->y >= top->y - && (top->y == p->y || top->y > ins->y - || !XmuValidScanline(Z) - || (p->y == P->y && XmuValidScanline(p) - && XmuValidScanline(P)) - || XmuScanlineEqu(ins, top))) - { - if (or) - XmuScanlineOr(q, top); - else - XmuScanlineXor(q, top); - } - if (ins->y != p->y && p->y != P->y) - { - XmuScanlineCopy(ins, p); - ins->y = p->y; - } - } - if (!XmuValidScanline(p) || Z->y <= p->y) - { - XmuScanlineCopy(top, p); - top->y = p->y; - } - p = q; - } - P = Z; - Z = Z->next; - continue; - } - else if (Z->y == z->y) - { - if (top->y != z->y) - { - XmuScanlineCopy(top, z); - top->y = z->y; - } - if (or) - XmuScanlineOr(z, Z); - else - XmuScanlineXor(z, Z); - P = Z; - Z = Z->next; - } - else if (P != Z) /* && Z->y > z->y */ - { - if (top->y == ins->y && top->y != z->y) - { - XmuScanlineCopy(top, z); - top->y = z->y; - } - if (ins->y != z->y) - { - XmuScanlineCopy(ins, z); - ins->y = z->y; - } - if (or) - XmuScanlineOr(z, P); - else - XmuScanlineXor(z, P); - } - else if (ins->y != z->y) - { - XmuScanlineCopy(ins, z); - ins->y = z->y; - } - p = z; - z = z->next; - if (!z) - { - while (Z) - { - p->next = XmuNewScanline(Z->y, 0, 0); - XmuScanlineCopy(p->next, Z); - p = p->next; - Z = Z->next; - } - break; - } - else if (ins->y > top->y && !XmuValidScanline(z) - && XmuValidScanline(ins)) - { - XmuScanlineCopy(top, ins); - top->y = ins->y; - } - } - XmuOptimizeArea(dst); - XmuDestroyScanline(ins); - XmuDestroyScanline(top); - - return (dst); -} - -/* - * Function: - * XmuAreaAnd(dst, src) - * - * Parameters: - * dst - destination area - * src - source area - * - * Description: - * Executes And (intersection) of the areas - */ -XmuArea * -XmuAreaAnd(XmuArea *dst, XmuArea *src) -{ - XmuScanline *z, *p, *Z, *P, *top; - - if (!dst || !src || dst == src) - return (dst); - if (!XmuValidArea(dst) || !XmuValidArea(src)) - { - XmuDestroyScanlineList(dst->scanline); - dst->scanline = (XmuScanline *)NULL; - return (dst); - } - z = p = dst->scanline; - Z = P = src->scanline; - top = XmuNewScanline(dst->scanline->y, 0, 0); - XmuScanlineCopy(top, dst->scanline); - - while (z) - { - while (Z->next && Z->next->y < z->y) - { - P = Z; - Z = Z->next; - if (Z->y >= p->y) - { - XmuScanline *q = XmuNewScanline(Z->y, 0, 0); - XmuScanlineCopy(q, Z); - - XmuScanlineAnd(q, top); - if (p->y != P->y) - { - XmuScanlineAnd(p, P); - p->y = XmuMax(p->y, P->y); - } - p->next = q; - q->next = z; - p = q; - } - } - if (!z->next) - { - z->y = XmuMax(z->y, Z->y); - break; - } - while (Z->y >= z->next->y) - { - if (z == dst->scanline) - { - p = dst->scanline = dst->scanline->next; - XmuDestroyScanline(z); - z = dst->scanline; - } - else - { - p->next = z->next; - XmuDestroyScanline(z); - z = p; - } - if (!z || !z->next) - { - XmuOptimizeArea(dst); - XmuDestroyScanline(top); - - return (dst); - } - } - if (Z->y > p->y) - z->y = XmuMax(z->y, Z->y); - if (top->y != z->y) - { - XmuScanlineCopy(top, z); - top->y = z->y; - } - XmuScanlineAnd(z, Z); - p = z; - z = z->next; - } - XmuOptimizeArea(dst); - XmuDestroyScanline(top); - - return (dst); -} - -/* - * Function: - * XmuValidArea(area) - * - * Parameters: - * area - area to verify - * - * Description: - * Verifies if the area is valid and/or useful - */ -Bool -XmuValidArea(XmuArea *area) -{ - XmuScanline *at; - - if (!area || !area->scanline) - return (False); - - at = area->scanline; - while (at) - { - if (XmuValidScanline(at)) - return (True); - at = at->next; - } - - return (False); -} - -/* - * Function: - * XmuValidScanline - * - * Parameters: - * scanline - scanline to verify - * - * Description: - * Verifies if a scanline is useful - */ -Bool -XmuValidScanline(XmuScanline *scanline) -{ - XmuSegment *z; - - if (!scanline) - return (False); - - z = scanline->segment; - while (z) - { - if (XmuValidSegment(z)) - return (True); - z = z->next; - } - - return (False); -} - -/* - * Function: - * XmuScanlineEqu - * - * Parameters: - * s1 - scanline 1 - * s2 - scanline 2 - * - * Description: - * Checks if s1 and s2 are equal - */ -Bool -XmuScanlineEqu(XmuScanline *s1, XmuScanline *s2) -{ - XmuSegment *z, *Z; - - if ((!s1 && !s2) || s1 == s2) - return (True); - if (!s1 || !s2) - return (False); - - z = s1->segment; - Z = s2->segment; - - /*CONSTCOND*/ - while (1) - { - if (!z && !Z) - return (True); - if (!z || !Z) - return (False); - if (!XmuSegmentEqu(z, Z)) - return (False); - z = z->next; - Z = Z->next; - } - /*NOTREACHED*/ -} - -/* - * Function: - * XmuNewSegment - * - * Parameters: - * x1 - coordinates of the segment - * x2 - "" - * - * Description: - * Creates a new segments with the coordinates x1 and x2 - * - * Returns: - * New Segment of NULL - */ -XmuSegment * -XmuNewSegment(int x1, int x2) -{ - XmuSegment *segment; - - if ((segment = (XmuSegment *)XtMalloc(sizeof(XmuSegment))) == NULL) - return (segment); - - segment->x1 = x1; - segment->x2 = x2; - segment->next = (XmuSegment *)NULL; - - return (segment); -} - -/* - * Function: - * XmuDestroySegmentList - * - * Parameters: - * segment - Segment to destroy - * - * Description: - * Frees the memory used by the list headed by segment - */ -void -XmuDestroySegmentList(XmuSegment *segment) -{ - XmuSegment *z; - - if (!segment) - return; - - while (segment) - { - z = segment; - segment = segment->next; - XmuDestroySegment(z); - } -} - -/* - * Function: - * XmuScanlineCopy - * - * Parameters: - * dst - destination scanline - * src - source scanline - * - * Description: - * Makes dst contain the same data as src - */ -XmuScanline * -XmuScanlineCopy(XmuScanline *dst, XmuScanline *src) -{ - XmuSegment *z, *p, *Z; - - if (!dst || !src || dst == src) - return (dst); - - z = p = dst->segment; - Z = src->segment; - - /*CONSTCOND*/ - while (1) - { - if (!Z) - { - if (z == dst->segment) - dst->segment = (XmuSegment *)NULL; - else - p->next = (XmuSegment *)NULL; - XmuDestroySegmentList(z); - return (dst); - } - if (z) - { - z->x1 = Z->x1; - z->x2 = Z->x2; - } - else - { - z = XmuNewSegment(Z->x1, Z->x2); - if (p == dst->segment && !dst->segment) - p = dst->segment = z; - else - p->next = z; - } - p = z; - z = z->next; - Z = Z->next; - } - /*NOTREACHED*/ -} - -/* - * Function: - * XmuAppendSegment - * - * Parameters: - * segment - destination segment - * append - segment to add - * - * Description: - * Adds a copy of the append list at the end of the segment list - */ -Bool -XmuAppendSegment(XmuSegment *segment, XmuSegment *append) -{ - if (!segment || !append) - return (False); - - if (segment->next) - /* Should not happen! */ - XmuDestroySegmentList(segment->next); - - while (append) - { - if (XmuValidSegment(append)) - { - if ((segment->next = XmuNewSegment(append->x1, append->x2)) == NULL) - return (False); - segment = segment->next; - } - append = append->next; - } - - return (True); -} - -/* - * Function: - * XmuOptimizeScanline - * - * Parameters: - * scanline - scanline to optimize - * - * Description: - * Some functions, when transforming Segments of Scanlines, left these - * with unnecessary data (that may cause error in these same functions). - * This function corrects these incorrect segments. - */ -XmuScanline * -XmuOptimizeScanline(XmuScanline *scanline) -{ - XmuSegment *z, *p; - - while (scanline->segment && !XmuValidSegment(scanline->segment)) - { - XmuSegment *s = scanline->segment; - - scanline->segment = scanline->segment->next; - XmuDestroySegment(s); - } - for (z = p = scanline->segment; z; p = z, z = z->next) - { - if (!XmuValidSegment(z)) - { - p->next = z->next; - XmuDestroySegment(z); - z = p; - } - } - return (scanline); -} - -/* - * Name: - * XmuScanlineNot(scanline, minx, maxx) - * - * Parameters: - * scanline - scanlines operate - * minx - minimum x coordinate - * maxx - maximum x coordinate - * - * Description: - * (minx) (maxx) - * + + - * (input) +---------+ +--------+ +--------+ - * (output) +-----+ +-----+ +--------+ +------------+ - */ -XmuScanline * -XmuScanlineNot(XmuScanline *scanline, int minx, int maxx) -{ - XmuSegment *z; - static XmuSegment x = { 0, 0, NULL }; - static XmuScanline and = { 0, &x, NULL }; - - if (!scanline) - return (scanline); - - XmuOptimizeScanline(scanline); - if (minx > maxx) - { - minx ^= maxx; maxx ^= minx; minx ^= maxx; - } - and.segment->x1 = minx; - and.segment->x2 = maxx; - XmuScanlineAnd(scanline, &and); - if (!scanline->segment) - { - scanline->segment = XmuNewSegment(minx, maxx); - return (scanline); - } - z = scanline->segment; - if (z->x1 != minx) - { - XmuSegment *q = XmuNewSegment(minx, z->x1); - - q->next = z; - scanline->segment = q; - } - - /*CONSTCOND*/ - while (1) - { - z->x1 = z->x2; - if (!z->next) - { - z->x2 = maxx; - break; - } - z->x2 = z->next->x1; - if (z->next->x2 == maxx) - { - XmuDestroySegment(z->next); - z->next = (XmuSegment *)NULL; - break; - } - z = z->next; - } - - return (scanline); -} - - -#ifndef notdef -/* - * Function: - * XmuScanlineOrSegment - * - * Parameters: - * dst - destionation scanline - * src - source segment - * - * Description: - * (input) +-----------+ +--------+ +---------+ - * (src) +-------------------+ - * (output) +-------------------------+ +---------+ - */ -XmuScanline * -XmuScanlineOrSegment(XmuScanline *dst, XmuSegment *src) -{ - XmuSegment *z, *p, ins; - - if (!src || !dst || !XmuValidSegment(src)) - return (dst); - - if (!dst->segment) - { - dst->segment = XmuNewSegment(src->x1, src->x2); - return (dst); - } - - z = p = dst->segment; - ins.x1 = src->x1; - ins.x2 = src->x2; - - /*CONSTCOND*/ - while (1) - { - if (!z) - { - XmuSegment *q = XmuNewSegment(ins.x1, ins.x2); - - if (p == dst->segment && z == p) - dst->segment = q; - else - p->next = q; - break; - } - else if (ins.x2 < z->x1) - { - XmuSegment *q = XmuNewSegment(ins.x1, ins.x2); - - if (p == dst->segment && z == p) - { - q->next = dst->segment; - dst->segment = q; - } - else - { - p->next = q; - q->next = z; - } - break; - } - else if (ins.x2 <= z->x2) - { - z->x1 = XmuMin(z->x1, ins.x1); - break; - } - else if (ins.x1 <= z->x2) - { - ins.x1 = XmuMin(z->x1, ins.x1); - if (!z->next) - { - z->x1 = ins.x1; - z->x2 = ins.x2; - break; - } - else - { - if (z == dst->segment) - { - p = dst->segment = dst->segment->next; - XmuDestroySegment(z); - z = dst->segment; - continue; - } - else - { - p->next = z->next; - XmuDestroySegment(z); - z = p; - } - } - } - p = z; - z = z->next; - } - - return (dst); -} - -/* - * Function: - * XmuScanlineAndSegment - * - * Parameters: - * dst - destination scanline - * src - source segment - * - * Description: - * (input) +------------+ +------+ +----------+ - * (src) +---------------------+ - * (output) +-------+ +------+ - */ -XmuScanline * -XmuScanlineAndSegment(XmuScanline *dst, XmuSegment *src) -{ - XmuSegment *z, *p; - - if (!dst || !src) - return (dst); - - if (!XmuValidSegment(src)) - { - XmuDestroySegmentList(dst->segment); - dst->segment = (XmuSegment *)NULL; - return (dst); - } - if (!dst->segment) - return (dst); - - z = p = dst->segment; - while (z) - { - if (src->x2 <= z->x1 || src->x1 >= z->x2) - { - if (z == dst->segment) - { - p = dst->segment = dst->segment->next; - XmuDestroySegment(z); - z = dst->segment; - continue; - } - else - { - p->next = z->next; - XmuDestroySegment(z); - z = p; - } - } - else - { - z->x1 = XmuMax(z->x1, src->x1); - z->x2 = XmuMin(z->x2, src->x2); - } - p = z; - z = z->next; - } - - return (dst); -} - -/* - * Function: - * XmuScanlineXorSegment - * - * Parameters: - * dst - destionation scanline - * src - source segment - * - * Descriptipn: - * (input) +------------+ +----------+ +-----------+ - * (src) +------------------------+ - * (output) +---+ +--+ +-+ +-----------+ - */ -XmuScanline * -XmuScanlineXorSegment(XmuScanline *dst, XmuSegment *src) -{ - XmuSegment *p, *z, ins; - int tmp1, tmp2; - - if (!dst || !src || !XmuValidSegment(src)) - return (dst); - if (!dst->segment) - { - dst->segment = XmuNewSegment(src->x1, src->x2); - return (dst); - } - - p = z = dst->segment; - ins.x1 = src->x1; - ins.x2 = src->x2; - - /*CONSTCOND*/ - while (1) - { - if (!XmuValidSegment((&ins))) - break; - if (!z || ins.x2 < z->x1) - { - XmuSegment *q = XmuNewSegment(ins.x1, ins.x2); - - q->next = z; - if (z == dst->segment) - dst->segment = q; - else - p->next = q; - break; - } - else if (ins.x2 == z->x1) - { - z->x1 = ins.x1; - break; - } - else if (ins.x1 < z->x2) - { - if (ins.x1 < z->x1) - { - tmp1 = ins.x2; - tmp2 = z->x2; - ins.x2 = XmuMax(ins.x2, z->x2); - z->x2 = z->x1; - z->x1 = ins.x1; - ins.x1 = XmuMin(tmp1, tmp2); - } - else if (ins.x1 > z->x1) - { - tmp1 = ins.x1; - ins.x1 = XmuMin(ins.x2, z->x2); - ins.x2 = XmuMax(z->x2, ins.x2); - z->x2 = tmp1; - } - else /* ins.x1 == z->x1 */ - { - if (ins.x2 < z->x2) - { - z->x1 = ins.x2; - break; - } - else - { - ins.x1 = z->x2; - if (z == dst->segment) - p = dst->segment = dst->segment->next; - else - p->next = z->next; - XmuDestroySegment(z); - z = p; - continue; - } - } - } - else if (ins.x1 == z->x2) - { - ins.x1 = z->x1; - if (z == dst->segment) - p = dst->segment = dst->segment->next; - else - p->next = z->next; - XmuDestroySegment(z); - z = p; - continue; - } - p = z; - z = z->next; - } - - return (dst); -} -#endif /* notdef */ - -/* - * Function: - * ScanlineOr - * - * Parameters: - * dst - destionation scanline - * src - source scanline - * - * Description: - * (input) +--------------+ +-----+ +----------+ - * (src) +---------------------+ +-----------+ - * (output) +-------------------------+ +----------------+ - */ -XmuScanline * -XmuScanlineOr(XmuScanline *dst, XmuScanline *src) -{ - XmuSegment *z, *p, *Z, ins; - - if (!src || !src->segment || !dst || dst == src) - return (dst); - if (!dst->segment) - { - XmuScanlineCopy(dst, src); - return (dst); - } - - z = p = dst->segment; - Z = src->segment; - ins.x1 = Z->x1; - ins.x2 = Z->x2; - - /*CONSTCOND*/ - while (1) - { - while (!XmuValidSegment((&ins))) - { - if ((Z = Z->next) == (XmuSegment *)NULL) - return (dst); - ins.x1 = Z->x1; - ins.x2 = Z->x2; - } - if (!z) - { - XmuSegment *q = XmuNewSegment(ins.x1, ins.x2); - - if (p == dst->segment && z == p) - dst->segment = p = q; - else - { - p->next = q; - p = q; - } - Z = Z->next; - XmuAppendSegment(p, Z); - break; - } - else if (ins.x2 < z->x1) - { - XmuSegment *r = XmuNewSegment(ins.x1, ins.x2); - - if (p == dst->segment && z == p) - { - r->next = dst->segment; - dst->segment = p = r; - } - else - { - p->next = r; - r->next = z; - p = r; - } - Z = Z->next; - if (!Z) - break; - else - { - ins.x1 = Z->x1; - ins.x2 = Z->x2; - continue; - } - } - else if (ins.x2 <= z->x2) - { - z->x1 = XmuMin(z->x1, ins.x1); - Z = Z->next; - if (!Z) - break; - else - { - ins.x1 = Z->x1; - ins.x2 = Z->x2; - continue; - } - } - else if (ins.x1 <= z->x2) - { - ins.x1 = XmuMin(z->x1, ins.x1); - if (!z->next) - { - z->x1 = ins.x1; - z->x2 = ins.x2; - p = z; - Z = Z->next; - XmuAppendSegment(p, Z); - break; - } - else - { - if (z == dst->segment) - { - p = dst->segment = dst->segment->next; - XmuDestroySegment(z); - z = p; - continue; - } - else - { - p->next = z->next; - XmuDestroySegment(z); - z = p; - } - } - } - p = z; - z = z->next; - } - - return (dst); -} - -/* - * Function: - * XmuScanlineAnd - * - * Parameters: - * dst - destination scanline - * src - source scanline - * - * Description: - * (input) +--------------+ +-----+ +----------+ - * (src) +---------------------+ +-----------+ - * (output) +----------+ +-----+ +-----+ - */ -XmuScanline * -XmuScanlineAnd(XmuScanline *dst, XmuScanline *src) -{ - XmuSegment *z, *p, *Z; - - if (!dst || !src || dst == src || !dst->segment) { - return (dst); - } - if (!src->segment) - { - XmuDestroySegmentList(dst->segment); - dst->segment = (XmuSegment *)NULL; - return (dst); - } - z = p = dst->segment; - Z = src->segment; - - while (z) - { - while (!XmuValidSegment(Z) || Z->x2 <= z->x1) - { - Z = Z->next; - if (!Z) - { - if (z == dst->segment) - dst->segment = (XmuSegment *)NULL; - else - p->next = (XmuSegment *)0; - XmuDestroySegmentList(z); - return (dst); - } - } - if (Z->x1 >= z->x2) - { - if (z == dst->segment) - { - p = dst->segment = dst->segment->next; - XmuDestroySegment(z); - z = dst->segment; - } - else - { - p->next = z->next; - XmuDestroySegment(z); - z = p->next; - } - if (!z) - return (dst); - else - continue; - } - z->x1 = XmuMax(z->x1, Z->x1); - if (z->x2 > Z->x2) - { - if (Z->next) - { - XmuSegment *q = XmuNewSegment(Z->x2, z->x2); - - q->next = z->next; - z->next = q; - } - z->x2 = Z->x2; - } - p = z; - z = z->next; - } - - return (dst); -} - -/* - * Function: - * ScanlineXor - * - * Parameters: - * dst - destination scanline - * src - source scanline - * - * Description: - * (input) +--------------+ +-----+ +----------+ - * (src) +---------------------+ +-----------+ - * (output) +---+ +--+ +-+ +----+ +-----+ - */ -XmuScanline * -XmuScanlineXor(XmuScanline *dst, XmuScanline *src) -{ - XmuSegment *z, *p, *Z, ins; - int tmp1, tmp2; - - if (!src || !dst || !src->segment) - return (dst); - if (src == dst) - { - XmuDestroySegmentList(dst->segment); - dst->segment = (XmuSegment *)NULL; - return (dst); - } - if (!dst->segment) - { - XmuScanlineCopy(dst, src); - return (dst); - } - - z = p = dst->segment; - Z = src->segment; - ins.x1 = Z->x1; - ins.x2 = Z->x2; - - /*CONSTCOND*/ - while (1) - { - while (!XmuValidSegment((&ins))) - { - if ((Z = Z->next) == (XmuSegment *)NULL) - return (dst); - ins.x1 = Z->x1; - ins.x2 = Z->x2; - } - if (!z) - { - XmuSegment *q = XmuNewSegment(ins.x1, ins.x2); - - if (!dst->segment) - dst->segment = q; - else - p->next = q; - p = q; - Z = Z->next; - XmuAppendSegment(p, Z); - break; - } - else if (ins.x2 < z->x1) - { - XmuSegment *q = XmuNewSegment(ins.x1, ins.x2); - - q->next = z; - if (z == dst->segment) - dst->segment = q; - else - p->next = q; - if ((Z = Z->next) == (XmuSegment *)NULL) - return (dst); - - p = q; - ins.x1 = Z->x1; - ins.x2 = Z->x2; - continue; - } - else if (ins.x2 == z->x1) - { - z->x1 = ins.x1; - if ((Z = Z->next) == (XmuSegment *)NULL) - break; - ins.x1 = Z->x1; - ins.x2 = Z->x2; - continue; - } - else if (ins.x1 < z->x2) - { - if (ins.x1 == z->x1) - { - if (ins.x2 < z->x2) - { - z->x1 = ins.x2; - if ((Z = Z->next) == (XmuSegment *)NULL) - break; - ins.x1 = Z->x1; - ins.x2 = Z->x2; - continue; - } - else - { - ins.x1 = z->x2; - if (z == dst->segment) - p = dst->segment = dst->segment->next; - else - p->next = z->next; - XmuDestroySegment(z); - z = p; - continue; - } - } - else - { - if (Z->x2 < z->x2) - { - XmuSegment *q = XmuNewSegment(XmuMin(ins.x1, z->x1), - XmuMax(z->x1, ins.x1)); - - q->next = z; - if (z == dst->segment) - dst->segment = q; - else - p->next = q; - ins.x1 = z->x2; - z->x1 = ins.x2; - p = q; - continue; - } - else - { - tmp1 = ins.x2; - tmp2 = z->x2; - ins.x2 = XmuMax(ins.x2, z->x2); - z->x2 = XmuMax(z->x1, ins.x1); - z->x1 = XmuMin(ins.x1, z->x1); - ins.x1 = XmuMin(tmp1, tmp2); - } - } - } - else if (ins.x1 == z->x2) - { - ins.x1 = z->x1; - if (z == dst->segment) - p = dst->segment = dst->segment->next; - else - p->next = z->next; - XmuDestroySegment(z); - z = p; - continue; - } - p = z; - z = z->next; - } - - return (dst); -} - -/* - * Function: - * XmuNewScanline - * - * Parameters: - * y - y coordinate - * x1 - left coordinate - * x2 - right coordinate - * - * Description: - * Creates a new Scanline - */ -XmuScanline * -XmuNewScanline(int y, int x1, int x2) -{ - XmuScanline *scanline; - - scanline = (XmuScanline *)XtMalloc(sizeof(XmuScanline)); - scanline->y = y; - if (x1 < x2) - scanline->segment = XmuNewSegment(x1, x2); - else - scanline->segment = (XmuSegment *)NULL; - - scanline->next = (XmuScanline *)NULL; - - return (scanline); -} - -/* - * Function: - * XmuDestroyScanlineList - * - * Parameters: - * scanline - scanline list to destroy - * - * Description: - * Destroy a scanline list - * - * Observation: - * Use as follow: - * XmuDestroyScanlineList(area->scanline); - * area->scanline = (XmuScanline *)NULL; - */ -void -XmuDestroyScanlineList(XmuScanline *scanline) -{ - XmuScanline *z; - - if (!scanline) - return; - - while (scanline) - { - z = scanline; - scanline = scanline->next; - XmuDestroyScanline(z); - } -} - -/* - * Function: - * XmuOptimizeArea - * - * Parameters: - * area - area to optimize - * - * Description: - * Optimizes an area. This function is called when finishing a - * operation between areas, since they can end with redundant data, - * and the algorithms for area combination waits a area with - * correct data (but can left unnecessary data in the area, to avoid - * to much paranoia tests). - */ -XmuArea *XmuOptimizeArea(XmuArea *area) -{ - XmuScanline *pr, *at; - - if (!area || !area->scanline) - return (area); - - if (!area->scanline->next) - { - XmuDestroyScanlineList(area->scanline); - area->scanline = (XmuScanline *)0; - return (area); - } - - pr = area->scanline; - at = area->scanline->next; - while (area->scanline && (!XmuValidScanline(area->scanline) - || (area->scanline->next && area->scanline->y - >= area->scanline->next->y))) - { - area->scanline = area->scanline->next; - XmuDestroyScanline(pr); - pr = area->scanline; - if (pr) - at = pr->next; - } - - for (; at; pr = at, at = at->next) - { - if (XmuScanlineEqu(at, pr) - || (!XmuValidScanline(at) && !XmuValidScanline(pr)) - || (at->next && at->y >= at->next->y)) - { - pr->next = at->next; - XmuDestroyScanline(at); - at = pr; - } - } - if (pr && XmuValidScanline(pr)) - { - XmuDestroySegmentList(pr->segment); - pr->segment = (XmuSegment *)NULL; - } - if (area->scanline && !area->scanline->next) - { - XmuDestroyScanlineList(area->scanline); - area->scanline = (XmuScanline *)NULL; - } - - return (area); -} +/*
+ * Copyright (c) 1998 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the XFree86 Project shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from the
+ * XFree86 Project.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+
+#include <X11/IntrinsicP.h>
+#include <X11/Xmu/Xmu.h>
+
+#define XmuMax(a, b) ((a) > (b) ? (a) : (b))
+#define XmuMin(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ * Function:
+ * XmuNewArea
+ *
+ * Parameters:
+ * x1 - Coordinates of the rectangle
+ * y1 - ""
+ * x2 - ""
+ * y2 - ""
+ *
+ * Description:
+ * Creates a new rectangular clipping area
+ */
+XmuArea *
+XmuNewArea(int x1, int y1, int x2, int y2)
+{
+ XmuArea *area;
+
+ area = (XmuArea *)XtMalloc(sizeof(XmuArea));
+ if (x2 > x1 && y2 > y1)
+ {
+ area->scanline = XmuNewScanline(y1, x1, x2);
+ area->scanline->next = XmuNewScanline(y2, 0, 0);
+ }
+ else
+ area->scanline = (XmuScanline *)NULL;
+
+ return (area);
+}
+
+/*
+ * Function:
+ * XmuAreaDup
+ *
+ * Parameters:
+ * area - Area to copy
+ *
+ * Description:
+ * Returns a copy of its argument
+ */
+XmuArea *
+XmuAreaDup(XmuArea *area)
+{
+ XmuArea *dst;
+
+ if (!area)
+ return ((XmuArea *)NULL);
+
+ dst = XmuCreateArea();
+ XmuAreaCopy(dst, area);
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuAreaCopy
+ *
+ * Parameters:
+ * dst - destination area
+ * src - source area
+ *
+ * Description:
+ * Minimizes memory alocation, trying to use already alocated memory
+ * in dst, freeing what is not required anymore.
+ */
+XmuArea *
+XmuAreaCopy(XmuArea *dst, XmuArea *src)
+{
+ XmuScanline *z, *p, *Z;
+
+ if (!dst || !src || dst == src)
+ return (dst);
+
+ z = p = dst->scanline;
+ Z = src->scanline;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ if (!Z)
+ {
+ if (z == dst->scanline)
+ {
+ XmuDestroyScanlineList(dst->scanline);
+ dst->scanline = (XmuScanline *)NULL;
+ }
+ else
+ {
+ XmuDestroyScanlineList(p->next);
+ p->next = (XmuScanline *)NULL;
+ }
+ return (dst);
+ }
+ if (z)
+ {
+ XmuScanlineCopy(z, Z);
+ z->y = Z->y;
+ }
+ else
+ {
+ z = XmuNewScanline(Z->y, 0, 0);
+ XmuScanlineCopy(z, Z);
+ if (p == dst->scanline && !dst->scanline)
+ p = dst->scanline = z;
+ else
+ p->next = z;
+ }
+ p = z;
+ z = z->next;
+ Z = Z->next;
+ }
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuAreaNot
+ *
+ * Parameters:
+ * area - area to operate
+ * x1 - retangle to clip the result against
+ * y1 - ""
+ * x2 - ""
+ * y2 - ""
+ *
+ * Description:
+ * (Input)
+ * (x1, y1) (x2, y1)
+ * +-------------+
+ * +------------+ +----+
+ * | +--------------+
+ * +----------------+
+ * (x1, y2) (x2, y2)
+ *
+ * (Output)
+ * (x1, y1) (x2, y1)
+ * +--------------+ +--------------------------+
+ * | +------------+ +----+ |
+ * | | +--------------+ |
+ * +-+ +------------------------------------+
+ * (x1, y2) (x2, y2)
+ */
+XmuArea *
+XmuAreaNot(XmuArea *area, int x1, int y1, int x2, int y2)
+{
+ XmuScanline *z;
+ XmuArea *and;
+
+ if (!area)
+ return (area);
+
+ if (x1 > x2)
+ {
+ x1 ^= x2; x2 ^= x1; x1 ^= x2;
+ }
+ if (y1 > y2)
+ {
+ y1 ^= y2; y2 ^= y1; y1 ^= y2;
+ }
+ if (!area->scanline)
+ {
+ if ((area->scanline = XmuNewScanline(y1, x1, x2)) != NULL)
+ area->scanline->next = XmuNewScanline(y2, 0, 0);
+ return (area);
+ }
+ and = XmuNewArea(x1, y1, x2, y2);
+ XmuAreaAnd(area, and);
+ XmuDestroyArea(and);
+ z = area->scanline;
+ if (z->y != y1)
+ {
+ XmuScanline *q = XmuNewScanline(y1, x1, x2);
+ q->next = z;
+ area->scanline = q;
+ }
+ else
+ {
+ area->scanline = area->scanline->next;
+ XmuDestroyScanline(z);
+ XmuOptimizeArea(area);
+ if((z = area->scanline) == (XmuScanline *)NULL)
+ return (area);
+ }
+
+ /* CONSTCOND */
+ while (1)
+ {
+ XmuScanlineNot(z, x1, x2);
+ if (!z->next)
+ {
+ z->next = XmuNewScanline(y2, 0, 0);
+ break;
+ }
+ if (z->next->y == y2)
+ {
+ XmuDestroyScanlineList(z->next);
+ z->next = XmuNewScanline(y2, 0, 0);
+ break;
+ }
+ z = z->next;
+ }
+
+ return (area);
+}
+
+/*
+ * Function:
+ * XmuAreaOrXor
+ *
+ * Parameters:
+ * dst - destination area
+ * src - source area
+ * or - or operation if true, else xor operation
+ *
+ * Description:
+ * Executes Or (Union) or Xor (Reverse intesection) of the areas
+ */
+XmuArea *
+XmuAreaOrXor(XmuArea *dst, XmuArea *src, Bool or)
+{
+ XmuScanline *z, *p, *Z, *P, *ins, *top;
+
+ if (!dst || !src)
+ return (dst);
+
+ if (dst == src)
+ {
+ if (or)
+ return (dst);
+ XmuDestroyScanlineList(dst->scanline);
+ dst->scanline = (XmuScanline *)NULL;
+ return (dst);
+ }
+ if (!XmuValidArea(src))
+ return (dst);
+ if (!XmuValidArea(dst))
+ {
+ XmuAreaCopy(dst, src);
+ return (dst);
+ }
+
+ p = z = dst->scanline;
+ P = Z = src->scanline;
+ ins = XmuNewScanline(dst->scanline->y, 0, 0);
+ top = XmuNewScanline(dst->scanline->y, 0, 0);
+ XmuScanlineCopy(ins, dst->scanline);
+ XmuScanlineCopy(top, dst->scanline);
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ if (!Z)
+ break;
+ else if (Z->y < z->y)
+ {
+ XmuScanline *q = XmuNewScanline(Z->y, 0, 0);
+ XmuScanlineCopy(q, Z);
+
+ if (z == dst->scanline)
+ {
+ dst->scanline = p = q;
+ q->next = z;
+ }
+ else
+ {
+ p->next = q;
+ q->next = z;
+ if (Z->y >= p->y)
+ {
+ if (ins->y >= top->y
+ && (p->y != P->y || !XmuScanlineEqu(p, P)
+ || (ins->y <= P->y && !XmuScanlineEqu(ins, P))))
+ {
+ if (or)
+ XmuScanlineOr(q, ins);
+ else
+ XmuScanlineXor(q, ins);
+ }
+ else if (Z->y >= top->y
+ && (top->y == p->y || top->y > ins->y
+ || !XmuValidScanline(Z)
+ || (p->y == P->y && XmuValidScanline(p)
+ && XmuValidScanline(P))
+ || XmuScanlineEqu(ins, top)))
+ {
+ if (or)
+ XmuScanlineOr(q, top);
+ else
+ XmuScanlineXor(q, top);
+ }
+ if (ins->y != p->y && p->y != P->y)
+ {
+ XmuScanlineCopy(ins, p);
+ ins->y = p->y;
+ }
+ }
+ if (!XmuValidScanline(p) || Z->y <= p->y)
+ {
+ XmuScanlineCopy(top, p);
+ top->y = p->y;
+ }
+ p = q;
+ }
+ P = Z;
+ Z = Z->next;
+ continue;
+ }
+ else if (Z->y == z->y)
+ {
+ if (top->y != z->y)
+ {
+ XmuScanlineCopy(top, z);
+ top->y = z->y;
+ }
+ if (or)
+ XmuScanlineOr(z, Z);
+ else
+ XmuScanlineXor(z, Z);
+ P = Z;
+ Z = Z->next;
+ }
+ else if (P != Z) /* && Z->y > z->y */
+ {
+ if (top->y == ins->y && top->y != z->y)
+ {
+ XmuScanlineCopy(top, z);
+ top->y = z->y;
+ }
+ if (ins->y != z->y)
+ {
+ XmuScanlineCopy(ins, z);
+ ins->y = z->y;
+ }
+ if (or)
+ XmuScanlineOr(z, P);
+ else
+ XmuScanlineXor(z, P);
+ }
+ else if (ins->y != z->y)
+ {
+ XmuScanlineCopy(ins, z);
+ ins->y = z->y;
+ }
+ p = z;
+ z = z->next;
+ if (!z)
+ {
+ while (Z)
+ {
+ p->next = XmuNewScanline(Z->y, 0, 0);
+ XmuScanlineCopy(p->next, Z);
+ p = p->next;
+ Z = Z->next;
+ }
+ break;
+ }
+ else if (ins->y > top->y && !XmuValidScanline(z)
+ && XmuValidScanline(ins))
+ {
+ XmuScanlineCopy(top, ins);
+ top->y = ins->y;
+ }
+ }
+ XmuOptimizeArea(dst);
+ XmuDestroyScanline(ins);
+ XmuDestroyScanline(top);
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuAreaAnd(dst, src)
+ *
+ * Parameters:
+ * dst - destination area
+ * src - source area
+ *
+ * Description:
+ * Executes And (intersection) of the areas
+ */
+XmuArea *
+XmuAreaAnd(XmuArea *dst, XmuArea *src)
+{
+ XmuScanline *z, *p, *Z, *P, *top;
+
+ if (!dst || !src || dst == src)
+ return (dst);
+ if (!XmuValidArea(dst) || !XmuValidArea(src))
+ {
+ XmuDestroyScanlineList(dst->scanline);
+ dst->scanline = (XmuScanline *)NULL;
+ return (dst);
+ }
+ z = p = dst->scanline;
+ Z = P = src->scanline;
+ top = XmuNewScanline(dst->scanline->y, 0, 0);
+ XmuScanlineCopy(top, dst->scanline);
+
+ while (z)
+ {
+ while (Z->next && Z->next->y < z->y)
+ {
+ P = Z;
+ Z = Z->next;
+ if (Z->y >= p->y)
+ {
+ XmuScanline *q = XmuNewScanline(Z->y, 0, 0);
+ XmuScanlineCopy(q, Z);
+
+ XmuScanlineAnd(q, top);
+ if (p->y != P->y)
+ {
+ XmuScanlineAnd(p, P);
+ p->y = XmuMax(p->y, P->y);
+ }
+ p->next = q;
+ q->next = z;
+ p = q;
+ }
+ }
+ if (!z->next)
+ {
+ z->y = XmuMax(z->y, Z->y);
+ break;
+ }
+ while (Z->y >= z->next->y)
+ {
+ if (z == dst->scanline)
+ {
+ p = dst->scanline = dst->scanline->next;
+ XmuDestroyScanline(z);
+ z = dst->scanline;
+ }
+ else
+ {
+ p->next = z->next;
+ XmuDestroyScanline(z);
+ z = p;
+ }
+ if (!z || !z->next)
+ {
+ XmuOptimizeArea(dst);
+ XmuDestroyScanline(top);
+
+ return (dst);
+ }
+ }
+ if (Z->y > p->y)
+ z->y = XmuMax(z->y, Z->y);
+ if (top->y != z->y)
+ {
+ XmuScanlineCopy(top, z);
+ top->y = z->y;
+ }
+ XmuScanlineAnd(z, Z);
+ p = z;
+ z = z->next;
+ }
+ XmuOptimizeArea(dst);
+ XmuDestroyScanline(top);
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuValidArea(area)
+ *
+ * Parameters:
+ * area - area to verify
+ *
+ * Description:
+ * Verifies if the area is valid and/or useful
+ */
+Bool
+XmuValidArea(XmuArea *area)
+{
+ XmuScanline *at;
+
+ if (!area || !area->scanline)
+ return (False);
+
+ at = area->scanline;
+ while (at)
+ {
+ if (XmuValidScanline(at))
+ return (True);
+ at = at->next;
+ }
+
+ return (False);
+}
+
+/*
+ * Function:
+ * XmuValidScanline
+ *
+ * Parameters:
+ * scanline - scanline to verify
+ *
+ * Description:
+ * Verifies if a scanline is useful
+ */
+Bool
+XmuValidScanline(XmuScanline *scanline)
+{
+ XmuSegment *z;
+
+ if (!scanline)
+ return (False);
+
+ z = scanline->segment;
+ while (z)
+ {
+ if (XmuValidSegment(z))
+ return (True);
+ z = z->next;
+ }
+
+ return (False);
+}
+
+/*
+ * Function:
+ * XmuScanlineEqu
+ *
+ * Parameters:
+ * s1 - scanline 1
+ * s2 - scanline 2
+ *
+ * Description:
+ * Checks if s1 and s2 are equal
+ */
+Bool
+XmuScanlineEqu(XmuScanline *s1, XmuScanline *s2)
+{
+ XmuSegment *z, *Z;
+
+ if ((!s1 && !s2) || s1 == s2)
+ return (True);
+ if (!s1 || !s2)
+ return (False);
+
+ z = s1->segment;
+ Z = s2->segment;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ if (!z && !Z)
+ return (True);
+ if (!z || !Z)
+ return (False);
+ if (!XmuSegmentEqu(z, Z))
+ return (False);
+ z = z->next;
+ Z = Z->next;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * Function:
+ * XmuNewSegment
+ *
+ * Parameters:
+ * x1 - coordinates of the segment
+ * x2 - ""
+ *
+ * Description:
+ * Creates a new segments with the coordinates x1 and x2
+ *
+ * Returns:
+ * New Segment of NULL
+ */
+XmuSegment *
+XmuNewSegment(int x1, int x2)
+{
+ XmuSegment *segment;
+
+ if ((segment = (XmuSegment *)XtMalloc(sizeof(XmuSegment))) == NULL)
+ return (segment);
+
+ segment->x1 = x1;
+ segment->x2 = x2;
+ segment->next = (XmuSegment *)NULL;
+
+ return (segment);
+}
+
+/*
+ * Function:
+ * XmuDestroySegmentList
+ *
+ * Parameters:
+ * segment - Segment to destroy
+ *
+ * Description:
+ * Frees the memory used by the list headed by segment
+ */
+void
+XmuDestroySegmentList(XmuSegment *segment)
+{
+ XmuSegment *z;
+
+ if (!segment)
+ return;
+
+ while (segment)
+ {
+ z = segment;
+ segment = segment->next;
+ XmuDestroySegment(z);
+ }
+}
+
+/*
+ * Function:
+ * XmuScanlineCopy
+ *
+ * Parameters:
+ * dst - destination scanline
+ * src - source scanline
+ *
+ * Description:
+ * Makes dst contain the same data as src
+ */
+XmuScanline *
+XmuScanlineCopy(XmuScanline *dst, XmuScanline *src)
+{
+ XmuSegment *z, *p, *Z;
+
+ if (!dst || !src || dst == src)
+ return (dst);
+
+ z = p = dst->segment;
+ Z = src->segment;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ if (!Z)
+ {
+ if (z == dst->segment)
+ dst->segment = (XmuSegment *)NULL;
+ else
+ p->next = (XmuSegment *)NULL;
+ XmuDestroySegmentList(z);
+ return (dst);
+ }
+ if (z)
+ {
+ z->x1 = Z->x1;
+ z->x2 = Z->x2;
+ }
+ else
+ {
+ z = XmuNewSegment(Z->x1, Z->x2);
+ if (p == dst->segment && !dst->segment)
+ p = dst->segment = z;
+ else
+ p->next = z;
+ }
+ p = z;
+ z = z->next;
+ Z = Z->next;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * Function:
+ * XmuAppendSegment
+ *
+ * Parameters:
+ * segment - destination segment
+ * append - segment to add
+ *
+ * Description:
+ * Adds a copy of the append list at the end of the segment list
+ */
+Bool
+XmuAppendSegment(XmuSegment *segment, XmuSegment *append)
+{
+ if (!segment || !append)
+ return (False);
+
+ if (segment->next)
+ /* Should not happen! */
+ XmuDestroySegmentList(segment->next);
+
+ while (append)
+ {
+ if (XmuValidSegment(append))
+ {
+ if ((segment->next = XmuNewSegment(append->x1, append->x2)) == NULL)
+ return (False);
+ segment = segment->next;
+ }
+ append = append->next;
+ }
+
+ return (True);
+}
+
+/*
+ * Function:
+ * XmuOptimizeScanline
+ *
+ * Parameters:
+ * scanline - scanline to optimize
+ *
+ * Description:
+ * Some functions, when transforming Segments of Scanlines, left these
+ * with unnecessary data (that may cause error in these same functions).
+ * This function corrects these incorrect segments.
+ */
+XmuScanline *
+XmuOptimizeScanline(XmuScanline *scanline)
+{
+ XmuSegment *z, *p;
+
+ while (scanline->segment && !XmuValidSegment(scanline->segment))
+ {
+ XmuSegment *s = scanline->segment;
+
+ scanline->segment = scanline->segment->next;
+ XmuDestroySegment(s);
+ }
+ for (z = p = scanline->segment; z; p = z, z = z->next)
+ {
+ if (!XmuValidSegment(z))
+ {
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ }
+ }
+ return (scanline);
+}
+
+/*
+ * Name:
+ * XmuScanlineNot(scanline, minx, maxx)
+ *
+ * Parameters:
+ * scanline - scanlines operate
+ * minx - minimum x coordinate
+ * maxx - maximum x coordinate
+ *
+ * Description:
+ * (minx) (maxx)
+ * + +
+ * (input) +---------+ +--------+ +--------+
+ * (output) +-----+ +-----+ +--------+ +------------+
+ */
+XmuScanline *
+XmuScanlineNot(XmuScanline *scanline, int minx, int maxx)
+{
+ XmuSegment *z;
+ static XmuSegment x = { 0, 0, NULL };
+ static XmuScanline and = { 0, &x, NULL };
+
+ if (!scanline)
+ return (scanline);
+
+ XmuOptimizeScanline(scanline);
+ if (minx > maxx)
+ {
+ minx ^= maxx; maxx ^= minx; minx ^= maxx;
+ }
+ and.segment->x1 = minx;
+ and.segment->x2 = maxx;
+ XmuScanlineAnd(scanline, &and);
+ if (!scanline->segment)
+ {
+ scanline->segment = XmuNewSegment(minx, maxx);
+ return (scanline);
+ }
+ z = scanline->segment;
+ if (z->x1 != minx)
+ {
+ XmuSegment *q = XmuNewSegment(minx, z->x1);
+
+ q->next = z;
+ scanline->segment = q;
+ }
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ z->x1 = z->x2;
+ if (!z->next)
+ {
+ z->x2 = maxx;
+ break;
+ }
+ z->x2 = z->next->x1;
+ if (z->next->x2 == maxx)
+ {
+ XmuDestroySegment(z->next);
+ z->next = (XmuSegment *)NULL;
+ break;
+ }
+ z = z->next;
+ }
+
+ return (scanline);
+}
+
+
+#ifndef notdef
+/*
+ * Function:
+ * XmuScanlineOrSegment
+ *
+ * Parameters:
+ * dst - destionation scanline
+ * src - source segment
+ *
+ * Description:
+ * (input) +-----------+ +--------+ +---------+
+ * (src) +-------------------+
+ * (output) +-------------------------+ +---------+
+ */
+XmuScanline *
+XmuScanlineOrSegment(XmuScanline *dst, XmuSegment *src)
+{
+ XmuSegment *z, *p, ins;
+
+ if (!src || !dst || !XmuValidSegment(src))
+ return (dst);
+
+ if (!dst->segment)
+ {
+ dst->segment = XmuNewSegment(src->x1, src->x2);
+ return (dst);
+ }
+
+ z = p = dst->segment;
+ ins.x1 = src->x1;
+ ins.x2 = src->x2;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ if (!z)
+ {
+ XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
+
+ if (p == dst->segment && z == p)
+ dst->segment = q;
+ else
+ p->next = q;
+ break;
+ }
+ else if (ins.x2 < z->x1)
+ {
+ XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
+
+ if (p == dst->segment && z == p)
+ {
+ q->next = dst->segment;
+ dst->segment = q;
+ }
+ else
+ {
+ p->next = q;
+ q->next = z;
+ }
+ break;
+ }
+ else if (ins.x2 <= z->x2)
+ {
+ z->x1 = XmuMin(z->x1, ins.x1);
+ break;
+ }
+ else if (ins.x1 <= z->x2)
+ {
+ ins.x1 = XmuMin(z->x1, ins.x1);
+ if (!z->next)
+ {
+ z->x1 = ins.x1;
+ z->x2 = ins.x2;
+ break;
+ }
+ else
+ {
+ if (z == dst->segment)
+ {
+ p = dst->segment = dst->segment->next;
+ XmuDestroySegment(z);
+ z = dst->segment;
+ continue;
+ }
+ else
+ {
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ }
+ }
+ }
+ p = z;
+ z = z->next;
+ }
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuScanlineAndSegment
+ *
+ * Parameters:
+ * dst - destination scanline
+ * src - source segment
+ *
+ * Description:
+ * (input) +------------+ +------+ +----------+
+ * (src) +---------------------+
+ * (output) +-------+ +------+
+ */
+XmuScanline *
+XmuScanlineAndSegment(XmuScanline *dst, XmuSegment *src)
+{
+ XmuSegment *z, *p;
+
+ if (!dst || !src)
+ return (dst);
+
+ if (!XmuValidSegment(src))
+ {
+ XmuDestroySegmentList(dst->segment);
+ dst->segment = (XmuSegment *)NULL;
+ return (dst);
+ }
+ if (!dst->segment)
+ return (dst);
+
+ z = p = dst->segment;
+ while (z)
+ {
+ if (src->x2 <= z->x1 || src->x1 >= z->x2)
+ {
+ if (z == dst->segment)
+ {
+ p = dst->segment = dst->segment->next;
+ XmuDestroySegment(z);
+ z = dst->segment;
+ continue;
+ }
+ else
+ {
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ }
+ }
+ else
+ {
+ z->x1 = XmuMax(z->x1, src->x1);
+ z->x2 = XmuMin(z->x2, src->x2);
+ }
+ p = z;
+ z = z->next;
+ }
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuScanlineXorSegment
+ *
+ * Parameters:
+ * dst - destionation scanline
+ * src - source segment
+ *
+ * Descriptipn:
+ * (input) +------------+ +----------+ +-----------+
+ * (src) +------------------------+
+ * (output) +---+ +--+ +-+ +-----------+
+ */
+XmuScanline *
+XmuScanlineXorSegment(XmuScanline *dst, XmuSegment *src)
+{
+ XmuSegment *p, *z, ins;
+ int tmp1, tmp2;
+
+ if (!dst || !src || !XmuValidSegment(src))
+ return (dst);
+ if (!dst->segment)
+ {
+ dst->segment = XmuNewSegment(src->x1, src->x2);
+ return (dst);
+ }
+
+ p = z = dst->segment;
+ ins.x1 = src->x1;
+ ins.x2 = src->x2;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ if (!XmuValidSegment((&ins)))
+ break;
+ if (!z || ins.x2 < z->x1)
+ {
+ XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
+
+ q->next = z;
+ if (z == dst->segment)
+ dst->segment = q;
+ else
+ p->next = q;
+ break;
+ }
+ else if (ins.x2 == z->x1)
+ {
+ z->x1 = ins.x1;
+ break;
+ }
+ else if (ins.x1 < z->x2)
+ {
+ if (ins.x1 < z->x1)
+ {
+ tmp1 = ins.x2;
+ tmp2 = z->x2;
+ ins.x2 = XmuMax(ins.x2, z->x2);
+ z->x2 = z->x1;
+ z->x1 = ins.x1;
+ ins.x1 = XmuMin(tmp1, tmp2);
+ }
+ else if (ins.x1 > z->x1)
+ {
+ tmp1 = ins.x1;
+ ins.x1 = XmuMin(ins.x2, z->x2);
+ ins.x2 = XmuMax(z->x2, ins.x2);
+ z->x2 = tmp1;
+ }
+ else /* ins.x1 == z->x1 */
+ {
+ if (ins.x2 < z->x2)
+ {
+ z->x1 = ins.x2;
+ break;
+ }
+ else
+ {
+ ins.x1 = z->x2;
+ if (z == dst->segment)
+ p = dst->segment = dst->segment->next;
+ else
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ continue;
+ }
+ }
+ }
+ else if (ins.x1 == z->x2)
+ {
+ ins.x1 = z->x1;
+ if (z == dst->segment)
+ p = dst->segment = dst->segment->next;
+ else
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ continue;
+ }
+ p = z;
+ z = z->next;
+ }
+
+ return (dst);
+}
+#endif /* notdef */
+
+/*
+ * Function:
+ * ScanlineOr
+ *
+ * Parameters:
+ * dst - destionation scanline
+ * src - source scanline
+ *
+ * Description:
+ * (input) +--------------+ +-----+ +----------+
+ * (src) +---------------------+ +-----------+
+ * (output) +-------------------------+ +----------------+
+ */
+XmuScanline *
+XmuScanlineOr(XmuScanline *dst, XmuScanline *src)
+{
+ XmuSegment *z, *p, *Z, ins;
+
+ if (!src || !src->segment || !dst || dst == src)
+ return (dst);
+ if (!dst->segment)
+ {
+ XmuScanlineCopy(dst, src);
+ return (dst);
+ }
+
+ z = p = dst->segment;
+ Z = src->segment;
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ while (!XmuValidSegment((&ins)))
+ {
+ if ((Z = Z->next) == (XmuSegment *)NULL)
+ return (dst);
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ }
+ if (!z)
+ {
+ XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
+
+ if (p == dst->segment && z == p)
+ dst->segment = p = q;
+ else
+ {
+ p->next = q;
+ p = q;
+ }
+ Z = Z->next;
+ XmuAppendSegment(p, Z);
+ break;
+ }
+ else if (ins.x2 < z->x1)
+ {
+ XmuSegment *r = XmuNewSegment(ins.x1, ins.x2);
+
+ if (p == dst->segment && z == p)
+ {
+ r->next = dst->segment;
+ dst->segment = p = r;
+ }
+ else
+ {
+ p->next = r;
+ r->next = z;
+ p = r;
+ }
+ Z = Z->next;
+ if (!Z)
+ break;
+ else
+ {
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ continue;
+ }
+ }
+ else if (ins.x2 <= z->x2)
+ {
+ z->x1 = XmuMin(z->x1, ins.x1);
+ Z = Z->next;
+ if (!Z)
+ break;
+ else
+ {
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ continue;
+ }
+ }
+ else if (ins.x1 <= z->x2)
+ {
+ ins.x1 = XmuMin(z->x1, ins.x1);
+ if (!z->next)
+ {
+ z->x1 = ins.x1;
+ z->x2 = ins.x2;
+ p = z;
+ Z = Z->next;
+ XmuAppendSegment(p, Z);
+ break;
+ }
+ else
+ {
+ if (z == dst->segment)
+ {
+ p = dst->segment = dst->segment->next;
+ XmuDestroySegment(z);
+ z = p;
+ continue;
+ }
+ else
+ {
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ }
+ }
+ }
+ p = z;
+ z = z->next;
+ }
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuScanlineAnd
+ *
+ * Parameters:
+ * dst - destination scanline
+ * src - source scanline
+ *
+ * Description:
+ * (input) +--------------+ +-----+ +----------+
+ * (src) +---------------------+ +-----------+
+ * (output) +----------+ +-----+ +-----+
+ */
+XmuScanline *
+XmuScanlineAnd(XmuScanline *dst, XmuScanline *src)
+{
+ XmuSegment *z, *p, *Z;
+
+ if (!dst || !src || dst == src || !dst->segment) {
+ return (dst);
+ }
+ if (!src->segment)
+ {
+ XmuDestroySegmentList(dst->segment);
+ dst->segment = (XmuSegment *)NULL;
+ return (dst);
+ }
+ z = p = dst->segment;
+ Z = src->segment;
+
+ while (z)
+ {
+ while (!XmuValidSegment(Z) || Z->x2 <= z->x1)
+ {
+ Z = Z->next;
+ if (!Z)
+ {
+ if (z == dst->segment)
+ dst->segment = (XmuSegment *)NULL;
+ else
+ p->next = (XmuSegment *)0;
+ XmuDestroySegmentList(z);
+ return (dst);
+ }
+ }
+ if (Z->x1 >= z->x2)
+ {
+ if (z == dst->segment)
+ {
+ p = dst->segment = dst->segment->next;
+ XmuDestroySegment(z);
+ z = dst->segment;
+ }
+ else
+ {
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p->next;
+ }
+ if (!z)
+ return (dst);
+ else
+ continue;
+ }
+ z->x1 = XmuMax(z->x1, Z->x1);
+ if (z->x2 > Z->x2)
+ {
+ if (Z->next)
+ {
+ XmuSegment *q = XmuNewSegment(Z->x2, z->x2);
+
+ q->next = z->next;
+ z->next = q;
+ }
+ z->x2 = Z->x2;
+ }
+ p = z;
+ z = z->next;
+ }
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * ScanlineXor
+ *
+ * Parameters:
+ * dst - destination scanline
+ * src - source scanline
+ *
+ * Description:
+ * (input) +--------------+ +-----+ +----------+
+ * (src) +---------------------+ +-----------+
+ * (output) +---+ +--+ +-+ +----+ +-----+
+ */
+XmuScanline *
+XmuScanlineXor(XmuScanline *dst, XmuScanline *src)
+{
+ XmuSegment *z, *p, *Z, ins;
+ int tmp1, tmp2;
+
+ if (!src || !dst || !src->segment)
+ return (dst);
+ if (src == dst)
+ {
+ XmuDestroySegmentList(dst->segment);
+ dst->segment = (XmuSegment *)NULL;
+ return (dst);
+ }
+ if (!dst->segment)
+ {
+ XmuScanlineCopy(dst, src);
+ return (dst);
+ }
+
+ z = p = dst->segment;
+ Z = src->segment;
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+
+ /*CONSTCOND*/
+ while (1)
+ {
+ while (!XmuValidSegment((&ins)))
+ {
+ if ((Z = Z->next) == (XmuSegment *)NULL)
+ return (dst);
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ }
+ if (!z)
+ {
+ XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
+
+ if (!dst->segment)
+ dst->segment = q;
+ else
+ p->next = q;
+ p = q;
+ Z = Z->next;
+ XmuAppendSegment(p, Z);
+ break;
+ }
+ else if (ins.x2 < z->x1)
+ {
+ XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
+
+ q->next = z;
+ if (z == dst->segment)
+ dst->segment = q;
+ else
+ p->next = q;
+ if ((Z = Z->next) == (XmuSegment *)NULL)
+ return (dst);
+
+ p = q;
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ continue;
+ }
+ else if (ins.x2 == z->x1)
+ {
+ z->x1 = ins.x1;
+ if ((Z = Z->next) == (XmuSegment *)NULL)
+ break;
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ continue;
+ }
+ else if (ins.x1 < z->x2)
+ {
+ if (ins.x1 == z->x1)
+ {
+ if (ins.x2 < z->x2)
+ {
+ z->x1 = ins.x2;
+ if ((Z = Z->next) == (XmuSegment *)NULL)
+ break;
+ ins.x1 = Z->x1;
+ ins.x2 = Z->x2;
+ continue;
+ }
+ else
+ {
+ ins.x1 = z->x2;
+ if (z == dst->segment)
+ p = dst->segment = dst->segment->next;
+ else
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ continue;
+ }
+ }
+ else
+ {
+ if (Z->x2 < z->x2)
+ {
+ XmuSegment *q = XmuNewSegment(XmuMin(ins.x1, z->x1),
+ XmuMax(z->x1, ins.x1));
+
+ q->next = z;
+ if (z == dst->segment)
+ dst->segment = q;
+ else
+ p->next = q;
+ ins.x1 = z->x2;
+ z->x1 = ins.x2;
+ p = q;
+ continue;
+ }
+ else
+ {
+ tmp1 = ins.x2;
+ tmp2 = z->x2;
+ ins.x2 = XmuMax(ins.x2, z->x2);
+ z->x2 = XmuMax(z->x1, ins.x1);
+ z->x1 = XmuMin(ins.x1, z->x1);
+ ins.x1 = XmuMin(tmp1, tmp2);
+ }
+ }
+ }
+ else if (ins.x1 == z->x2)
+ {
+ ins.x1 = z->x1;
+ if (z == dst->segment)
+ p = dst->segment = dst->segment->next;
+ else
+ p->next = z->next;
+ XmuDestroySegment(z);
+ z = p;
+ continue;
+ }
+ p = z;
+ z = z->next;
+ }
+
+ return (dst);
+}
+
+/*
+ * Function:
+ * XmuNewScanline
+ *
+ * Parameters:
+ * y - y coordinate
+ * x1 - left coordinate
+ * x2 - right coordinate
+ *
+ * Description:
+ * Creates a new Scanline
+ */
+XmuScanline *
+XmuNewScanline(int y, int x1, int x2)
+{
+ XmuScanline *scanline;
+
+ scanline = (XmuScanline *)XtMalloc(sizeof(XmuScanline));
+ scanline->y = y;
+ if (x1 < x2)
+ scanline->segment = XmuNewSegment(x1, x2);
+ else
+ scanline->segment = (XmuSegment *)NULL;
+
+ scanline->next = (XmuScanline *)NULL;
+
+ return (scanline);
+}
+
+/*
+ * Function:
+ * XmuDestroyScanlineList
+ *
+ * Parameters:
+ * scanline - scanline list to destroy
+ *
+ * Description:
+ * Destroy a scanline list
+ *
+ * Observation:
+ * Use as follow:
+ * XmuDestroyScanlineList(area->scanline);
+ * area->scanline = (XmuScanline *)NULL;
+ */
+void
+XmuDestroyScanlineList(XmuScanline *scanline)
+{
+ XmuScanline *z;
+
+ if (!scanline)
+ return;
+
+ while (scanline)
+ {
+ z = scanline;
+ scanline = scanline->next;
+ XmuDestroyScanline(z);
+ }
+}
+
+/*
+ * Function:
+ * XmuOptimizeArea
+ *
+ * Parameters:
+ * area - area to optimize
+ *
+ * Description:
+ * Optimizes an area. This function is called when finishing a
+ * operation between areas, since they can end with redundant data,
+ * and the algorithms for area combination waits a area with
+ * correct data (but can left unnecessary data in the area, to avoid
+ * to much paranoia tests).
+ */
+XmuArea *XmuOptimizeArea(XmuArea *area)
+{
+ XmuScanline *pr, *at;
+
+ if (!area || !area->scanline)
+ return (area);
+
+ if (!area->scanline->next)
+ {
+ XmuDestroyScanlineList(area->scanline);
+ area->scanline = (XmuScanline *)0;
+ return (area);
+ }
+
+ pr = area->scanline;
+ at = area->scanline->next;
+ while (area->scanline && (!XmuValidScanline(area->scanline)
+ || (area->scanline->next && area->scanline->y
+ >= area->scanline->next->y)))
+ {
+ area->scanline = area->scanline->next;
+ XmuDestroyScanline(pr);
+ pr = area->scanline;
+ if (pr)
+ at = pr->next;
+ }
+
+ for (; at; pr = at, at = at->next)
+ {
+ if (XmuScanlineEqu(at, pr)
+ || (!XmuValidScanline(at) && !XmuValidScanline(pr))
+ || (at->next && at->y >= at->next->y))
+ {
+ pr->next = at->next;
+ XmuDestroyScanline(at);
+ at = pr;
+ }
+ }
+ if (pr && XmuValidScanline(pr))
+ {
+ XmuDestroySegmentList(pr->segment);
+ pr->segment = (XmuSegment *)NULL;
+ }
+ if (area->scanline && !area->scanline->next)
+ {
+ XmuDestroyScanlineList(area->scanline);
+ area->scanline = (XmuScanline *)NULL;
+ }
+
+ return (area);
+}
|