Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright (c) 1998 by The XFree86 Project, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * SOFTWARE.
     21  *
     22  * Except as contained in this notice, the name of the XFree86 Project shall
     23  * not be used in advertising or otherwise to promote the sale, use or other
     24  * dealings in this Software without prior written authorization from the
     25  * XFree86 Project.
     26  */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include <config.h>
     30 #endif
     31 #include <stdlib.h>
     32 
     33 #include <X11/IntrinsicP.h>
     34 #include <X11/Xmu/Xmu.h>
     35 
     36 #define XmuMax(a, b)	((a) > (b) ? (a) : (b))
     37 #define XmuMin(a, b)	((a) < (b) ? (a) : (b))
     38 
     39 /*
     40  * Function:
     41  *	XmuNewArea
     42  *
     43  * Parameters:
     44  *	x1 - Coordinates of the rectangle
     45  *	y1 - ""
     46  *	x2 - ""
     47  *	y2 - ""
     48  *
     49  * Description:
     50  *	Creates a new rectangular clipping area
     51  */
     52 XmuArea *
     53 XmuNewArea(int x1, int y1, int x2, int y2)
     54 {
     55   XmuArea *area;
     56 
     57   area = (XmuArea *)XtMalloc(sizeof(XmuArea));
     58   if (x2 > x1 && y2 > y1)
     59     {
     60       area->scanline = XmuNewScanline(y1, x1, x2);
     61       area->scanline->next = XmuNewScanline(y2, 0, 0);
     62     }
     63   else
     64     area->scanline = (XmuScanline *)NULL;
     65 
     66   return (area);
     67 }
     68 
     69 /*
     70  * Function:
     71  *	XmuAreaDup
     72  *
     73  * Parameters:
     74  *	area - Area to copy
     75  *
     76  * Description:
     77  *	Returns a copy of its argument
     78  */
     79 XmuArea *
     80 XmuAreaDup(XmuArea *area)
     81 {
     82   XmuArea *dst;
     83 
     84   if (!area)
     85     return ((XmuArea *)NULL);
     86 
     87   dst = XmuCreateArea();
     88   XmuAreaCopy(dst, area);
     89   return (dst);
     90 }
     91 
     92 /*
     93  * Function:
     94  *	XmuAreaCopy
     95  *
     96  * Parameters:
     97  *	dst - destination area
     98  *	src - source area
     99  *
    100  * Description:
    101  *	Minimizes memory allocation, trying to use already allocated memory
    102  *	in dst, freeing what is not required anymore.
    103  */
    104 XmuArea *
    105 XmuAreaCopy(XmuArea *dst, XmuArea *src)
    106 {
    107   XmuScanline *z, *p, *Z;
    108 
    109   if (!dst || !src || dst == src)
    110     return (dst);
    111 
    112   z = p = dst->scanline;
    113   Z = src->scanline;
    114 
    115   /*CONSTCOND*/
    116   while (1)
    117     {
    118       if (!Z)
    119 	{
    120 	  if (z == dst->scanline)
    121 	    {
    122 	      XmuDestroyScanlineList(dst->scanline);
    123 	      dst->scanline = (XmuScanline *)NULL;
    124 	    }
    125 	  else
    126 	    {
    127 	      XmuDestroyScanlineList(p->next);
    128 	      p->next = (XmuScanline *)NULL;
    129 	    }
    130 	  return (dst);
    131 	}
    132       if (z)
    133 	{
    134 	  XmuScanlineCopy(z, Z);
    135 	  z->y = Z->y;
    136 	}
    137       else
    138 	{
    139 	  z = XmuNewScanline(Z->y, 0, 0);
    140 	  XmuScanlineCopy(z, Z);
    141 	  if (p == dst->scanline && !dst->scanline)
    142 	    p = dst->scanline = z;
    143 	  else
    144 	    p->next = z;
    145 	}
    146       p = z;
    147       z = z->next;
    148       Z = Z->next;
    149     }
    150 
    151   return (dst);
    152 }
    153 
    154 /*
    155  * Function:
    156  *   XmuAreaNot
    157  *
    158  * Parameters:
    159  *	area - area to operate
    160  *	x1   - retangle to clip the result against
    161  *	y1   - ""
    162  *	x2   - ""
    163  *	y2   - ""
    164  *
    165  * Description:
    166  * (Input)
    167  * (x1, y1)                                                (x2, y1)
    168  *                   +-------------+
    169  *      +------------+             +----+
    170  *      |                +--------------+
    171  *      +----------------+
    172  * (x1, y2)                                                (x2, y2)
    173  *
    174  * (Output)
    175  * (x1, y1)                                                (x2, y1)
    176  *    +--------------+             +--------------------------+
    177  *    | +------------+             +----+                     |
    178  *    | |                +--------------+                     |
    179  *    +-+                +------------------------------------+
    180  * (x1, y2)                                                (x2, y2)
    181  */
    182 XmuArea *
    183 XmuAreaNot(XmuArea *area, int x1, int y1, int x2, int y2)
    184 {
    185   XmuScanline *z;
    186   XmuArea *and;
    187 
    188   if (!area)
    189     return (area);
    190 
    191   if (x1 > x2)
    192     {
    193       x1 ^= x2; x2 ^= x1; x1 ^= x2;
    194     }
    195     if (y1 > y2)
    196       {
    197 	y1 ^= y2; y2 ^= y1; y1 ^= y2;
    198       }
    199     if (!area->scanline)
    200       {
    201 	if ((area->scanline = XmuNewScanline(y1, x1, x2)) != NULL)
    202 	  area->scanline->next = XmuNewScanline(y2, 0, 0);
    203 	return (area);
    204       }
    205     and = XmuNewArea(x1, y1, x2, y2);
    206     XmuAreaAnd(area, and);
    207     XmuDestroyArea(and);
    208     z = area->scanline;
    209     if (z->y != y1)
    210       {
    211 	XmuScanline *q = XmuNewScanline(y1, x1, x2);
    212 	q->next = z;
    213 	area->scanline = q;
    214       }
    215     else
    216       {
    217 	area->scanline = area->scanline->next;
    218 	XmuDestroyScanline(z);
    219 	XmuOptimizeArea(area);
    220 	if((z = area->scanline) == (XmuScanline *)NULL)
    221 	  return (area);
    222       }
    223 
    224     /* CONSTCOND */
    225     while (1)
    226       {
    227 	XmuScanlineNot(z, x1, x2);
    228 	if (!z->next)
    229 	  {
    230 	    z->next = XmuNewScanline(y2, 0, 0);
    231 	    break;
    232 	  }
    233 	if (z->next->y == y2)
    234 	  {
    235 	    XmuDestroyScanlineList(z->next);
    236 	    z->next = XmuNewScanline(y2, 0, 0);
    237 	    break;
    238 	  }
    239 	z = z->next;
    240       }
    241 
    242     return (area);
    243 }
    244 
    245 /*
    246  * Function:
    247  *	XmuAreaOrXor
    248  *
    249  * Parameters:
    250  *	dst - destination area
    251  *	src - source area
    252  *	or  - or operation if true, else xor operation
    253  *
    254  * Description:
    255  *	Executes Or (Union) or Xor (Reverse intersection) of the areas
    256  */
    257 XmuArea *
    258 XmuAreaOrXor(XmuArea *dst, XmuArea *src, Bool or)
    259 {
    260   XmuScanline *z, *p, *Z, *P, *ins, *top;
    261 
    262   if (!dst || !src)
    263     return (dst);
    264 
    265   if (dst == src)
    266     {
    267       if (or)
    268 	return (dst);
    269       XmuDestroyScanlineList(dst->scanline);
    270       dst->scanline = (XmuScanline *)NULL;
    271       return (dst);
    272     }
    273   if (!XmuValidArea(src))
    274     return (dst);
    275   if (!XmuValidArea(dst))
    276     {
    277       XmuAreaCopy(dst, src);
    278       return (dst);
    279     }
    280 
    281   p = z = dst->scanline;
    282   P = Z = src->scanline;
    283   ins = XmuNewScanline(dst->scanline->y, 0, 0);
    284   top = XmuNewScanline(dst->scanline->y, 0, 0);
    285   XmuScanlineCopy(ins, dst->scanline);
    286   XmuScanlineCopy(top, dst->scanline);
    287 
    288   /*CONSTCOND*/
    289   while (1)
    290     {
    291       if (!Z)
    292 	break;
    293       else if (Z->y < z->y)
    294 	{
    295 	  XmuScanline  *q = XmuNewScanline(Z->y, 0, 0);
    296 	  XmuScanlineCopy(q, Z);
    297 
    298 	  if (z == dst->scanline)
    299 	    {
    300 	      dst->scanline = p = q;
    301 	      q->next = z;
    302             }
    303 	  else
    304 	    {
    305 	      p->next = q;
    306 	      q->next = z;
    307 	      if (Z->y >= p->y)
    308 		{
    309 		  if (ins->y >= top->y
    310 		      && (p->y != P->y || !XmuScanlineEqu(p, P)
    311 			  || (ins->y <= P->y && !XmuScanlineEqu(ins, P))))
    312 		    {
    313 		      if (or)
    314 			XmuScanlineOr(q, ins);
    315 		      else
    316 			XmuScanlineXor(q, ins);
    317                     }
    318 		  else if (Z->y >= top->y
    319 			   && (top->y == p->y || top->y > ins->y
    320 			       || !XmuValidScanline(Z)
    321 			       || (p->y == P->y && XmuValidScanline(p)
    322 				   && XmuValidScanline(P))
    323 			       || XmuScanlineEqu(ins, top)))
    324 		    {
    325 		      if (or)
    326 			XmuScanlineOr(q, top);
    327 		      else
    328 			XmuScanlineXor(q, top);
    329 		    }
    330 		  if (ins->y != p->y && p->y != P->y)
    331 		    {
    332 		      XmuScanlineCopy(ins, p);
    333 		      ins->y = p->y;
    334 		    }
    335 		}
    336 	      if (!XmuValidScanline(p) || Z->y <= p->y)
    337 		{
    338 		  XmuScanlineCopy(top, p);
    339 		  top->y = p->y;
    340                 }
    341 	      p = q;
    342 	    }
    343 	  P = Z;
    344 	  Z = Z->next;
    345 	  continue;
    346         }
    347       else if (Z->y == z->y)
    348 	{
    349 	  if (top->y != z->y)
    350 	    {
    351 	      XmuScanlineCopy(top, z);
    352 	      top->y = z->y;
    353 	    }
    354 	  if (or)
    355 	    XmuScanlineOr(z, Z);
    356 	  else
    357 	    XmuScanlineXor(z, Z);
    358 	  P = Z;
    359 	  Z = Z->next;
    360 	}
    361       else if (P != Z)		/* && Z->y > z->y */
    362 	{
    363 	  if (top->y == ins->y && top->y != z->y)
    364 	    {
    365 	      XmuScanlineCopy(top, z);
    366 	      top->y = z->y;
    367 	    }
    368 	  if (ins->y != z->y)
    369 	    {
    370 	      XmuScanlineCopy(ins, z);
    371 	      ins->y = z->y;
    372 	    }
    373 	  if (or)
    374 	    XmuScanlineOr(z, P);
    375 	  else
    376 	    XmuScanlineXor(z, P);
    377 	}
    378       else if (ins->y != z->y)
    379 	{
    380 	  XmuScanlineCopy(ins, z);
    381 	  ins->y = z->y;
    382 	}
    383       p = z;
    384       z = z->next;
    385       if (!z)
    386 	{
    387 	  while (Z)
    388 	    {
    389 	      p->next = XmuNewScanline(Z->y, 0, 0);
    390 	      XmuScanlineCopy(p->next, Z);
    391 	      p = p->next;
    392 	      Z = Z->next;
    393 	    }
    394 	  break;
    395 	}
    396       else if (ins->y > top->y && !XmuValidScanline(z)
    397 	       && XmuValidScanline(ins))
    398 	{
    399 	  XmuScanlineCopy(top, ins);
    400 	  top->y = ins->y;
    401 	}
    402     }
    403   XmuOptimizeArea(dst);
    404   XmuDestroyScanline(ins);
    405   XmuDestroyScanline(top);
    406 
    407   return (dst);
    408 }
    409 
    410 /*
    411  * Function:
    412  *	XmuAreaAnd(dst, src)
    413  *
    414  * Parameters:
    415  *	dst - destination area
    416  *	src - source area
    417  *
    418  * Description:
    419  *	Executes And (intersection) of the areas
    420  */
    421 XmuArea *
    422 XmuAreaAnd(XmuArea *dst, XmuArea *src)
    423 {
    424   XmuScanline *z, *p, *Z, *P, *top;
    425 
    426   if (!dst || !src || dst == src)
    427     return (dst);
    428   if (!XmuValidArea(dst) || !XmuValidArea(src))
    429     {
    430       XmuDestroyScanlineList(dst->scanline);
    431       dst->scanline = (XmuScanline *)NULL;
    432       return (dst);
    433     }
    434   z = p = dst->scanline;
    435   Z = P = src->scanline;
    436   top = XmuNewScanline(dst->scanline->y, 0, 0);
    437   XmuScanlineCopy(top, dst->scanline);
    438 
    439   while (z)
    440     {
    441       while (Z->next && Z->next->y < z->y)
    442 	{
    443 	  P = Z;
    444 	  Z = Z->next;
    445 	  if (Z->y >= p->y)
    446 	    {
    447 	      XmuScanline *q = XmuNewScanline(Z->y, 0, 0);
    448 	      XmuScanlineCopy(q, Z);
    449 
    450 	      XmuScanlineAnd(q, top);
    451 	      if (p->y != P->y)
    452 		{
    453 		  XmuScanlineAnd(p, P);
    454 		  p->y = XmuMax(p->y, P->y);
    455 		}
    456 	      p->next = q;
    457 	      q->next = z;
    458 	      p = q;
    459 	    }
    460 	}
    461       if (!z->next)
    462 	{
    463 	  z->y = XmuMax(z->y, Z->y);
    464 	  break;
    465         }
    466       while (Z->y >= z->next->y)
    467 	{
    468 	  if (z == dst->scanline)
    469 	    {
    470 	      p = dst->scanline = dst->scanline->next;
    471 	      XmuDestroyScanline(z);
    472 	      z = dst->scanline;
    473 	    }
    474 	  else
    475 	    {
    476 	      p->next = z->next;
    477 	      XmuDestroyScanline(z);
    478 	      z = p;
    479 	    }
    480 	  if (!z || !z->next)
    481 	    {
    482 	      XmuOptimizeArea(dst);
    483 	      XmuDestroyScanline(top);
    484 
    485 	      return (dst);
    486 	    }
    487 	}
    488       if (Z->y > p->y)
    489 	z->y = XmuMax(z->y, Z->y);
    490       if (top->y != z->y)
    491 	{
    492 	  XmuScanlineCopy(top, z);
    493 	  top->y = z->y;
    494 	}
    495       XmuScanlineAnd(z, Z);
    496       p = z;
    497       z = z->next;
    498     }
    499   XmuOptimizeArea(dst);
    500   XmuDestroyScanline(top);
    501 
    502   return (dst);
    503 }
    504 
    505 /*
    506  * Function:
    507  *   XmuValidArea(area)
    508  *
    509  * Parameters:
    510  *	area - area to verify
    511  *
    512  * Description:
    513  *	Verifies if the area is valid and/or useful
    514  */
    515 Bool
    516 XmuValidArea(XmuArea *area)
    517 {
    518   XmuScanline *at;
    519 
    520   if (!area || !area->scanline)
    521     return (False);
    522 
    523   at = area->scanline;
    524   while (at)
    525     {
    526       if (XmuValidScanline(at))
    527 	return (True);
    528       at = at->next;
    529     }
    530 
    531   return (False);
    532 }
    533 
    534 /*
    535  * Function:
    536  *	XmuValidScanline
    537  *
    538  * Parameters:
    539  *	scanline - scanline to verify
    540  *
    541  * Description:
    542  *	Verifies if a scanline is useful
    543  */
    544 Bool
    545 XmuValidScanline(XmuScanline *scanline)
    546 {
    547   XmuSegment *z;
    548 
    549   if (!scanline)
    550     return (False);
    551 
    552   z = scanline->segment;
    553   while (z)
    554     {
    555       if (XmuValidSegment(z))
    556 	return (True);
    557       z = z->next;
    558     }
    559 
    560   return (False);
    561 }
    562 
    563 /*
    564  * Function:
    565  *   XmuScanlineEqu
    566  *
    567  * Parameters:
    568  *	s1 - scanline 1
    569  *	s2 - scanline 2
    570  *
    571  * Description:
    572  *	Checks if s1 and s2 are equal
    573  */
    574 Bool
    575 XmuScanlineEqu(XmuScanline *s1, XmuScanline *s2)
    576 {
    577   XmuSegment *z, *Z;
    578 
    579   if ((!s1 && !s2) || s1 == s2)
    580     return (True);
    581   if (!s1 || !s2)
    582     return (False);
    583 
    584   z = s1->segment;
    585   Z = s2->segment;
    586 
    587   /*CONSTCOND*/
    588   while (1)
    589     {
    590       if (!z && !Z)
    591 	return (True);
    592       if (!z || !Z)
    593 	return (False);
    594       if (!XmuSegmentEqu(z, Z))
    595 	return (False);
    596       z = z->next;
    597       Z = Z->next;
    598     }
    599   /*NOTREACHED*/
    600 }
    601 
    602 /*
    603  * Function:
    604  *	XmuNewSegment
    605  *
    606  * Parameters:
    607  *	x1 - coordinates of the segment
    608  *	x2 - ""
    609  *
    610  * Description:
    611  *	Creates a new segments with the coordinates x1 and x2
    612  *
    613  * Returns:
    614  *	New Segment of NULL
    615  */
    616 XmuSegment *
    617 XmuNewSegment(int x1, int x2)
    618 {
    619   XmuSegment *segment;
    620 
    621   if ((segment = (XmuSegment *)XtMalloc(sizeof(XmuSegment))) == NULL)
    622     return (segment);
    623 
    624   segment->x1 = x1;
    625   segment->x2 = x2;
    626   segment->next = (XmuSegment *)NULL;
    627 
    628   return (segment);
    629 }
    630 
    631 /*
    632  * Function:
    633  *	XmuDestroySegmentList
    634  *
    635  * Parameters:
    636  *	segment - Segment to destroy
    637  *
    638  * Description:
    639  *	Frees the memory used by the list headed by segment
    640  */
    641 void
    642 XmuDestroySegmentList(XmuSegment *segment)
    643 {
    644   XmuSegment *z;
    645 
    646   if (!segment)
    647     return;
    648 
    649   while (segment)
    650     {
    651       z = segment;
    652       segment = segment->next;
    653       XmuDestroySegment(z);
    654     }
    655 }
    656 
    657 /*
    658  * Function:
    659  *	XmuScanlineCopy
    660  *
    661  * Parameters:
    662  *	dst - destination scanline
    663  *	src - source scanline
    664  *
    665  * Description:
    666  *	Makes dst contain the same data as src
    667  */
    668 XmuScanline *
    669 XmuScanlineCopy(XmuScanline *dst, XmuScanline *src)
    670 {
    671   XmuSegment *z, *p, *Z;
    672 
    673   if (!dst || !src || dst == src)
    674     return (dst);
    675 
    676   z = p = dst->segment;
    677   Z = src->segment;
    678 
    679   /*CONSTCOND*/
    680   while (1)
    681     {
    682       if (!Z)
    683 	{
    684 	  if (z == dst->segment)
    685 	    dst->segment = (XmuSegment *)NULL;
    686 	  else
    687 	    p->next = (XmuSegment *)NULL;
    688 	  XmuDestroySegmentList(z);
    689 	  return (dst);
    690 	}
    691       if (z)
    692 	{
    693 	  z->x1 = Z->x1;
    694 	  z->x2 = Z->x2;
    695 	}
    696       else
    697 	{
    698 	  z = XmuNewSegment(Z->x1, Z->x2);
    699 	  if (p == dst->segment && !dst->segment)
    700 	    p = dst->segment = z;
    701 	  else
    702 	    p->next = z;
    703 	}
    704       p = z;
    705       z = z->next;
    706       Z = Z->next;
    707     }
    708   /*NOTREACHED*/
    709 }
    710 
    711 /*
    712  * Function:
    713  *	XmuAppendSegment
    714  *
    715  * Parameters:
    716  *	segment - destination segment
    717  *	append  - segment to add
    718  *
    719  * Description:
    720  *	Adds a copy of the append list at the end of the segment list
    721  */
    722 Bool
    723 XmuAppendSegment(XmuSegment *segment, XmuSegment *append)
    724 {
    725   if (!segment || !append)
    726     return (False);
    727 
    728   if (segment->next)
    729     /* Should not happen! */
    730     XmuDestroySegmentList(segment->next);
    731 
    732   while (append)
    733     {
    734       if (XmuValidSegment(append))
    735 	{
    736 	  if ((segment->next = XmuNewSegment(append->x1, append->x2)) == NULL)
    737 	    return (False);
    738 	  segment = segment->next;
    739 	}
    740       append = append->next;
    741     }
    742 
    743   return (True);
    744 }
    745 
    746 /*
    747  * Function:
    748  *	XmuOptimizeScanline
    749  *
    750  * Parameters:
    751  *	scanline - scanline to optimize
    752  *
    753  * Description:
    754  *	  Some functions, when transforming Segments of Scanlines, left these
    755  *	with unnecessary data (that may cause error in these same functions).
    756  *	  This function corrects these incorrect segments.
    757  */
    758 XmuScanline *
    759 XmuOptimizeScanline(XmuScanline *scanline)
    760 {
    761   XmuSegment *z, *p;
    762 
    763   while (scanline->segment && !XmuValidSegment(scanline->segment))
    764     {
    765       XmuSegment *s = scanline->segment;
    766 
    767       scanline->segment = scanline->segment->next;
    768       XmuDestroySegment(s);
    769     }
    770   for (z = p = scanline->segment; z; p = z, z = z->next)
    771     {
    772       if (!XmuValidSegment(z))
    773 	{
    774 	  p->next = z->next;
    775 	  XmuDestroySegment(z);
    776 	  z = p;
    777 	}
    778     }
    779   return (scanline);
    780 }
    781 
    782 /*
    783  * Name:
    784  *	XmuScanlineNot(scanline, minx, maxx)
    785  *
    786  * Parameters:
    787  *	scanline - scanlines operate
    788  *	minx	 - minimum x coordinate
    789  *	maxx	 - maximum x coordinate
    790  *
    791  * Description:
    792  *         (minx)                                                        (maxx)
    793  *           +                                                             +
    794  * (input)         +---------+     +--------+        +--------+
    795  * (output)  +-----+         +-----+        +--------+        +------------+
    796  */
    797 XmuScanline *
    798 XmuScanlineNot(XmuScanline *scanline, int minx, int maxx)
    799 {
    800   XmuSegment *z;
    801   static XmuSegment x = { 0, 0, NULL };
    802   static XmuScanline and = { 0, &x, NULL };
    803 
    804   if (!scanline)
    805     return (scanline);
    806 
    807   XmuOptimizeScanline(scanline);
    808   if (minx > maxx)
    809     {
    810       minx ^= maxx; maxx ^= minx; minx ^= maxx;
    811     }
    812   and.segment->x1 = minx;
    813   and.segment->x2 = maxx;
    814   XmuScanlineAnd(scanline, &and);
    815   if (!scanline->segment)
    816     {
    817       scanline->segment = XmuNewSegment(minx, maxx);
    818       return (scanline);
    819     }
    820   z = scanline->segment;
    821   if (z->x1 != minx)
    822     {
    823       XmuSegment *q = XmuNewSegment(minx, z->x1);
    824 
    825       q->next = z;
    826       scanline->segment = q;
    827     }
    828 
    829   /*CONSTCOND*/
    830   while (1)
    831     {
    832       z->x1 = z->x2;
    833       if (!z->next)
    834 	{
    835 	  z->x2 = maxx;
    836 	  break;
    837 	}
    838       z->x2 = z->next->x1;
    839       if (z->next->x2 == maxx)
    840 	{
    841 	  XmuDestroySegment(z->next);
    842 	  z->next = (XmuSegment *)NULL;
    843 	  break;
    844 	}
    845       z = z->next;
    846     }
    847 
    848   return (scanline);
    849 }
    850 
    851 
    852 #ifndef notdef
    853 /*
    854  * Function:
    855  *	XmuScanlineOrSegment
    856  *
    857  * Parameters:
    858  *	dst - destination scanline
    859  *	src - source segment
    860  *
    861  * Description:
    862  * (input)      +-----------+  +--------+    +---------+
    863  * (src)              +-------------------+
    864  * (output)     +-------------------------+  +---------+
    865  */
    866 XmuScanline *
    867 XmuScanlineOrSegment(XmuScanline *dst, XmuSegment *src)
    868 {
    869   XmuSegment *z, *p, ins;
    870 
    871   if (!src || !dst || !XmuValidSegment(src))
    872     return (dst);
    873 
    874   if (!dst->segment)
    875     {
    876       dst->segment = XmuNewSegment(src->x1, src->x2);
    877       return (dst);
    878     }
    879 
    880   z = p = dst->segment;
    881   ins.x1 = src->x1;
    882   ins.x2 = src->x2;
    883 
    884   /*CONSTCOND*/
    885   while (1)
    886     {
    887       if (!z)
    888 	{
    889             XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
    890 
    891 	    if (p == dst->segment && z == p)
    892 	      dst->segment = q;
    893 	    else
    894 	      p->next = q;
    895 	    break;
    896 	}
    897       else if (ins.x2 < z->x1)
    898 	{
    899 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
    900 
    901 	  if (p == dst->segment && z == p)
    902 	    {
    903 	      q->next = dst->segment;
    904 	      dst->segment = q;
    905 	    }
    906 	  else
    907 	    {
    908 	      p->next = q;
    909 	      q->next = z;
    910 	    }
    911 	  break;
    912         }
    913       else if (ins.x2 <= z->x2)
    914 	{
    915 	  z->x1 = XmuMin(z->x1, ins.x1);
    916 	  break;
    917 	}
    918       else if (ins.x1 <= z->x2)
    919 	{
    920 	  ins.x1 = XmuMin(z->x1, ins.x1);
    921 	  if (!z->next)
    922 	    {
    923 	      z->x1 = ins.x1;
    924 	      z->x2 = ins.x2;
    925 	      break;
    926 	    }
    927 	  else
    928 	    {
    929 	      if (z == dst->segment)
    930 		{
    931 		  p = dst->segment = dst->segment->next;
    932 		  XmuDestroySegment(z);
    933 		  z = dst->segment;
    934 		  continue;
    935 		}
    936 	      else
    937 		{
    938 		  p->next = z->next;
    939 		  XmuDestroySegment(z);
    940 		  z = p;
    941 		}
    942 	    }
    943 	}
    944       p = z;
    945       z = z->next;
    946     }
    947 
    948   return (dst);
    949 }
    950 
    951 /*
    952  * Function:
    953  *	XmuScanlineAndSegment
    954  *
    955  * Parameters:
    956  *	dst - destination scanline
    957  *	src - source segment
    958  *
    959  * Description:
    960  * (input)      +------------+   +------+     +----------+
    961  * (src)             +---------------------+
    962  * (output)          +-------+   +------+
    963  */
    964 XmuScanline *
    965 XmuScanlineAndSegment(XmuScanline *dst, XmuSegment *src)
    966 {
    967   XmuSegment *z, *p;
    968 
    969   if (!dst || !src)
    970     return (dst);
    971 
    972   if (!XmuValidSegment(src))
    973     {
    974       XmuDestroySegmentList(dst->segment);
    975       dst->segment = (XmuSegment *)NULL;
    976       return (dst);
    977     }
    978   if (!dst->segment)
    979     return (dst);
    980 
    981   z = p = dst->segment;
    982   while (z)
    983     {
    984       if (src->x2 <= z->x1 || src->x1 >= z->x2)
    985 	{
    986 	  if (z == dst->segment)
    987 	    {
    988 	      p = dst->segment = dst->segment->next;
    989 	      XmuDestroySegment(z);
    990 	      z = dst->segment;
    991 	      continue;
    992 	    }
    993 	  else
    994 	    {
    995 	      p->next = z->next;
    996 	      XmuDestroySegment(z);
    997 	      z = p;
    998 	    }
    999 	}
   1000       else
   1001 	{
   1002 	  z->x1 = XmuMax(z->x1, src->x1);
   1003 	  z->x2 = XmuMin(z->x2, src->x2);
   1004 	}
   1005       p = z;
   1006       z = z->next;
   1007     }
   1008 
   1009   return (dst);
   1010 }
   1011 
   1012 /*
   1013  * Function:
   1014  *	XmuScanlineXorSegment
   1015  *
   1016  * Parameters:
   1017  *	dst - destination scanline
   1018  *	src - source segment
   1019  *
   1020  * Description:
   1021  * (input)     +------------+  +----------+    +-----------+
   1022  * (src)           +------------------------+
   1023  * (output)    +---+        +--+          +-+  +-----------+
   1024  */
   1025 XmuScanline *
   1026 XmuScanlineXorSegment(XmuScanline *dst, XmuSegment *src)
   1027 {
   1028   XmuSegment *p, *z, ins;
   1029   int tmp1, tmp2;
   1030 
   1031   if (!dst || !src || !XmuValidSegment(src))
   1032     return (dst);
   1033   if (!dst->segment)
   1034     {
   1035       dst->segment = XmuNewSegment(src->x1, src->x2);
   1036       return (dst);
   1037     }
   1038 
   1039   p = z = dst->segment;
   1040   ins.x1 = src->x1;
   1041   ins.x2 = src->x2;
   1042 
   1043   /*CONSTCOND*/
   1044   while (1)
   1045     {
   1046       if (!XmuValidSegment((&ins)))
   1047 	break;
   1048       if (!z || ins.x2 < z->x1)
   1049 	{
   1050 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1051 
   1052 	  q->next = z;
   1053 	  if (z == dst->segment)
   1054 	    dst->segment = q;
   1055 	  else
   1056 	    p->next = q;
   1057 	  break;
   1058 	}
   1059       else if (ins.x2 == z->x1)
   1060 	{
   1061 	  z->x1 = ins.x1;
   1062 	  break;
   1063 	}
   1064       else if (ins.x1 < z->x2)
   1065 	{
   1066 	  if (ins.x1 < z->x1)
   1067 	    {
   1068 	      tmp1 = ins.x2;
   1069 	      tmp2 = z->x2;
   1070 	      ins.x2 = XmuMax(ins.x2, z->x2);
   1071 	      z->x2 = z->x1;
   1072 	      z->x1 = ins.x1;
   1073 	      ins.x1 = XmuMin(tmp1, tmp2);
   1074 	    }
   1075 	  else if (ins.x1 > z->x1)
   1076 	    {
   1077 	      tmp1 = ins.x1;
   1078 	      ins.x1 = XmuMin(ins.x2, z->x2);
   1079 	      ins.x2 = XmuMax(z->x2, ins.x2);
   1080 	      z->x2 = tmp1;
   1081 	    }
   1082 	  else	/* ins.x1 == z->x1 */
   1083 	    {
   1084 	      if (ins.x2 < z->x2)
   1085 		{
   1086 		  z->x1 = ins.x2;
   1087 		  break;
   1088 		}
   1089 	      else
   1090 		{
   1091 		  ins.x1 = z->x2;
   1092 		  if (z == dst->segment)
   1093 		    p = dst->segment = dst->segment->next;
   1094 		  else
   1095 		    p->next = z->next;
   1096 		  XmuDestroySegment(z);
   1097 		  z = p;
   1098 		  continue;
   1099 		}
   1100 	    }
   1101 	}
   1102       else if (ins.x1 == z->x2)
   1103 	{
   1104 	  ins.x1 = z->x1;
   1105 	  if (z == dst->segment)
   1106 	    p = dst->segment = dst->segment->next;
   1107 	  else
   1108 	    p->next = z->next;
   1109 	  XmuDestroySegment(z);
   1110 	  z = p;
   1111 	  continue;
   1112 	}
   1113       p = z;
   1114       z = z->next;
   1115     }
   1116 
   1117   return (dst);
   1118 }
   1119 #endif /* notdef */
   1120 
   1121 /*
   1122  * Function:
   1123  *	ScanlineOr
   1124  *
   1125  * Parameters:
   1126  *	dst - destination scanline
   1127  *	src - source scanline
   1128  *
   1129  * Description:
   1130  * (input)    +--------------+  +-----+    +----------+
   1131  * (src)          +---------------------+       +-----------+
   1132  * (output)   +-------------------------+  +----------------+
   1133  */
   1134 XmuScanline *
   1135 XmuScanlineOr(XmuScanline *dst, XmuScanline *src)
   1136 {
   1137   XmuSegment *z, *p, *Z, ins;
   1138 
   1139   if (!src || !src->segment || !dst || dst == src)
   1140     return (dst);
   1141   if (!dst->segment)
   1142     {
   1143       XmuScanlineCopy(dst, src);
   1144       return (dst);
   1145     }
   1146 
   1147   z = p = dst->segment;
   1148   Z = src->segment;
   1149   ins.x1 = Z->x1;
   1150   ins.x2 = Z->x2;
   1151 
   1152   /*CONSTCOND*/
   1153   while (1)
   1154     {
   1155       while (!XmuValidSegment((&ins)))
   1156 	{
   1157 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1158 	    return (dst);
   1159 	  ins.x1 = Z->x1;
   1160 	  ins.x2 = Z->x2;
   1161 	}
   1162         if (!z)
   1163 	  {
   1164             XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1165 
   1166             if (p == dst->segment && z == p)
   1167 	      dst->segment = p = q;
   1168             else
   1169 	      {
   1170 		p->next = q;
   1171 		p = q;
   1172 	      }
   1173 	    Z = Z->next;
   1174 	    XmuAppendSegment(p, Z);
   1175 	    break;
   1176 	  }
   1177         else if (ins.x2 < z->x1)
   1178 	  {
   1179 	    XmuSegment *r = XmuNewSegment(ins.x1, ins.x2);
   1180 
   1181 	    if (p == dst->segment && z == p)
   1182 	      {
   1183 		r->next = dst->segment;
   1184 		dst->segment = p = r;
   1185 	      }
   1186 	    else
   1187 	      {
   1188 		p->next = r;
   1189 		r->next = z;
   1190 		p = r;
   1191 	      }
   1192 	    Z = Z->next;
   1193             if (!Z)
   1194 	      break;
   1195             else
   1196 	      {
   1197 		ins.x1 = Z->x1;
   1198 		ins.x2 = Z->x2;
   1199 		continue;
   1200 	      }
   1201 	  }
   1202 	else if (ins.x2 <= z->x2)
   1203 	  {
   1204 	    z->x1 = XmuMin(z->x1, ins.x1);
   1205 	    Z = Z->next;
   1206 	    if (!Z)
   1207 	      break;
   1208             else
   1209 	      {
   1210 		ins.x1 = Z->x1;
   1211 		ins.x2 = Z->x2;
   1212 		continue;
   1213 	      }
   1214 	  }
   1215 	else if (ins.x1 <= z->x2)
   1216 	  {
   1217 	    ins.x1 = XmuMin(z->x1, ins.x1);
   1218 	    if (!z->next)
   1219 	      {
   1220 		z->x1 = ins.x1;
   1221 		z->x2 = ins.x2;
   1222 		p = z;
   1223 		Z = Z->next;
   1224 		XmuAppendSegment(p, Z);
   1225 		break;
   1226 	      }
   1227             else
   1228 	      {
   1229 		if (z == dst->segment)
   1230 		  {
   1231 		    p = dst->segment = dst->segment->next;
   1232 		    XmuDestroySegment(z);
   1233 		    z = p;
   1234 		    continue;
   1235 		  }
   1236                 else
   1237 		  {
   1238 		    p->next = z->next;
   1239 		    XmuDestroySegment(z);
   1240 		    z = p;
   1241 		  }
   1242 	      }
   1243 	  }
   1244 	p = z;
   1245 	z = z->next;
   1246     }
   1247 
   1248   return (dst);
   1249 }
   1250 
   1251 /*
   1252  * Function:
   1253  *	XmuScanlineAnd
   1254  *
   1255  * Parameters:
   1256  *	dst - destination scanline
   1257  *	src - source scanline
   1258  *
   1259  * Description:
   1260  * (input)    +--------------+  +-----+    +----------+
   1261  * (src)          +---------------------+       +-----------+
   1262  * (output)       +----------+  +-----+         +-----+
   1263  */
   1264 XmuScanline *
   1265 XmuScanlineAnd(XmuScanline *dst, XmuScanline *src)
   1266 {
   1267   XmuSegment  *z, *p, *Z;
   1268 
   1269   if (!dst || !src || dst == src || !dst->segment) {
   1270         return (dst);
   1271   }
   1272   if (!src->segment)
   1273     {
   1274       XmuDestroySegmentList(dst->segment);
   1275       dst->segment = (XmuSegment *)NULL;
   1276       return (dst);
   1277     }
   1278   z = p = dst->segment;
   1279   Z = src->segment;
   1280 
   1281   while (z)
   1282     {
   1283       while (!XmuValidSegment(Z) || Z->x2 <= z->x1)
   1284 	{
   1285 	  Z = Z->next;
   1286 	  if (!Z)
   1287 	    {
   1288 	      if (z == dst->segment)
   1289 		dst->segment = (XmuSegment *)NULL;
   1290 	      else
   1291 		p->next = (XmuSegment *)0;
   1292 	      XmuDestroySegmentList(z);
   1293 	      return (dst);
   1294 	    }
   1295 	}
   1296       if (Z->x1 >= z->x2)
   1297 	{
   1298 	  if (z == dst->segment)
   1299 	    {
   1300 	      p = dst->segment = dst->segment->next;
   1301 	      XmuDestroySegment(z);
   1302 	      z = dst->segment;
   1303 	    }
   1304 	  else
   1305 	    {
   1306 	      p->next = z->next;
   1307 	      XmuDestroySegment(z);
   1308 	      z = p->next;
   1309 	    }
   1310 	  if (!z)
   1311 	    return (dst);
   1312 	  else
   1313 	    continue;
   1314 	}
   1315         z->x1 = XmuMax(z->x1, Z->x1);
   1316 	if (z->x2 > Z->x2)
   1317 	  {
   1318             if (Z->next)
   1319 	      {
   1320                 XmuSegment *q = XmuNewSegment(Z->x2, z->x2);
   1321 
   1322 		q->next = z->next;
   1323 		z->next = q;
   1324 	      }
   1325 	    z->x2 = Z->x2;
   1326 	  }
   1327 	p = z;
   1328 	z = z->next;
   1329     }
   1330 
   1331   return (dst);
   1332 }
   1333 
   1334 /*
   1335  * Function:
   1336  *	ScanlineXor
   1337  *
   1338  * Parameters:
   1339  *	dst - destination scanline
   1340  *	src - source scanline
   1341  *
   1342  * Description:
   1343  * (input)    +--------------+  +-----+    +----------+
   1344  * (src)          +---------------------+       +-----------+
   1345  * (output)   +---+          +--+     +-+  +----+     +-----+
   1346  */
   1347 XmuScanline *
   1348 XmuScanlineXor(XmuScanline *dst, XmuScanline *src)
   1349 {
   1350   XmuSegment *z, *p, *Z, ins;
   1351   int tmp1, tmp2;
   1352 
   1353   if (!src || !dst || !src->segment)
   1354     return (dst);
   1355   if (src == dst)
   1356     {
   1357       XmuDestroySegmentList(dst->segment);
   1358       dst->segment = (XmuSegment *)NULL;
   1359       return (dst);
   1360     }
   1361   if (!dst->segment)
   1362     {
   1363       XmuScanlineCopy(dst, src);
   1364       return (dst);
   1365     }
   1366 
   1367   z = p = dst->segment;
   1368   Z = src->segment;
   1369   ins.x1 = Z->x1;
   1370   ins.x2 = Z->x2;
   1371 
   1372   /*CONSTCOND*/
   1373   while (1)
   1374     {
   1375       while (!XmuValidSegment((&ins)))
   1376 	{
   1377 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1378 	    return (dst);
   1379 	  ins.x1 = Z->x1;
   1380 	  ins.x2 = Z->x2;
   1381 	}
   1382       if (!z)
   1383 	{
   1384 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1385 
   1386             if (!dst->segment)
   1387 	      dst->segment = q;
   1388             else
   1389 	      p->next = q;
   1390 	    p = q;
   1391 	    Z = Z->next;
   1392 	    XmuAppendSegment(p, Z);
   1393 	    break;
   1394 	}
   1395       else if (ins.x2 < z->x1)
   1396 	{
   1397 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1398 
   1399 	  q->next = z;
   1400 	  if (z == dst->segment)
   1401 	    dst->segment = q;
   1402 	  else
   1403 	    p->next = q;
   1404 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1405 	    return (dst);
   1406 
   1407 	  p = q;
   1408 	  ins.x1 = Z->x1;
   1409 	  ins.x2 = Z->x2;
   1410 	  continue;
   1411 	}
   1412       else if (ins.x2 == z->x1)
   1413 	{
   1414 	  z->x1 = ins.x1;
   1415 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1416 	    break;
   1417 	  ins.x1 = Z->x1;
   1418 	  ins.x2 = Z->x2;
   1419 	  continue;
   1420 	}
   1421       else if (ins.x1 < z->x2)
   1422 	{
   1423 	  if (ins.x1 == z->x1)
   1424 	    {
   1425 	      if (ins.x2 < z->x2)
   1426 		{
   1427 		  z->x1 = ins.x2;
   1428 		  if ((Z = Z->next) == (XmuSegment *)NULL)
   1429 		    break;
   1430 		  ins.x1 = Z->x1;
   1431 		  ins.x2 = Z->x2;
   1432 		  continue;
   1433 		}
   1434 	      else
   1435 		{
   1436 		  ins.x1 = z->x2;
   1437 		  if (z == dst->segment)
   1438 		    p = dst->segment = dst->segment->next;
   1439 		  else
   1440 		    p->next = z->next;
   1441 		  XmuDestroySegment(z);
   1442 		  z = p;
   1443 		  continue;
   1444 		}
   1445 	    }
   1446 	  else
   1447 	    {
   1448 	      if (Z->x2 < z->x2)
   1449 		{
   1450 		  XmuSegment  *q = XmuNewSegment(XmuMin(ins.x1, z->x1),
   1451 						 XmuMax(z->x1, ins.x1));
   1452 
   1453 		  q->next = z;
   1454 		  if (z == dst->segment)
   1455 		    dst->segment = q;
   1456 		  else
   1457 		    p->next = q;
   1458 		  ins.x1 = z->x2;
   1459 		  z->x1 = ins.x2;
   1460 		  p = q;
   1461 		  continue;
   1462 		}
   1463 	      else
   1464 		{
   1465 		  tmp1 = ins.x2;
   1466 		  tmp2 = z->x2;
   1467 		  ins.x2 = XmuMax(ins.x2, z->x2);
   1468 		  z->x2 = XmuMax(z->x1, ins.x1);
   1469 		  z->x1 = XmuMin(ins.x1, z->x1);
   1470 		  ins.x1 = XmuMin(tmp1, tmp2);
   1471 		}
   1472 	    }
   1473 	}
   1474       else if (ins.x1 == z->x2)
   1475 	{
   1476 	  ins.x1 = z->x1;
   1477 	  if (z == dst->segment)
   1478 	    p = dst->segment = dst->segment->next;
   1479 	  else
   1480 	    p->next = z->next;
   1481 	  XmuDestroySegment(z);
   1482 	  z = p;
   1483 	  continue;
   1484 	}
   1485       p = z;
   1486       z = z->next;
   1487     }
   1488 
   1489   return (dst);
   1490 }
   1491 
   1492 /*
   1493  * Function:
   1494  *	XmuNewScanline
   1495  *
   1496  * Parameters:
   1497  *	y  - y coordinate
   1498  *	x1 - left coordinate
   1499  *	x2 - right coordinate
   1500  *
   1501  * Description:
   1502  *	Creates a new Scanline
   1503  */
   1504 XmuScanline *
   1505 XmuNewScanline(int y, int x1, int x2)
   1506 {
   1507   XmuScanline *scanline;
   1508 
   1509   scanline = (XmuScanline *)XtMalloc(sizeof(XmuScanline));
   1510   scanline->y = y;
   1511   if (x1 < x2)
   1512     scanline->segment = XmuNewSegment(x1, x2);
   1513   else
   1514     scanline->segment = (XmuSegment *)NULL;
   1515 
   1516   scanline->next = (XmuScanline *)NULL;
   1517 
   1518   return (scanline);
   1519 }
   1520 
   1521 /*
   1522  * Function:
   1523  *	XmuDestroyScanlineList
   1524  *
   1525  * Parameters:
   1526  *	scanline - scanline list to destroy
   1527  *
   1528  * Description:
   1529  *	Destroy a scanline list
   1530  *
   1531  * Observation:
   1532  *	Use as follow:
   1533  *	XmuDestroyScanlineList(area->scanline);
   1534  *	area->scanline = (XmuScanline *)NULL;
   1535  */
   1536 void
   1537 XmuDestroyScanlineList(XmuScanline *scanline)
   1538 {
   1539   XmuScanline *z;
   1540 
   1541   if (!scanline)
   1542     return;
   1543 
   1544   while (scanline)
   1545     {
   1546       z = scanline;
   1547       scanline = scanline->next;
   1548       XmuDestroyScanline(z);
   1549     }
   1550 }
   1551 
   1552 /*
   1553  * Function:
   1554  *	XmuOptimizeArea
   1555  *
   1556  * Parameters:
   1557  *	area - area to optimize
   1558  *
   1559  * Description:
   1560  *	  Optimizes an area. This function is called when finishing a
   1561  *	operation between areas, since they can end with redundant data,
   1562  *	and the algorithms for area combination waits a area with
   1563  *	correct data (but can left unnecessary data in the area, to avoid
   1564  *	to much paranoia tests).
   1565  */
   1566 XmuArea *XmuOptimizeArea(XmuArea *area)
   1567 {
   1568   XmuScanline *pr, *at;
   1569 
   1570   if (!area || !area->scanline)
   1571     return (area);
   1572 
   1573   if (!area->scanline->next)
   1574     {
   1575       XmuDestroyScanlineList(area->scanline);
   1576       area->scanline = (XmuScanline *)0;
   1577       return (area);
   1578     }
   1579 
   1580   pr = area->scanline;
   1581   at = area->scanline->next;
   1582   while (area->scanline && (!XmuValidScanline(area->scanline)
   1583 			    || (area->scanline->next && area->scanline->y
   1584 				>= area->scanline->next->y)))
   1585     {
   1586       area->scanline = area->scanline->next;
   1587       XmuDestroyScanline(pr);
   1588       pr = area->scanline;
   1589       if (pr)
   1590 	at = pr->next;
   1591     }
   1592 
   1593   for (; at; pr = at, at = at->next)
   1594     {
   1595       if (XmuScanlineEqu(at, pr)
   1596 	  || (!XmuValidScanline(at) && !XmuValidScanline(pr))
   1597 	  || (at->next && at->y >= at->next->y))
   1598 	{
   1599 	  pr->next = at->next;
   1600 	  XmuDestroyScanline(at);
   1601 	  at = pr;
   1602 	}
   1603     }
   1604   if (pr && XmuValidScanline(pr))
   1605     {
   1606       XmuDestroySegmentList(pr->segment);
   1607       pr->segment = (XmuSegment *)NULL;
   1608     }
   1609   if (area->scanline && !area->scanline->next)
   1610     {
   1611       XmuDestroyScanlineList(area->scanline);
   1612       area->scanline = (XmuScanline *)NULL;
   1613     }
   1614 
   1615   return (area);
   1616 }
   1617