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 /*
    853  * Function:
    854  *	XmuScanlineOrSegment
    855  *
    856  * Parameters:
    857  *	dst - destination scanline
    858  *	src - source segment
    859  *
    860  * Description:
    861  * (input)      +-----------+  +--------+    +---------+
    862  * (src)              +-------------------+
    863  * (output)     +-------------------------+  +---------+
    864  */
    865 XmuScanline *
    866 XmuScanlineOrSegment(XmuScanline *dst, XmuSegment *src)
    867 {
    868   XmuSegment *z, *p, ins;
    869 
    870   if (!src || !dst || !XmuValidSegment(src))
    871     return (dst);
    872 
    873   if (!dst->segment)
    874     {
    875       dst->segment = XmuNewSegment(src->x1, src->x2);
    876       return (dst);
    877     }
    878 
    879   z = p = dst->segment;
    880   ins.x1 = src->x1;
    881   ins.x2 = src->x2;
    882 
    883   /*CONSTCOND*/
    884   while (1)
    885     {
    886       if (!z)
    887 	{
    888             XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
    889 
    890 	    if (p == dst->segment && z == p)
    891 	      dst->segment = q;
    892 	    else
    893 	      p->next = q;
    894 	    break;
    895 	}
    896       else if (ins.x2 < z->x1)
    897 	{
    898 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
    899 
    900 	  if (p == dst->segment && z == p)
    901 	    {
    902 	      q->next = dst->segment;
    903 	      dst->segment = q;
    904 	    }
    905 	  else
    906 	    {
    907 	      p->next = q;
    908 	      q->next = z;
    909 	    }
    910 	  break;
    911         }
    912       else if (ins.x2 <= z->x2)
    913 	{
    914 	  z->x1 = XmuMin(z->x1, ins.x1);
    915 	  break;
    916 	}
    917       else if (ins.x1 <= z->x2)
    918 	{
    919 	  ins.x1 = XmuMin(z->x1, ins.x1);
    920 	  if (!z->next)
    921 	    {
    922 	      z->x1 = ins.x1;
    923 	      z->x2 = ins.x2;
    924 	      break;
    925 	    }
    926 	  else
    927 	    {
    928 	      if (z == dst->segment)
    929 		{
    930 		  p = dst->segment = dst->segment->next;
    931 		  XmuDestroySegment(z);
    932 		  z = dst->segment;
    933 		  continue;
    934 		}
    935 	      else
    936 		{
    937 		  p->next = z->next;
    938 		  XmuDestroySegment(z);
    939 		  z = p;
    940 		}
    941 	    }
    942 	}
    943       p = z;
    944       z = z->next;
    945     }
    946 
    947   return (dst);
    948 }
    949 
    950 /*
    951  * Function:
    952  *	XmuScanlineAndSegment
    953  *
    954  * Parameters:
    955  *	dst - destination scanline
    956  *	src - source segment
    957  *
    958  * Description:
    959  * (input)      +------------+   +------+     +----------+
    960  * (src)             +---------------------+
    961  * (output)          +-------+   +------+
    962  */
    963 XmuScanline *
    964 XmuScanlineAndSegment(XmuScanline *dst, XmuSegment *src)
    965 {
    966   XmuSegment *z, *p;
    967 
    968   if (!dst || !src)
    969     return (dst);
    970 
    971   if (!XmuValidSegment(src))
    972     {
    973       XmuDestroySegmentList(dst->segment);
    974       dst->segment = (XmuSegment *)NULL;
    975       return (dst);
    976     }
    977   if (!dst->segment)
    978     return (dst);
    979 
    980   z = p = dst->segment;
    981   while (z)
    982     {
    983       if (src->x2 <= z->x1 || src->x1 >= z->x2)
    984 	{
    985 	  if (z == dst->segment)
    986 	    {
    987 	      p = dst->segment = dst->segment->next;
    988 	      XmuDestroySegment(z);
    989 	      z = dst->segment;
    990 	      continue;
    991 	    }
    992 	  else
    993 	    {
    994 	      p->next = z->next;
    995 	      XmuDestroySegment(z);
    996 	      z = p;
    997 	    }
    998 	}
    999       else
   1000 	{
   1001 	  z->x1 = XmuMax(z->x1, src->x1);
   1002 	  z->x2 = XmuMin(z->x2, src->x2);
   1003 	}
   1004       p = z;
   1005       z = z->next;
   1006     }
   1007 
   1008   return (dst);
   1009 }
   1010 
   1011 /*
   1012  * Function:
   1013  *	XmuScanlineXorSegment
   1014  *
   1015  * Parameters:
   1016  *	dst - destination scanline
   1017  *	src - source segment
   1018  *
   1019  * Description:
   1020  * (input)     +------------+  +----------+    +-----------+
   1021  * (src)           +------------------------+
   1022  * (output)    +---+        +--+          +-+  +-----------+
   1023  */
   1024 XmuScanline *
   1025 XmuScanlineXorSegment(XmuScanline *dst, XmuSegment *src)
   1026 {
   1027   XmuSegment *p, *z, ins;
   1028   int tmp1, tmp2;
   1029 
   1030   if (!dst || !src || !XmuValidSegment(src))
   1031     return (dst);
   1032   if (!dst->segment)
   1033     {
   1034       dst->segment = XmuNewSegment(src->x1, src->x2);
   1035       return (dst);
   1036     }
   1037 
   1038   p = z = dst->segment;
   1039   ins.x1 = src->x1;
   1040   ins.x2 = src->x2;
   1041 
   1042   /*CONSTCOND*/
   1043   while (1)
   1044     {
   1045       if (!XmuValidSegment((&ins)))
   1046 	break;
   1047       if (!z || ins.x2 < z->x1)
   1048 	{
   1049 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1050 
   1051 	  q->next = z;
   1052 	  if (z == dst->segment)
   1053 	    dst->segment = q;
   1054 	  else
   1055 	    p->next = q;
   1056 	  break;
   1057 	}
   1058       else if (ins.x2 == z->x1)
   1059 	{
   1060 	  z->x1 = ins.x1;
   1061 	  break;
   1062 	}
   1063       else if (ins.x1 < z->x2)
   1064 	{
   1065 	  if (ins.x1 < z->x1)
   1066 	    {
   1067 	      tmp1 = ins.x2;
   1068 	      tmp2 = z->x2;
   1069 	      ins.x2 = XmuMax(ins.x2, z->x2);
   1070 	      z->x2 = z->x1;
   1071 	      z->x1 = ins.x1;
   1072 	      ins.x1 = XmuMin(tmp1, tmp2);
   1073 	    }
   1074 	  else if (ins.x1 > z->x1)
   1075 	    {
   1076 	      tmp1 = ins.x1;
   1077 	      ins.x1 = XmuMin(ins.x2, z->x2);
   1078 	      ins.x2 = XmuMax(z->x2, ins.x2);
   1079 	      z->x2 = tmp1;
   1080 	    }
   1081 	  else	/* ins.x1 == z->x1 */
   1082 	    {
   1083 	      if (ins.x2 < z->x2)
   1084 		{
   1085 		  z->x1 = ins.x2;
   1086 		  break;
   1087 		}
   1088 	      else
   1089 		{
   1090 		  ins.x1 = z->x2;
   1091 		  if (z == dst->segment)
   1092 		    p = dst->segment = dst->segment->next;
   1093 		  else
   1094 		    p->next = z->next;
   1095 		  XmuDestroySegment(z);
   1096 		  z = p;
   1097 		  continue;
   1098 		}
   1099 	    }
   1100 	}
   1101       else if (ins.x1 == z->x2)
   1102 	{
   1103 	  ins.x1 = z->x1;
   1104 	  if (z == dst->segment)
   1105 	    p = dst->segment = dst->segment->next;
   1106 	  else
   1107 	    p->next = z->next;
   1108 	  XmuDestroySegment(z);
   1109 	  z = p;
   1110 	  continue;
   1111 	}
   1112       p = z;
   1113       z = z->next;
   1114     }
   1115 
   1116   return (dst);
   1117 }
   1118 
   1119 /*
   1120  * Function:
   1121  *	ScanlineOr
   1122  *
   1123  * Parameters:
   1124  *	dst - destination scanline
   1125  *	src - source scanline
   1126  *
   1127  * Description:
   1128  * (input)    +--------------+  +-----+    +----------+
   1129  * (src)          +---------------------+       +-----------+
   1130  * (output)   +-------------------------+  +----------------+
   1131  */
   1132 XmuScanline *
   1133 XmuScanlineOr(XmuScanline *dst, XmuScanline *src)
   1134 {
   1135   XmuSegment *z, *p, *Z, ins;
   1136 
   1137   if (!src || !src->segment || !dst || dst == src)
   1138     return (dst);
   1139   if (!dst->segment)
   1140     {
   1141       XmuScanlineCopy(dst, src);
   1142       return (dst);
   1143     }
   1144 
   1145   z = p = dst->segment;
   1146   Z = src->segment;
   1147   ins.x1 = Z->x1;
   1148   ins.x2 = Z->x2;
   1149 
   1150   /*CONSTCOND*/
   1151   while (1)
   1152     {
   1153       while (!XmuValidSegment((&ins)))
   1154 	{
   1155 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1156 	    return (dst);
   1157 	  ins.x1 = Z->x1;
   1158 	  ins.x2 = Z->x2;
   1159 	}
   1160         if (!z)
   1161 	  {
   1162             XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1163 
   1164             if (p == dst->segment && z == p)
   1165 	      dst->segment = p = q;
   1166             else
   1167 	      {
   1168 		p->next = q;
   1169 		p = q;
   1170 	      }
   1171 	    Z = Z->next;
   1172 	    XmuAppendSegment(p, Z);
   1173 	    break;
   1174 	  }
   1175         else if (ins.x2 < z->x1)
   1176 	  {
   1177 	    XmuSegment *r = XmuNewSegment(ins.x1, ins.x2);
   1178 
   1179 	    if (p == dst->segment && z == p)
   1180 	      {
   1181 		r->next = dst->segment;
   1182 		dst->segment = p = r;
   1183 	      }
   1184 	    else
   1185 	      {
   1186 		p->next = r;
   1187 		r->next = z;
   1188 		p = r;
   1189 	      }
   1190 	    Z = Z->next;
   1191             if (!Z)
   1192 	      break;
   1193             else
   1194 	      {
   1195 		ins.x1 = Z->x1;
   1196 		ins.x2 = Z->x2;
   1197 		continue;
   1198 	      }
   1199 	  }
   1200 	else if (ins.x2 <= z->x2)
   1201 	  {
   1202 	    z->x1 = XmuMin(z->x1, ins.x1);
   1203 	    Z = Z->next;
   1204 	    if (!Z)
   1205 	      break;
   1206             else
   1207 	      {
   1208 		ins.x1 = Z->x1;
   1209 		ins.x2 = Z->x2;
   1210 		continue;
   1211 	      }
   1212 	  }
   1213 	else if (ins.x1 <= z->x2)
   1214 	  {
   1215 	    ins.x1 = XmuMin(z->x1, ins.x1);
   1216 	    if (!z->next)
   1217 	      {
   1218 		z->x1 = ins.x1;
   1219 		z->x2 = ins.x2;
   1220 		p = z;
   1221 		Z = Z->next;
   1222 		XmuAppendSegment(p, Z);
   1223 		break;
   1224 	      }
   1225             else
   1226 	      {
   1227 		if (z == dst->segment)
   1228 		  {
   1229 		    p = dst->segment = dst->segment->next;
   1230 		    XmuDestroySegment(z);
   1231 		    z = p;
   1232 		    continue;
   1233 		  }
   1234                 else
   1235 		  {
   1236 		    p->next = z->next;
   1237 		    XmuDestroySegment(z);
   1238 		    z = p;
   1239 		  }
   1240 	      }
   1241 	  }
   1242 	p = z;
   1243 	z = z->next;
   1244     }
   1245 
   1246   return (dst);
   1247 }
   1248 
   1249 /*
   1250  * Function:
   1251  *	XmuScanlineAnd
   1252  *
   1253  * Parameters:
   1254  *	dst - destination scanline
   1255  *	src - source scanline
   1256  *
   1257  * Description:
   1258  * (input)    +--------------+  +-----+    +----------+
   1259  * (src)          +---------------------+       +-----------+
   1260  * (output)       +----------+  +-----+         +-----+
   1261  */
   1262 XmuScanline *
   1263 XmuScanlineAnd(XmuScanline *dst, XmuScanline *src)
   1264 {
   1265   XmuSegment  *z, *p, *Z;
   1266 
   1267   if (!dst || !src || dst == src || !dst->segment) {
   1268         return (dst);
   1269   }
   1270   if (!src->segment)
   1271     {
   1272       XmuDestroySegmentList(dst->segment);
   1273       dst->segment = (XmuSegment *)NULL;
   1274       return (dst);
   1275     }
   1276   z = p = dst->segment;
   1277   Z = src->segment;
   1278 
   1279   while (z)
   1280     {
   1281       while (!XmuValidSegment(Z) || Z->x2 <= z->x1)
   1282 	{
   1283 	  Z = Z->next;
   1284 	  if (!Z)
   1285 	    {
   1286 	      if (z == dst->segment)
   1287 		dst->segment = (XmuSegment *)NULL;
   1288 	      else
   1289 		p->next = (XmuSegment *)0;
   1290 	      XmuDestroySegmentList(z);
   1291 	      return (dst);
   1292 	    }
   1293 	}
   1294       if (Z->x1 >= z->x2)
   1295 	{
   1296 	  if (z == dst->segment)
   1297 	    {
   1298 	      p = dst->segment = dst->segment->next;
   1299 	      XmuDestroySegment(z);
   1300 	      z = dst->segment;
   1301 	    }
   1302 	  else
   1303 	    {
   1304 	      p->next = z->next;
   1305 	      XmuDestroySegment(z);
   1306 	      z = p->next;
   1307 	    }
   1308 	  if (!z)
   1309 	    return (dst);
   1310 	  else
   1311 	    continue;
   1312 	}
   1313         z->x1 = XmuMax(z->x1, Z->x1);
   1314 	if (z->x2 > Z->x2)
   1315 	  {
   1316             if (Z->next)
   1317 	      {
   1318                 XmuSegment *q = XmuNewSegment(Z->x2, z->x2);
   1319 
   1320 		q->next = z->next;
   1321 		z->next = q;
   1322 	      }
   1323 	    z->x2 = Z->x2;
   1324 	  }
   1325 	p = z;
   1326 	z = z->next;
   1327     }
   1328 
   1329   return (dst);
   1330 }
   1331 
   1332 /*
   1333  * Function:
   1334  *	ScanlineXor
   1335  *
   1336  * Parameters:
   1337  *	dst - destination scanline
   1338  *	src - source scanline
   1339  *
   1340  * Description:
   1341  * (input)    +--------------+  +-----+    +----------+
   1342  * (src)          +---------------------+       +-----------+
   1343  * (output)   +---+          +--+     +-+  +----+     +-----+
   1344  */
   1345 XmuScanline *
   1346 XmuScanlineXor(XmuScanline *dst, XmuScanline *src)
   1347 {
   1348   XmuSegment *z, *p, *Z, ins;
   1349   int tmp1, tmp2;
   1350 
   1351   if (!src || !dst || !src->segment)
   1352     return (dst);
   1353   if (src == dst)
   1354     {
   1355       XmuDestroySegmentList(dst->segment);
   1356       dst->segment = (XmuSegment *)NULL;
   1357       return (dst);
   1358     }
   1359   if (!dst->segment)
   1360     {
   1361       XmuScanlineCopy(dst, src);
   1362       return (dst);
   1363     }
   1364 
   1365   z = p = dst->segment;
   1366   Z = src->segment;
   1367   ins.x1 = Z->x1;
   1368   ins.x2 = Z->x2;
   1369 
   1370   /*CONSTCOND*/
   1371   while (1)
   1372     {
   1373       while (!XmuValidSegment((&ins)))
   1374 	{
   1375 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1376 	    return (dst);
   1377 	  ins.x1 = Z->x1;
   1378 	  ins.x2 = Z->x2;
   1379 	}
   1380       if (!z)
   1381 	{
   1382 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1383 
   1384             if (!dst->segment)
   1385 	      dst->segment = q;
   1386             else
   1387 	      p->next = q;
   1388 	    p = q;
   1389 	    Z = Z->next;
   1390 	    XmuAppendSegment(p, Z);
   1391 	    break;
   1392 	}
   1393       else if (ins.x2 < z->x1)
   1394 	{
   1395 	  XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
   1396 
   1397 	  q->next = z;
   1398 	  if (z == dst->segment)
   1399 	    dst->segment = q;
   1400 	  else
   1401 	    p->next = q;
   1402 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1403 	    return (dst);
   1404 
   1405 	  p = q;
   1406 	  ins.x1 = Z->x1;
   1407 	  ins.x2 = Z->x2;
   1408 	  continue;
   1409 	}
   1410       else if (ins.x2 == z->x1)
   1411 	{
   1412 	  z->x1 = ins.x1;
   1413 	  if ((Z = Z->next) == (XmuSegment *)NULL)
   1414 	    break;
   1415 	  ins.x1 = Z->x1;
   1416 	  ins.x2 = Z->x2;
   1417 	  continue;
   1418 	}
   1419       else if (ins.x1 < z->x2)
   1420 	{
   1421 	  if (ins.x1 == z->x1)
   1422 	    {
   1423 	      if (ins.x2 < z->x2)
   1424 		{
   1425 		  z->x1 = ins.x2;
   1426 		  if ((Z = Z->next) == (XmuSegment *)NULL)
   1427 		    break;
   1428 		  ins.x1 = Z->x1;
   1429 		  ins.x2 = Z->x2;
   1430 		  continue;
   1431 		}
   1432 	      else
   1433 		{
   1434 		  ins.x1 = z->x2;
   1435 		  if (z == dst->segment)
   1436 		    p = dst->segment = dst->segment->next;
   1437 		  else
   1438 		    p->next = z->next;
   1439 		  XmuDestroySegment(z);
   1440 		  z = p;
   1441 		  continue;
   1442 		}
   1443 	    }
   1444 	  else
   1445 	    {
   1446 	      if (Z->x2 < z->x2)
   1447 		{
   1448 		  XmuSegment  *q = XmuNewSegment(XmuMin(ins.x1, z->x1),
   1449 						 XmuMax(z->x1, ins.x1));
   1450 
   1451 		  q->next = z;
   1452 		  if (z == dst->segment)
   1453 		    dst->segment = q;
   1454 		  else
   1455 		    p->next = q;
   1456 		  ins.x1 = z->x2;
   1457 		  z->x1 = ins.x2;
   1458 		  p = q;
   1459 		  continue;
   1460 		}
   1461 	      else
   1462 		{
   1463 		  tmp1 = ins.x2;
   1464 		  tmp2 = z->x2;
   1465 		  ins.x2 = XmuMax(ins.x2, z->x2);
   1466 		  z->x2 = XmuMax(z->x1, ins.x1);
   1467 		  z->x1 = XmuMin(ins.x1, z->x1);
   1468 		  ins.x1 = XmuMin(tmp1, tmp2);
   1469 		}
   1470 	    }
   1471 	}
   1472       else if (ins.x1 == z->x2)
   1473 	{
   1474 	  ins.x1 = z->x1;
   1475 	  if (z == dst->segment)
   1476 	    p = dst->segment = dst->segment->next;
   1477 	  else
   1478 	    p->next = z->next;
   1479 	  XmuDestroySegment(z);
   1480 	  z = p;
   1481 	  continue;
   1482 	}
   1483       p = z;
   1484       z = z->next;
   1485     }
   1486 
   1487   return (dst);
   1488 }
   1489 
   1490 /*
   1491  * Function:
   1492  *	XmuNewScanline
   1493  *
   1494  * Parameters:
   1495  *	y  - y coordinate
   1496  *	x1 - left coordinate
   1497  *	x2 - right coordinate
   1498  *
   1499  * Description:
   1500  *	Creates a new Scanline
   1501  */
   1502 XmuScanline *
   1503 XmuNewScanline(int y, int x1, int x2)
   1504 {
   1505   XmuScanline *scanline;
   1506 
   1507   scanline = (XmuScanline *)XtMalloc(sizeof(XmuScanline));
   1508   scanline->y = y;
   1509   if (x1 < x2)
   1510     scanline->segment = XmuNewSegment(x1, x2);
   1511   else
   1512     scanline->segment = (XmuSegment *)NULL;
   1513 
   1514   scanline->next = (XmuScanline *)NULL;
   1515 
   1516   return (scanline);
   1517 }
   1518 
   1519 /*
   1520  * Function:
   1521  *	XmuDestroyScanlineList
   1522  *
   1523  * Parameters:
   1524  *	scanline - scanline list to destroy
   1525  *
   1526  * Description:
   1527  *	Destroy a scanline list
   1528  *
   1529  * Observation:
   1530  *	Use as follow:
   1531  *	XmuDestroyScanlineList(area->scanline);
   1532  *	area->scanline = (XmuScanline *)NULL;
   1533  */
   1534 void
   1535 XmuDestroyScanlineList(XmuScanline *scanline)
   1536 {
   1537   XmuScanline *z;
   1538 
   1539   if (!scanline)
   1540     return;
   1541 
   1542   while (scanline)
   1543     {
   1544       z = scanline;
   1545       scanline = scanline->next;
   1546       XmuDestroyScanline(z);
   1547     }
   1548 }
   1549 
   1550 /*
   1551  * Function:
   1552  *	XmuOptimizeArea
   1553  *
   1554  * Parameters:
   1555  *	area - area to optimize
   1556  *
   1557  * Description:
   1558  *	  Optimizes an area. This function is called when finishing a
   1559  *	operation between areas, since they can end with redundant data,
   1560  *	and the algorithms for area combination waits a area with
   1561  *	correct data (but can left unnecessary data in the area, to avoid
   1562  *	to much paranoia tests).
   1563  */
   1564 XmuArea *XmuOptimizeArea(XmuArea *area)
   1565 {
   1566   XmuScanline *pr, *at;
   1567 
   1568   if (!area || !area->scanline)
   1569     return (area);
   1570 
   1571   if (!area->scanline->next)
   1572     {
   1573       XmuDestroyScanlineList(area->scanline);
   1574       area->scanline = (XmuScanline *)0;
   1575       return (area);
   1576     }
   1577 
   1578   pr = area->scanline;
   1579   at = area->scanline->next;
   1580   while (area->scanline && (!XmuValidScanline(area->scanline)
   1581 			    || (area->scanline->next && area->scanline->y
   1582 				>= area->scanline->next->y)))
   1583     {
   1584       area->scanline = area->scanline->next;
   1585       XmuDestroyScanline(pr);
   1586       pr = area->scanline;
   1587       if (pr)
   1588 	at = pr->next;
   1589     }
   1590 
   1591   for (; at; pr = at, at = at->next)
   1592     {
   1593       if (XmuScanlineEqu(at, pr)
   1594 	  || (!XmuValidScanline(at) && !XmuValidScanline(pr))
   1595 	  || (at->next && at->y >= at->next->y))
   1596 	{
   1597 	  pr->next = at->next;
   1598 	  XmuDestroyScanline(at);
   1599 	  at = pr;
   1600 	}
   1601     }
   1602   if (pr && XmuValidScanline(pr))
   1603     {
   1604       XmuDestroySegmentList(pr->segment);
   1605       pr->segment = (XmuSegment *)NULL;
   1606     }
   1607   if (area->scanline && !area->scanline->next)
   1608     {
   1609       XmuDestroyScanlineList(area->scanline);
   1610       area->scanline = (XmuScanline *)NULL;
   1611     }
   1612 
   1613   return (area);
   1614 }
   1615