Clip.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1998 by The XFree86 Project, Inc.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00017  * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00018  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00019  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00020  * SOFTWARE.
00021  *
00022  * Except as contained in this notice, the name of the XFree86 Project shall
00023  * not be used in advertising or otherwise to promote the sale, use or other
00024  * dealings in this Software without prior written authorization from the
00025  * XFree86 Project.
00026  */
00027 /* $XFree86: xc/lib/Xmu/Clip.c,v 1.1 1998/08/16 10:25:03 dawes Exp $ */
00028 
00029 #include <stdlib.h>
00030 
00031 #include <X11/IntrinsicP.h>
00032 #include <X11/Xmu/Xmu.h>
00033 
00034 #define XmuMax(a, b)    ((a) > (b) ? (a) : (b))
00035 #define XmuMin(a, b)    ((a) < (b) ? (a) : (b))
00036 
00037 /*
00038  * Function:
00039  *      XmuNewArea
00040  *
00041  * Parameters:
00042  *      x1 - Coordinates of the rectangle
00043  *      y1 - ""
00044  *      x2 - ""
00045  *      y2 - ""
00046  *
00047  * Description:
00048  *      Creates a new rectangular clipping area
00049  */
00050 XmuArea *
00051 XmuNewArea(int x1, int y1, int x2, int y2)
00052 {
00053   XmuArea *area;
00054 
00055   area = (XmuArea *)XtMalloc(sizeof(XmuArea));
00056   if (x2 > x1 && y2 > y1)
00057     {
00058       area->scanline = XmuNewScanline(y1, x1, x2);
00059       area->scanline->next = XmuNewScanline(y2, 0, 0);
00060     }
00061   else
00062     area->scanline = (XmuScanline *)NULL;
00063 
00064   return (area);
00065 }
00066 
00067 /*
00068  * Function:
00069  *      XmuAreaDup
00070  *
00071  * Parameters:
00072  *      area - Area to copy
00073  *
00074  * Description:
00075  *      Returns a copy of its argument
00076  */
00077 XmuArea *
00078 XmuAreaDup(XmuArea *area)
00079 {
00080   XmuArea *dst;
00081 
00082   if (!area)
00083     return ((XmuArea *)NULL);
00084 
00085   dst = XmuCreateArea();
00086   XmuAreaCopy(dst, area);
00087   return (dst);
00088 }
00089 
00090 /*
00091  * Function:
00092  *      XmuAreaCopy
00093  *
00094  * Parameters:
00095  *      dst - destination area
00096  *      src - source area
00097  *
00098  * Description:
00099  *      Minimizes memory alocation, trying to use already alocated memory
00100  *      in dst, freeing what is not required anymore.
00101  */
00102 XmuArea *
00103 XmuAreaCopy(XmuArea *dst, XmuArea *src)
00104 {
00105   XmuScanline *z, *p, *Z;
00106 
00107   if (!dst || !src || dst == src)
00108     return (dst);
00109 
00110   z = p = dst->scanline;
00111   Z = src->scanline;
00112 
00113   /*CONSTCOND*/
00114   while (1)
00115     {
00116       if (!Z)
00117         {
00118           if (z == dst->scanline)
00119             {
00120               XmuDestroyScanlineList(dst->scanline);
00121               dst->scanline = (XmuScanline *)NULL;
00122             }
00123           else
00124             {
00125               XmuDestroyScanlineList(p->next);
00126               p->next = (XmuScanline *)NULL;
00127             }
00128           return (dst);
00129         }
00130       if (z)
00131         {
00132           XmuScanlineCopy(z, Z);
00133           z->y = Z->y;
00134         }
00135       else
00136         {
00137           z = XmuNewScanline(Z->y, 0, 0);
00138           XmuScanlineCopy(z, Z);
00139           if (p == dst->scanline && !dst->scanline)
00140             p = dst->scanline = z;
00141           else
00142             p->next = z;
00143         }
00144       p = z;
00145       z = z->next;
00146       Z = Z->next;
00147     }
00148 
00149   return (dst);
00150 }
00151 
00152 /*
00153  * Function:
00154  *   XmuAreaNot
00155  *
00156  * Parameters:
00157  *      area - area to operate
00158  *      x1   - retangle to clip the result against
00159  *      y1   - ""
00160  *      x2   - ""
00161  *      y2   - ""
00162  *
00163  * Description:
00164  * (Input)
00165  * (x1, y1)                                                (x2, y1)
00166  *                   +-------------+
00167  *      +------------+             +----+
00168  *      |                +--------------+
00169  *      +----------------+
00170  * (x1, y2)                                                (x2, y2)
00171  *
00172  * (Output)
00173  * (x1, y1)                                                (x2, y1)
00174  *    +--------------+             +--------------------------+
00175  *    | +------------+             +----+                     |
00176  *    | |                +--------------+                     |
00177  *    +-+                +------------------------------------+
00178  * (x1, y2)                                                (x2, y2)
00179  */
00180 XmuArea *
00181 XmuAreaNot(XmuArea *area, int x1, int y1, int x2, int y2)
00182 {
00183   XmuScanline *z;
00184   XmuArea *and;
00185 
00186   if (!area)
00187     return (area);
00188 
00189   if (x1 > x2)
00190     {
00191       x1 ^= x2; x2 ^= x1; x1 ^= x2;
00192     }
00193     if (y1 > y2)
00194       {
00195         y1 ^= y2; y2 ^= y1; y1 ^= y2;
00196       }
00197     if (!area->scanline)
00198       {
00199         if ((area->scanline = XmuNewScanline(y1, x1, x2)) != NULL)
00200           area->scanline->next = XmuNewScanline(y2, 0, 0);
00201         return (area);
00202       }
00203     and = XmuNewArea(x1, y1, x2, y2);
00204     XmuAreaAnd(area, and);
00205     XmuDestroyArea(and);
00206     z = area->scanline;
00207     if (z->y != y1)
00208       {
00209         XmuScanline *q = XmuNewScanline(y1, x1, x2);
00210         q->next = z;
00211         area->scanline = q;
00212       }
00213     else
00214       {
00215         area->scanline = area->scanline->next;
00216         XmuDestroyScanline(z);
00217         XmuOptimizeArea(area);
00218         if((z = area->scanline) == (XmuScanline *)NULL)
00219           return (area);
00220       }
00221 
00222     /* CONSTCOND */
00223     while (1)
00224       {
00225         XmuScanlineNot(z, x1, x2);
00226         if (!z->next)
00227           {
00228             z->next = XmuNewScanline(y2, 0, 0);
00229             break;
00230           }
00231         if (z->next->y == y2)
00232           {
00233             XmuDestroyScanlineList(z->next);
00234             z->next = XmuNewScanline(y2, 0, 0);
00235             break;
00236           }
00237         z = z->next;
00238       }
00239 
00240     return (area);
00241 }
00242 
00243 /*
00244  * Function:
00245  *      XmuAreaOrXor
00246  *
00247  * Parameters:
00248  *      dst - destination area
00249  *      src - source area
00250  *      or  - or operation if true, else xor operation
00251  *
00252  * Description:
00253  *      Executes Or (Union) or Xor (Reverse intesection) of the areas
00254  */
00255 XmuArea *
00256 XmuAreaOrXor(XmuArea *dst, XmuArea *src, Bool or)
00257 {
00258   XmuScanline *z, *p, *Z, *P, *ins, *top;
00259 
00260   if (!dst || !src)
00261     return (dst);
00262 
00263   if (dst == src)
00264     {
00265       if (or)
00266         return (dst);
00267       XmuDestroyScanlineList(dst->scanline);
00268       dst->scanline = (XmuScanline *)NULL;
00269       return (dst);
00270     }
00271   if (!XmuValidArea(src))
00272     return (dst);
00273   if (!XmuValidArea(dst))
00274     {
00275       XmuAreaCopy(dst, src);
00276       return (dst);
00277     }
00278 
00279   p = z = dst->scanline;
00280   P = Z = src->scanline;
00281   ins = XmuNewScanline(dst->scanline->y, 0, 0);
00282   top = XmuNewScanline(dst->scanline->y, 0, 0);
00283   XmuScanlineCopy(ins, dst->scanline);
00284   XmuScanlineCopy(top, dst->scanline);
00285 
00286   /*CONSTCOND*/
00287   while (1)
00288     {
00289       if (!Z)
00290         break;
00291       else if (Z->y < z->y)
00292         {
00293           XmuScanline  *q = XmuNewScanline(Z->y, 0, 0);
00294           XmuScanlineCopy(q, Z);
00295 
00296           if (z == dst->scanline)
00297             {
00298               dst->scanline = p = q;
00299               q->next = z;
00300             }
00301           else
00302             {
00303               p->next = q;
00304               q->next = z;
00305               if (Z->y >= p->y)
00306                 {
00307                   if (ins->y >= top->y
00308                       && (p->y != P->y || !XmuScanlineEqu(p, P)
00309                           || (ins->y <= P->y && !XmuScanlineEqu(ins, P))))
00310                     {
00311                       if (or)
00312                         XmuScanlineOr(q, ins);
00313                       else
00314                         XmuScanlineXor(q, ins);
00315                     }
00316                   else if (Z->y >= top->y
00317                            && (top->y == p->y || top->y > ins->y
00318                                || !XmuValidScanline(Z)
00319                                || (p->y == P->y && XmuValidScanline(p)
00320                                    && XmuValidScanline(P))
00321                                || XmuScanlineEqu(ins, top)))
00322                     {
00323                       if (or)
00324                         XmuScanlineOr(q, top);
00325                       else
00326                         XmuScanlineXor(q, top);
00327                     }
00328                   if (ins->y != p->y && p->y != P->y)
00329                     {
00330                       XmuScanlineCopy(ins, p);
00331                       ins->y = p->y;
00332                     }
00333                 }
00334               if (!XmuValidScanline(p) || Z->y <= p->y)
00335                 {
00336                   XmuScanlineCopy(top, p);
00337                   top->y = p->y;
00338                 }
00339               p = q;
00340             }
00341           P = Z;
00342           Z = Z->next;
00343           continue;
00344         }
00345       else if (Z->y == z->y)
00346         {
00347           if (top->y != z->y)
00348             {
00349               XmuScanlineCopy(top, z);
00350               top->y = z->y;
00351             }
00352           if (or)
00353             XmuScanlineOr(z, Z);
00354           else
00355             XmuScanlineXor(z, Z);
00356           P = Z;
00357           Z = Z->next;
00358         }
00359       else if (P != Z)          /* && Z->y > z->y */
00360         {
00361           if (top->y == ins->y && top->y != z->y)
00362             {
00363               XmuScanlineCopy(top, z);
00364               top->y = z->y;
00365             }
00366           if (ins->y != z->y)
00367             {
00368               XmuScanlineCopy(ins, z);
00369               ins->y = z->y;
00370             }
00371           if (or)
00372             XmuScanlineOr(z, P);
00373           else
00374             XmuScanlineXor(z, P);
00375         }
00376       else if (ins->y != z->y)
00377         {
00378           XmuScanlineCopy(ins, z);
00379           ins->y = z->y;
00380         }
00381       p = z;
00382       z = z->next;
00383       if (!z)
00384         {
00385           while (Z)
00386             {
00387               p->next = XmuNewScanline(Z->y, 0, 0);
00388               XmuScanlineCopy(p->next, Z);
00389               p = p->next;
00390               Z = Z->next;
00391             }
00392           break;
00393         }
00394       else if (ins->y > top->y && !XmuValidScanline(z)
00395                && XmuValidScanline(ins))
00396         {
00397           XmuScanlineCopy(top, ins);
00398           top->y = ins->y;
00399         }
00400     }
00401   XmuOptimizeArea(dst);
00402   XmuDestroyScanline(ins);
00403   XmuDestroyScanline(top);
00404 
00405   return (dst);
00406 }
00407 
00408 /*
00409  * Function:
00410  *      XmuAreaAnd(dst, src)
00411  *
00412  * Parameters:
00413  *      dst - destination area
00414  *      src - source area
00415  *
00416  * Description:
00417  *      Executes And (intersection) of the areas
00418  */
00419 XmuArea *
00420 XmuAreaAnd(XmuArea *dst, XmuArea *src)
00421 {
00422   XmuScanline *z, *p, *Z, *P, *top;
00423 
00424   if (!dst || !src || dst == src)
00425     return (dst);
00426   if (!XmuValidArea(dst) || !XmuValidArea(src))
00427     {
00428       XmuDestroyScanlineList(dst->scanline);
00429       dst->scanline = (XmuScanline *)NULL;
00430       return (dst);
00431     }
00432   z = p = dst->scanline;
00433   Z = P = src->scanline;
00434   top = XmuNewScanline(dst->scanline->y, 0, 0);
00435   XmuScanlineCopy(top, dst->scanline);
00436 
00437   while (z)
00438     {
00439       while (Z->next && Z->next->y < z->y)
00440         {
00441           P = Z;
00442           Z = Z->next;
00443           if (Z->y >= p->y)
00444             {
00445               XmuScanline *q = XmuNewScanline(Z->y, 0, 0); 
00446               XmuScanlineCopy(q, Z);
00447 
00448               XmuScanlineAnd(q, top);
00449               if (p->y != P->y)
00450                 {
00451                   XmuScanlineAnd(p, P);
00452                   p->y = XmuMax(p->y, P->y);
00453                 }
00454               p->next = q;
00455               q->next = z;
00456               p = q;
00457             }
00458         }
00459       if (!z->next)
00460         {
00461           z->y = XmuMax(z->y, Z->y);
00462           break;
00463         }
00464       while (Z->y >= z->next->y)
00465         {
00466           if (z == dst->scanline)
00467             {
00468               p = dst->scanline = dst->scanline->next;
00469               XmuDestroyScanline(z);
00470               z = dst->scanline;
00471             }
00472           else
00473             {
00474               p->next = z->next;
00475               XmuDestroyScanline(z);
00476               z = p;
00477             }
00478           if (!z || !z->next)
00479             {
00480               XmuOptimizeArea(dst);
00481               XmuDestroyScanline(top);
00482 
00483               return (dst);
00484             }
00485         }
00486       if (Z->y > p->y)
00487         z->y = XmuMax(z->y, Z->y);
00488       if (top->y != z->y)
00489         {
00490           XmuScanlineCopy(top, z);
00491           top->y = z->y;
00492         }
00493       XmuScanlineAnd(z, Z);
00494       p = z;
00495       z = z->next;
00496     }
00497   XmuOptimizeArea(dst);
00498   XmuDestroyScanline(top);
00499 
00500   return (dst);
00501 }
00502 
00503 /*
00504  * Function:
00505  *   XmuValidArea(area)
00506  *
00507  * Parameters:
00508  *      area - area to verify
00509  *
00510  * Description:
00511  *      Verifies if the area is valid and/or useful
00512  */
00513 Bool
00514 XmuValidArea(XmuArea *area)
00515 {
00516   XmuScanline *at;
00517 
00518   if (!area || !area->scanline)
00519     return (False);
00520 
00521   at = area->scanline;
00522   while (at)
00523     {
00524       if (XmuValidScanline(at))
00525         return (True);
00526       at = at->next;
00527     }
00528 
00529   return (False);
00530 }
00531 
00532 /*
00533  * Function:
00534  *      XmuValidScanline
00535  *
00536  * Parameters:
00537  *      scanline - scanline to verify
00538  *
00539  * Description:
00540  *      Verifies if a scanline is useful
00541  */
00542 Bool
00543 XmuValidScanline(XmuScanline *scanline)
00544 {
00545   XmuSegment *z;
00546 
00547   if (!scanline)
00548     return (False);
00549 
00550   z = scanline->segment;
00551   while (z)
00552     {
00553       if (XmuValidSegment(z))
00554         return (True);
00555       z = z->next;
00556     }
00557 
00558   return (False);
00559 }
00560 
00561 /*
00562  * Function:
00563  *   XmuScanlineEqu
00564  *
00565  * Parameters:
00566  *      s1 - scanline 1
00567  *      s2 - scanline 2
00568  *
00569  * Description:
00570  *      Checks if s1 and s2 are equal
00571  */
00572 Bool
00573 XmuScanlineEqu(XmuScanline *s1, XmuScanline *s2)
00574 {
00575   XmuSegment *z, *Z;
00576 
00577   if ((!s1 && !s2) || s1 == s2)
00578     return (True);
00579   if (!s1 || !s2)
00580     return (False);
00581 
00582   z = s1->segment;
00583   Z = s2->segment;
00584 
00585   /*CONSTCOND*/
00586   while (1)
00587     {
00588       if (!z && !Z)
00589         return (True);
00590       if (!z || !Z)
00591         return (False);
00592       if (!XmuSegmentEqu(z, Z))
00593         return (False);
00594       z = z->next;
00595       Z = Z->next;
00596     }
00597   /*NOTREACHED*/
00598 }
00599 
00600 /*
00601  * Function:
00602  *      XmuNewSegment
00603  *
00604  * Parameters:
00605  *      x1 - coordinates of the segment
00606  *      x2 - ""
00607  *
00608  * Description:
00609  *      Creates a new segments with the coordinates x1 and x2
00610  *
00611  * Returns:
00612  *      New Segment of NULL
00613  */
00614 XmuSegment *
00615 XmuNewSegment(int x1, int x2)
00616 {
00617   XmuSegment *segment;
00618 
00619   if ((segment = (XmuSegment *)XtMalloc(sizeof(XmuSegment))) == NULL)
00620     return (segment);
00621 
00622   segment->x1 = x1;
00623   segment->x2 = x2;
00624   segment->next = (XmuSegment *)NULL;
00625 
00626   return (segment);
00627 }
00628 
00629 /*
00630  * Function:
00631  *      XmuDestroySegmentList
00632  *
00633  * Parameters:
00634  *      segment - Segment to destroy
00635  *
00636  * Description:
00637  *      Frees the memory used by the list headed by segment
00638  */
00639 void
00640 XmuDestroySegmentList(XmuSegment *segment)
00641 {
00642   XmuSegment *z;
00643 
00644   if (!segment)
00645     return;
00646 
00647   while (segment)
00648     {
00649       z = segment;
00650       segment = segment->next;
00651       XmuDestroySegment(z);
00652     }
00653 }
00654 
00655 /*
00656  * Function:
00657  *      XmuScanlineCopy
00658  *
00659  * Parameters:
00660  *      dst - destination scanline
00661  *      src - source scanline
00662  *
00663  * Description:
00664  *      Makes dst contain the same data as src
00665  */
00666 XmuScanline *
00667 XmuScanlineCopy(XmuScanline *dst, XmuScanline *src)
00668 {
00669   XmuSegment *z, *p, *Z;
00670 
00671   if (!dst || !src || dst == src)
00672     return (dst);
00673 
00674   z = p = dst->segment;
00675   Z = src->segment;
00676 
00677   /*CONSTCOND*/
00678   while (1)
00679     {
00680       if (!Z)
00681         {
00682           if (z == dst->segment)
00683             dst->segment = (XmuSegment *)NULL;
00684           else
00685             p->next = (XmuSegment *)NULL;
00686           XmuDestroySegmentList(z);
00687           return (dst);
00688         }
00689       if (z)
00690         {
00691           z->x1 = Z->x1;
00692           z->x2 = Z->x2;
00693         }
00694       else
00695         {
00696           z = XmuNewSegment(Z->x1, Z->x2);
00697           if (p == dst->segment && !dst->segment)
00698             p = dst->segment = z;
00699           else
00700             p->next = z;
00701         }
00702       p = z;
00703       z = z->next;
00704       Z = Z->next;
00705     }
00706   /*NOTREACHED*/
00707 }
00708 
00709 /*
00710  * Function:
00711  *      XmuAppendSegment
00712  *
00713  * Parameters:
00714  *      segment - destination segment
00715  *      append  - segment to add
00716  *
00717  * Description:
00718  *      Adds a copy of the append list at the end of the segment list
00719  */
00720 Bool
00721 XmuAppendSegment(XmuSegment *segment, XmuSegment *append)
00722 {
00723   if (!segment || !append)
00724     return (False);
00725 
00726   if (segment->next)
00727     /* Should not happen! */
00728     XmuDestroySegmentList(segment->next);
00729 
00730   while (append)
00731     {
00732       if (XmuValidSegment(append))
00733         {
00734           if ((segment->next = XmuNewSegment(append->x1, append->x2)) == NULL)
00735             return (False);
00736           segment = segment->next;
00737         }
00738       append = append->next;
00739     }
00740 
00741   return (True);
00742 }
00743 
00744 /*
00745  * Function:
00746  *      XmuOptimizeScanline
00747  *
00748  * Parameters:
00749  *      scanline - scanline to optimize
00750  *
00751  * Description:
00752  *        Some functions, when transforming Segments of Scanlines, left these
00753  *      with unnecessary data (that may cause error in these same functions).
00754  *        This function corrects these incorrect segments.
00755  */
00756 XmuScanline *
00757 XmuOptimizeScanline(XmuScanline *scanline)
00758 {
00759   XmuSegment *z, *p;
00760 
00761   while (scanline->segment && !XmuValidSegment(scanline->segment))
00762     {
00763       XmuSegment *s = scanline->segment;
00764 
00765       scanline->segment = scanline->segment->next;
00766       XmuDestroySegment(s);
00767     }
00768   for (z = p = scanline->segment; z; p = z, z = z->next)
00769     {
00770       if (!XmuValidSegment(z))
00771         {
00772           p->next = z->next;
00773           XmuDestroySegment(z);
00774           z = p;
00775         }
00776     }
00777   return (scanline);
00778 }
00779 
00780 /*
00781  * Name:
00782  *      XmuScanlineNot(scanline, minx, maxx)
00783  *
00784  * Parameters:
00785  *      scanline - scanlines operate
00786  *      minx     - minimum x coordinate
00787  *      maxx     - maximum x coordinate
00788  *
00789  * Description:
00790  *         (minx)                                                        (maxx)
00791  *           +                                                             +
00792  * (input)         +---------+     +--------+        +--------+
00793  * (output)  +-----+         +-----+        +--------+        +------------+
00794  */
00795 XmuScanline *
00796 XmuScanlineNot(XmuScanline *scanline, int minx, int maxx)
00797 {
00798   XmuSegment *z;
00799   static XmuSegment x = { 0, 0, 0 };
00800   static XmuScanline and = { 0, &x, 0 };
00801 
00802   if (!scanline)
00803     return (scanline);
00804 
00805   XmuOptimizeScanline(scanline);
00806   if (minx > maxx)
00807     {
00808       minx ^= maxx; maxx ^= minx; minx ^= maxx;
00809     }
00810   and.segment->x1 = minx;
00811   and.segment->x2 = maxx;
00812   XmuScanlineAnd(scanline, &and);
00813   if (!scanline->segment)
00814     {
00815       scanline->segment = XmuNewSegment(minx, maxx);
00816       return (scanline);
00817     }
00818   z = scanline->segment;
00819   if (z->x1 != minx)
00820     {
00821       XmuSegment *q = XmuNewSegment(minx, z->x1);
00822 
00823       q->next = z;
00824       scanline->segment = q;
00825     }
00826 
00827   /*CONSTCOND*/
00828   while (1)
00829     {
00830       z->x1 = z->x2;
00831       if (!z->next)
00832         {
00833           z->x2 = maxx;
00834           break;
00835         }
00836       z->x2 = z->next->x1;
00837       if (z->next->x2 == maxx)
00838         {
00839           XmuDestroySegment(z->next);
00840           z->next = (XmuSegment *)NULL;
00841           break;
00842         }
00843       z = z->next;
00844     }
00845 
00846   return (scanline);
00847 }
00848 
00849 
00850 #ifndef notdef
00851 /*
00852  * Function:
00853  *      XmuScanlineOrSegment
00854  *
00855  * Parameters:
00856  *      dst - destionation scanline
00857  *      src - source segment
00858  *
00859  * Description:
00860  * (input)      +-----------+  +--------+    +---------+
00861  * (src)              +-------------------+
00862  * (output)     +-------------------------+  +---------+
00863  */
00864 XmuScanline *
00865 XmuScanlineOrSegment(XmuScanline *dst, XmuSegment *src)
00866 {
00867   XmuSegment *z, *p, ins;
00868 
00869   if (!src || !dst || !XmuValidSegment(src))
00870     return (dst);
00871 
00872   if (!dst->segment)
00873     {
00874       dst->segment = XmuNewSegment(src->x1, src->x2);
00875       return (dst);
00876     }
00877 
00878   z = p = dst->segment;
00879   ins.x1 = src->x1;
00880   ins.x2 = src->x2;
00881 
00882   /*CONSTCOND*/
00883   while (1)
00884     {
00885       if (!z)
00886         {
00887             XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
00888 
00889             if (p == dst->segment && z == p)
00890               dst->segment = q;
00891             else
00892               p->next = q;
00893             break;
00894         }
00895       else if (ins.x2 < z->x1)
00896         {
00897           XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
00898 
00899           if (p == dst->segment && z == p)
00900             {
00901               q->next = dst->segment;
00902               dst->segment = q;
00903             }
00904           else
00905             {
00906               p->next = q;
00907               q->next = z;
00908             }
00909           break;
00910         }
00911       else if (ins.x2 <= z->x2)
00912         {
00913           z->x1 = XmuMin(z->x1, ins.x1);
00914           break;
00915         }
00916       else if (ins.x1 <= z->x2)
00917         {
00918           ins.x1 = XmuMin(z->x1, ins.x1);
00919           if (!z->next)
00920             {
00921               z->x1 = ins.x1;
00922               z->x2 = ins.x2;
00923               break;
00924             }
00925           else
00926             {
00927               if (z == dst->segment)
00928                 {
00929                   p = dst->segment = dst->segment->next;
00930                   XmuDestroySegment(z);
00931                   z = dst->segment;
00932                   continue;
00933                 }
00934               else
00935                 {
00936                   p->next = z->next;
00937                   XmuDestroySegment(z);
00938                   z = p;
00939                 }
00940             }
00941         }
00942       p = z;
00943       z = z->next;
00944     }
00945 
00946   return (dst);
00947 }
00948 
00949 /*
00950  * Function:
00951  *      XmuScanlineAndSegment
00952  *
00953  * Parameters:
00954  *      dst - destination scanline
00955  *      src - source segment
00956  *
00957  * Description:
00958  * (input)      +------------+   +------+     +----------+
00959  * (src)             +---------------------+
00960  * (output)          +-------+   +------+
00961  */
00962 XmuScanline *
00963 XmuScanlineAndSegment(XmuScanline *dst, XmuSegment *src)
00964 {
00965   XmuSegment *z, *p;
00966 
00967   if (!dst || !src)
00968     return (dst);
00969 
00970   if (!XmuValidSegment(src))
00971     {
00972       XmuDestroySegmentList(dst->segment);
00973       dst->segment = (XmuSegment *)NULL;
00974       return (dst);
00975     }
00976   if (!dst->segment)
00977     return (dst);
00978 
00979   z = p = dst->segment;
00980   while (z)
00981     {
00982       if (src->x2 <= z->x1 || src->x1 >= z->x2)
00983         {
00984           if (z == dst->segment)
00985             {
00986               p = dst->segment = dst->segment->next;
00987               XmuDestroySegment(z);
00988               z = dst->segment;
00989               continue;
00990             }
00991           else
00992             {
00993               p->next = z->next;
00994               XmuDestroySegment(z);
00995               z = p;
00996             }
00997         }
00998       else
00999         {
01000           z->x1 = XmuMax(z->x1, src->x1);
01001           z->x2 = XmuMin(z->x2, src->x2);
01002         }
01003       p = z;
01004       z = z->next;
01005     }
01006 
01007   return (dst);
01008 }
01009 
01010 /*
01011  * Function:
01012  *      XmuScanlineXorSegment
01013  *
01014  * Parameters:
01015  *      dst - destionation scanline
01016  *      src - source segment
01017  *
01018  * Descriptipn:
01019  * (input)     +------------+  +----------+    +-----------+
01020  * (src)           +------------------------+
01021  * (output)    +---+        +--+          +-+  +-----------+
01022  */
01023 XmuScanline *
01024 XmuScanlineXorSegment(XmuScanline *dst, XmuSegment *src)
01025 {
01026   XmuSegment *p, *z, ins;
01027   int tmp1, tmp2;
01028 
01029   if (!dst || !src || !XmuValidSegment(src))
01030     return (dst);
01031   if (!dst->segment)
01032     {
01033       dst->segment = XmuNewSegment(src->x1, src->x2);
01034       return (dst);
01035     }
01036 
01037   p = z = dst->segment;
01038   ins.x1 = src->x1;
01039   ins.x2 = src->x2;
01040 
01041   /*CONSTCOND*/
01042   while (1)
01043     {
01044       if (!XmuValidSegment((&ins)))
01045         break;
01046       if (!z || ins.x2 < z->x1)
01047         {
01048           XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
01049 
01050           q->next = z;
01051           if (z == dst->segment)
01052             dst->segment = q;
01053           else
01054             p->next = q;
01055           break;
01056         }
01057       else if (ins.x2 == z->x1)
01058         {
01059           z->x1 = ins.x1;
01060           break;
01061         }
01062       else if (ins.x1 < z->x2)
01063         {
01064           if (ins.x1 < z->x1)
01065             {
01066               tmp1 = ins.x2;
01067               tmp2 = z->x2;
01068               ins.x2 = XmuMax(ins.x2, z->x2);
01069               z->x2 = z->x1;
01070               z->x1 = ins.x1;
01071               ins.x1 = XmuMin(tmp1, tmp2);
01072             }
01073           else if (ins.x1 > z->x1)
01074             {
01075               tmp1 = ins.x1;
01076               ins.x1 = XmuMin(ins.x2, z->x2);
01077               ins.x2 = XmuMax(z->x2, ins.x2);
01078               z->x2 = tmp1;
01079             }
01080           else  /* ins.x1 == z->x1 */
01081             {
01082               if (ins.x2 < z->x2)
01083                 {
01084                   z->x1 = ins.x2;
01085                   break;
01086                 }
01087               else
01088                 {
01089                   ins.x1 = z->x2;
01090                   if (z == dst->segment)
01091                     p = dst->segment = dst->segment->next;
01092                   else
01093                     p->next = z->next;
01094                   XmuDestroySegment(z);
01095                   z = p;
01096                   continue;
01097                 }
01098             }
01099         }
01100       else if (ins.x1 == z->x2)
01101         {
01102           ins.x1 = z->x1;
01103           if (z == dst->segment)
01104             p = dst->segment = dst->segment->next;
01105           else
01106             p->next = z->next;
01107           XmuDestroySegment(z);
01108           z = p;
01109           continue;
01110         }
01111       p = z;
01112       z = z->next;
01113     }
01114 
01115   return (dst);
01116 }
01117 #endif /* notdef */
01118 
01119 /*
01120  * Function:
01121  *      ScanlineOr
01122  *
01123  * Parameters:
01124  *      dst - destionation scanline
01125  *      src - source scanline
01126  *
01127  * Description:
01128  * (input)    +--------------+  +-----+    +----------+
01129  * (src)          +---------------------+       +-----------+
01130  * (output)   +-------------------------+  +----------------+
01131  */
01132 XmuScanline *
01133 XmuScanlineOr(XmuScanline *dst, XmuScanline *src)
01134 {
01135   XmuSegment *z, *p, *Z, ins;
01136 
01137   if (!src || !src->segment || !dst || dst == src)
01138     return (dst);
01139   if (!dst->segment)
01140     {
01141       XmuScanlineCopy(dst, src);
01142       return (dst);
01143     }
01144 
01145   z = p = dst->segment;
01146   Z = src->segment;
01147   ins.x1 = Z->x1;
01148   ins.x2 = Z->x2;
01149 
01150   /*CONSTCOND*/
01151   while (1)
01152     {
01153       while (!XmuValidSegment((&ins)))
01154         {
01155           if ((Z = Z->next) == (XmuSegment *)NULL)
01156             return (dst);
01157           ins.x1 = Z->x1;
01158           ins.x2 = Z->x2;
01159         }
01160         if (!z)
01161           {
01162             XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
01163 
01164             if (p == dst->segment && z == p)
01165               dst->segment = p = q;
01166             else
01167               {
01168                 p->next = q;
01169                 p = q;
01170               }
01171             Z = Z->next;
01172             XmuAppendSegment(p, Z);
01173             break;
01174           }
01175         else if (ins.x2 < z->x1)
01176           {
01177             XmuSegment *r = XmuNewSegment(ins.x1, ins.x2);
01178 
01179             if (p == dst->segment && z == p)
01180               {
01181                 r->next = dst->segment;
01182                 dst->segment = p = r;
01183               }
01184             else
01185               {
01186                 p->next = r;
01187                 r->next = z;
01188                 p = r;
01189               }
01190             Z = Z->next;
01191             if (!Z)
01192               break;
01193             else
01194               {
01195                 ins.x1 = Z->x1;
01196                 ins.x2 = Z->x2;
01197                 continue;
01198               }
01199           }
01200         else if (ins.x2 <= z->x2)
01201           {
01202             z->x1 = XmuMin(z->x1, ins.x1);
01203             Z = Z->next;
01204             if (!Z)
01205               break;
01206             else
01207               {
01208                 ins.x1 = Z->x1;
01209                 ins.x2 = Z->x2;
01210                 continue;
01211               }
01212           }
01213         else if (ins.x1 <= z->x2)
01214           {
01215             ins.x1 = XmuMin(z->x1, ins.x1);
01216             if (!z->next)
01217               {
01218                 z->x1 = ins.x1;
01219                 z->x2 = ins.x2;
01220                 p = z;
01221                 Z = Z->next;
01222                 XmuAppendSegment(p, Z);
01223                 break;
01224               }
01225             else
01226               {
01227                 if (z == dst->segment)
01228                   {
01229                     p = dst->segment = dst->segment->next;
01230                     XmuDestroySegment(z);
01231                     z = p;
01232                     continue;
01233                   }
01234                 else
01235                   {
01236                     p->next = z->next;
01237                     XmuDestroySegment(z);
01238                     z = p;
01239                   }
01240               }
01241           }
01242         p = z;
01243         z = z->next;
01244     }
01245 
01246   return (dst);
01247 }
01248 
01249 /*
01250  * Function:
01251  *      XmuScanlineAnd
01252  *
01253  * Parameters:
01254  *      dst - destination scanline
01255  *      src - source scanline
01256  *
01257  * Description:
01258  * (input)    +--------------+  +-----+    +----------+
01259  * (src)          +---------------------+       +-----------+
01260  * (output)       +----------+  +-----+         +-----+
01261  */
01262 XmuScanline *
01263 XmuScanlineAnd(XmuScanline *dst, XmuScanline *src)
01264 {
01265   XmuSegment  *z, *p, *Z;
01266 
01267   if (!dst || !src || dst == src || !dst->segment) {
01268         return (dst);
01269   }
01270   if (!src->segment)
01271     {
01272       XmuDestroySegmentList(dst->segment);
01273       dst->segment = (XmuSegment *)NULL;
01274       return (dst);
01275     }
01276   z = p = dst->segment;
01277   Z = src->segment;
01278 
01279   while (z)
01280     {
01281       while (!XmuValidSegment(Z) || Z->x2 <= z->x1)
01282         {
01283           Z = Z->next;
01284           if (!Z)
01285             {
01286               if (z == dst->segment)
01287                 dst->segment = (XmuSegment *)NULL;
01288               else
01289                 p->next = (XmuSegment *)0;
01290               XmuDestroySegmentList(z);
01291               return (dst);
01292             }
01293         }
01294       if (Z->x1 >= z->x2)
01295         {
01296           if (z == dst->segment)
01297             {
01298               p = dst->segment = dst->segment->next;
01299               XmuDestroySegment(z);
01300               z = dst->segment;
01301             }
01302           else
01303             {
01304               p->next = z->next;
01305               XmuDestroySegment(z);
01306               z = p->next;
01307             }
01308           if (!z)
01309             return (dst);
01310           else
01311             continue;
01312         }
01313         z->x1 = XmuMax(z->x1, Z->x1);
01314         if (z->x2 > Z->x2)
01315           {
01316             if (Z->next)
01317               {
01318                 XmuSegment *q = XmuNewSegment(Z->x2, z->x2);
01319 
01320                 q->next = z->next;
01321                 z->next = q;
01322               }
01323             z->x2 = Z->x2;
01324           }
01325         p = z;
01326         z = z->next;
01327     }
01328 
01329   return (dst);
01330 }
01331 
01332 /*
01333  * Function:
01334  *      ScanlineXor
01335  *
01336  * Parameters:
01337  *      dst - destination scanline
01338  *      src - source scanline
01339  *
01340  * Description:
01341  * (input)    +--------------+  +-----+    +----------+
01342  * (src)          +---------------------+       +-----------+
01343  * (output)   +---+          +--+     +-+  +----+     +-----+
01344  */
01345 XmuScanline *
01346 XmuScanlineXor(XmuScanline *dst, XmuScanline *src)
01347 {
01348   XmuSegment *z, *p, *Z, ins;
01349   int tmp1, tmp2;
01350 
01351   if (!src || !dst || !src->segment)
01352     return (dst);
01353   if (src == dst)
01354     {
01355       XmuDestroySegmentList(dst->segment);
01356       dst->segment = (XmuSegment *)NULL;
01357       return (dst);
01358     }
01359   if (!dst->segment)
01360     {
01361       XmuScanlineCopy(dst, src);
01362       return (dst);
01363     }
01364 
01365   z = p = dst->segment;
01366   Z = src->segment;
01367   ins.x1 = Z->x1;
01368   ins.x2 = Z->x2;
01369 
01370   /*CONSTCOND*/
01371   while (1)
01372     {
01373       while (!XmuValidSegment((&ins)))
01374         {
01375           if ((Z = Z->next) == (XmuSegment *)NULL)
01376             return (dst);
01377           ins.x1 = Z->x1;
01378           ins.x2 = Z->x2;
01379         }
01380       if (!z)
01381         {
01382           XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
01383 
01384             if (!dst->segment)
01385               dst->segment = q;
01386             else
01387               p->next = q;
01388             p = q;
01389             Z = Z->next;
01390             XmuAppendSegment(p, Z);
01391             break;
01392         }
01393       else if (ins.x2 < z->x1)
01394         {
01395           XmuSegment *q = XmuNewSegment(ins.x1, ins.x2);
01396 
01397           q->next = z;
01398           if (z == dst->segment)
01399             dst->segment = q;
01400           else
01401             p->next = q;
01402           if ((Z = Z->next) == (XmuSegment *)NULL)
01403             return (dst);
01404 
01405           p = q;
01406           ins.x1 = Z->x1;
01407           ins.x2 = Z->x2;
01408           continue;
01409         }
01410       else if (ins.x2 == z->x1)
01411         {
01412           z->x1 = ins.x1;
01413           if ((Z = Z->next) == (XmuSegment *)NULL)
01414             break;
01415           ins.x1 = Z->x1;
01416           ins.x2 = Z->x2;
01417           continue;
01418         }
01419       else if (ins.x1 < z->x2)
01420         {
01421           if (ins.x1 == z->x1)
01422             {
01423               if (ins.x2 < z->x2)
01424                 {
01425                   z->x1 = ins.x2;
01426                   if ((Z = Z->next) == (XmuSegment *)NULL)
01427                     break;
01428                   ins.x1 = Z->x1;
01429                   ins.x2 = Z->x2;
01430                   continue;
01431                 }
01432               else
01433                 {
01434                   ins.x1 = z->x2;
01435                   if (z == dst->segment)
01436                     p = dst->segment = dst->segment->next;
01437                   else
01438                     p->next = z->next;
01439                   XmuDestroySegment(z);
01440                   z = p;
01441                   continue;
01442                 }
01443             }
01444           else
01445             {
01446               if (Z->x2 < z->x2)
01447                 {
01448                   XmuSegment  *q = XmuNewSegment(XmuMin(ins.x1, z->x1),
01449                                                  XmuMax(z->x1, ins.x1));
01450 
01451                   q->next = z;
01452                   if (z == dst->segment)
01453                     dst->segment = q;
01454                   else
01455                     p->next = q;
01456                   ins.x1 = z->x2;
01457                   z->x1 = ins.x2;
01458                   p = q;
01459                   continue;
01460                 }
01461               else
01462                 {
01463                   tmp1 = ins.x2;
01464                   tmp2 = z->x2;
01465                   ins.x2 = XmuMax(ins.x2, z->x2);
01466                   z->x2 = XmuMax(z->x1, ins.x1);
01467                   z->x1 = XmuMin(ins.x1, z->x1);
01468                   ins.x1 = XmuMin(tmp1, tmp2);
01469                 }
01470             }
01471         }
01472       else if (ins.x1 == z->x2)
01473         {
01474           ins.x1 = z->x1;
01475           if (z == dst->segment)
01476             p = dst->segment = dst->segment->next;
01477           else
01478             p->next = z->next;
01479           XmuDestroySegment(z);
01480           z = p;
01481           continue;
01482         }
01483       p = z;
01484       z = z->next;
01485     }
01486 
01487   return (dst);
01488 }
01489 
01490 /*
01491  * Function:
01492  *      XmuNewScanline
01493  *
01494  * Parameters:
01495  *      y  - y coordinate
01496  *      x1 - left coordinate
01497  *      x2 - right coordinate
01498  *
01499  * Description:
01500  *      Creates a new Scanline
01501  */
01502 XmuScanline *
01503 XmuNewScanline(int y, int x1, int x2)
01504 {
01505   XmuScanline *scanline;
01506 
01507   scanline = (XmuScanline *)XtMalloc(sizeof(XmuScanline));
01508   scanline->y = y;
01509   if (x1 < x2)
01510     scanline->segment = XmuNewSegment(x1, x2);
01511   else
01512     scanline->segment = (XmuSegment *)NULL;
01513 
01514   scanline->next = (XmuScanline *)NULL;
01515 
01516   return (scanline);
01517 }
01518 
01519 /*
01520  * Function:
01521  *      XmuDestroyScanlineList
01522  *
01523  * Parameters:
01524  *      scanline - scanline list to destroy
01525  *
01526  * Description:
01527  *      Destroy a scanline list
01528  *
01529  * Observation:
01530  *      Use as follow:
01531  *      XmuDestroyScanlineList(area->scanline);
01532  *      area->scanline = (XmuScanline *)NULL;
01533  */
01534 void
01535 XmuDestroyScanlineList(XmuScanline *scanline)
01536 {
01537   XmuScanline *z;
01538 
01539   if (!scanline)
01540     return;
01541 
01542   while (scanline)
01543     {
01544       z = scanline;
01545       scanline = scanline->next;
01546       XmuDestroyScanline(z);
01547     }
01548 }
01549 
01550 /*
01551  * Function:
01552  *      XmuOptimizeArea
01553  *
01554  * Parameters:
01555  *      area - area to optimize
01556  *
01557  * Description:
01558  *        Optimizes an area. This function is called when finishing a
01559  *      operation between areas, since they can end with redundant data,
01560  *      and the algorithms for area combination waits a area with
01561  *      correct data (but can left unnecessary data in the area, to avoid
01562  *      to much paranoia tests).
01563  */
01564 XmuArea *XmuOptimizeArea(XmuArea *area)
01565 {
01566   XmuScanline *pr, *at;
01567 
01568   if (!area || !area->scanline)
01569     return (area);
01570 
01571   if (!area->scanline->next)
01572     {
01573       XmuDestroyScanlineList(area->scanline);
01574       area->scanline = (XmuScanline *)0;
01575       return (area);
01576     }
01577 
01578   pr = area->scanline;
01579   at = area->scanline->next;
01580   while (area->scanline && (!XmuValidScanline(area->scanline)
01581                             || (area->scanline->next && area->scanline->y
01582                                 >= area->scanline->next->y)))
01583     {
01584       area->scanline = area->scanline->next;
01585       XmuDestroyScanline(pr);
01586       pr = area->scanline;
01587       if (pr)
01588         at = pr->next;
01589     }
01590 
01591   for (; at; pr = at, at = at->next)
01592     {
01593       if (XmuScanlineEqu(at, pr)
01594           || (!XmuValidScanline(at) && !XmuValidScanline(pr))
01595           || (at->next && at->y >= at->next->y))
01596         {
01597           pr->next = at->next;
01598           XmuDestroyScanline(at);
01599           at = pr;
01600         }
01601     }
01602   if (pr && XmuValidScanline(pr))
01603     {
01604       XmuDestroySegmentList(pr->segment);
01605       pr->segment = (XmuSegment *)NULL;
01606     }
01607   if (area->scanline && !area->scanline->next)
01608     {
01609       XmuDestroyScanlineList(area->scanline);
01610       area->scanline = (XmuScanline *)NULL;
01611     }
01612 
01613   return (area);
01614 }

Generated on Sun Mar 4 15:03:56 2007 for Scilab [trunk] by  doxygen 1.5.1