00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
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
00069
00070
00071
00072
00073
00074
00075
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
00092
00093
00094
00095
00096
00097
00098
00099
00100
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
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
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
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
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
00245
00246
00247
00248
00249
00250
00251
00252
00253
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
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)
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
00410
00411
00412
00413
00414
00415
00416
00417
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
00505
00506
00507
00508
00509
00510
00511
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
00534
00535
00536
00537
00538
00539
00540
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
00563
00564
00565
00566
00567
00568
00569
00570
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
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
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
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
00631
00632
00633
00634
00635
00636
00637
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
00657
00658
00659
00660
00661
00662
00663
00664
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
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
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 Bool
00721 XmuAppendSegment(XmuSegment *segment, XmuSegment *append)
00722 {
00723 if (!segment || !append)
00724 return (False);
00725
00726 if (segment->next)
00727
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
00746
00747
00748
00749
00750
00751
00752
00753
00754
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
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
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
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
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
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
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
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
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
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
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
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
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
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
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
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
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
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
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
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
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
01492
01493
01494
01495
01496
01497
01498
01499
01500
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
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
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
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
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 }