1 /*
2  * Copyright © 1998 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Keith Packard not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Keith Packard makes no
11  * representations about the suitability of this software for any purpose.  It
12  * is provided "as is" without express or implied warranty.
13  *
14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 /*
24  * This file defines functions for drawing some primitives using
25  * underlying datatypes instead of masks
26  */
27 
28 #define isClipped(c,ul,lr)  (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
29 
30 #ifdef HAVE_DIX_CONFIG_H
31 #include <dix-config.h>
32 #endif
33 
34 #ifdef BITSSTORE
35 #define STORE(b,x)  BITSSTORE(b,x)
36 #else
37 #define STORE(b,x)  WRITE((b), (x))
38 #endif
39 
40 #ifdef BITSRROP
41 #define RROP(b,a,x)	BITSRROP(b,a,x)
42 #else
43 #define RROP(b,a,x)	WRITE((b), FbDoRRop (READ(b), (a), (x)))
44 #endif
45 
46 #ifdef BITSUNIT
47 #define UNIT BITSUNIT
48 #define USE_SOLID
49 #else
50 #define UNIT BITS
51 #endif
52 
53 /*
54  * Define the following before including this file:
55  *
56  *  BRESSOLID	name of function for drawing a solid segment
57  *  BRESDASH	name of function for drawing a dashed segment
58  *  DOTS	name of function for drawing dots
59  *  ARC		name of function for drawing a solid arc
60  *  BITS	type of underlying unit
61  */
62 
63 #ifdef BRESSOLID
64 void
BRESSOLID(DrawablePtr pDrawable,GCPtr pGC,int dashOffset,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e3,int len)65 BRESSOLID(DrawablePtr pDrawable,
66           GCPtr pGC,
67           int dashOffset,
68           int signdx,
69           int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len)
70 {
71     FbBits *dst;
72     FbStride dstStride;
73     int dstBpp;
74     int dstXoff, dstYoff;
75     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
76     UNIT *bits;
77     FbStride bitsStride;
78     FbStride majorStep, minorStep;
79     BITS xor = (BITS) pPriv->xor;
80 
81     fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
82     bits =
83         ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff);
84     bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT));
85     if (signdy < 0)
86         bitsStride = -bitsStride;
87     if (axis == X_AXIS) {
88         majorStep = signdx;
89         minorStep = bitsStride;
90     }
91     else {
92         majorStep = bitsStride;
93         minorStep = signdx;
94     }
95     while (len--) {
96         STORE(bits, xor);
97         bits += majorStep;
98         e += e1;
99         if (e >= 0) {
100             bits += minorStep;
101             e += e3;
102         }
103     }
104 
105     fbFinishAccess(pDrawable);
106 }
107 #endif
108 
109 #ifdef BRESDASH
110 void
BRESDASH(DrawablePtr pDrawable,GCPtr pGC,int dashOffset,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e3,int len)111 BRESDASH(DrawablePtr pDrawable,
112          GCPtr pGC,
113          int dashOffset,
114          int signdx,
115          int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len)
116 {
117     FbBits *dst;
118     FbStride dstStride;
119     int dstBpp;
120     int dstXoff, dstYoff;
121     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
122     UNIT *bits;
123     FbStride bitsStride;
124     FbStride majorStep, minorStep;
125     BITS xorfg, xorbg;
126 
127     FbDashDeclare;
128     int dashlen;
129     Bool even;
130     Bool doOdd;
131 
132     fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
133     doOdd = pGC->lineStyle == LineDoubleDash;
134     xorfg = (BITS) pPriv->xor;
135     xorbg = (BITS) pPriv->bgxor;
136 
137     FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
138 
139     bits =
140         ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff);
141     bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT));
142     if (signdy < 0)
143         bitsStride = -bitsStride;
144     if (axis == X_AXIS) {
145         majorStep = signdx;
146         minorStep = bitsStride;
147     }
148     else {
149         majorStep = bitsStride;
150         minorStep = signdx;
151     }
152     if (dashlen >= len)
153         dashlen = len;
154     if (doOdd) {
155         if (!even)
156             goto doubleOdd;
157         for (;;) {
158             len -= dashlen;
159             while (dashlen--) {
160                 STORE(bits, xorfg);
161                 bits += majorStep;
162                 if ((e += e1) >= 0) {
163                     e += e3;
164                     bits += minorStep;
165                 }
166             }
167             if (!len)
168                 break;
169 
170             FbDashNextEven(dashlen);
171 
172             if (dashlen >= len)
173                 dashlen = len;
174  doubleOdd:
175             len -= dashlen;
176             while (dashlen--) {
177                 STORE(bits, xorbg);
178                 bits += majorStep;
179                 if ((e += e1) >= 0) {
180                     e += e3;
181                     bits += minorStep;
182                 }
183             }
184             if (!len)
185                 break;
186 
187             FbDashNextOdd(dashlen);
188 
189             if (dashlen >= len)
190                 dashlen = len;
191         }
192     }
193     else {
194         if (!even)
195             goto onOffOdd;
196         for (;;) {
197             len -= dashlen;
198             while (dashlen--) {
199                 STORE(bits, xorfg);
200                 bits += majorStep;
201                 if ((e += e1) >= 0) {
202                     e += e3;
203                     bits += minorStep;
204                 }
205             }
206             if (!len)
207                 break;
208 
209             FbDashNextEven(dashlen);
210 
211             if (dashlen >= len)
212                 dashlen = len;
213  onOffOdd:
214             len -= dashlen;
215             while (dashlen--) {
216                 bits += majorStep;
217                 if ((e += e1) >= 0) {
218                     e += e3;
219                     bits += minorStep;
220                 }
221             }
222             if (!len)
223                 break;
224 
225             FbDashNextOdd(dashlen);
226 
227             if (dashlen >= len)
228                 dashlen = len;
229         }
230     }
231 
232     fbFinishAccess(pDrawable);
233 }
234 #endif
235 
236 #ifdef DOTS
237 void
DOTS(FbBits * dst,FbStride dstStride,int dstBpp,BoxPtr pBox,xPoint * ptsOrig,int npt,int xorg,int yorg,int xoff,int yoff,FbBits and,FbBits xor)238 DOTS(FbBits * dst,
239      FbStride dstStride,
240      int dstBpp,
241      BoxPtr pBox,
242      xPoint * ptsOrig,
243      int npt, int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor)
244 {
245     INT32 *pts = (INT32 *) ptsOrig;
246     UNIT *bits = (UNIT *) dst;
247     UNIT *point;
248     BITS bxor = (BITS) xor;
249     BITS band = (BITS) and;
250     FbStride bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT));
251     INT32 ul, lr;
252     INT32 pt;
253 
254     ul = coordToInt(pBox->x1 - xorg, pBox->y1 - yorg);
255     lr = coordToInt(pBox->x2 - xorg - 1, pBox->y2 - yorg - 1);
256 
257     bits += bitsStride * (yorg + yoff) + (xorg + xoff);
258 
259     if (and == 0) {
260         while (npt--) {
261             pt = *pts++;
262             if (!isClipped(pt, ul, lr)) {
263                 point = bits + intToY(pt) * bitsStride + intToX(pt);
264                 STORE(point, bxor);
265             }
266         }
267     }
268     else {
269         while (npt--) {
270             pt = *pts++;
271             if (!isClipped(pt, ul, lr)) {
272                 point = bits + intToY(pt) * bitsStride + intToX(pt);
273                 RROP(point, band, bxor);
274             }
275         }
276     }
277 }
278 #endif
279 
280 #ifdef ARC
281 
282 #define ARCCOPY(d)  STORE(d,xorBits)
283 #define ARCRROP(d)  RROP(d,andBits,xorBits)
284 
285 void
ARC(FbBits * dst,FbStride dstStride,int dstBpp,xArc * arc,int drawX,int drawY,FbBits and,FbBits xor)286 ARC(FbBits * dst,
287     FbStride dstStride,
288     int dstBpp, xArc * arc, int drawX, int drawY, FbBits and, FbBits xor)
289 {
290     UNIT *bits;
291     FbStride bitsStride;
292     miZeroArcRec info;
293     Bool do360;
294     int x;
295     UNIT *yorgp, *yorgop;
296     BITS andBits, xorBits;
297     int yoffset, dyoffset;
298     int y, a, b, d, mask;
299     int k1, k3, dx, dy;
300 
301     bits = (UNIT *) dst;
302     bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT));
303     andBits = (BITS) and;
304     xorBits = (BITS) xor;
305     do360 = miZeroArcSetup(arc, &info, TRUE);
306     yorgp = bits + ((info.yorg + drawY) * bitsStride);
307     yorgop = bits + ((info.yorgo + drawY) * bitsStride);
308     info.xorg = (info.xorg + drawX);
309     info.xorgo = (info.xorgo + drawX);
310     MIARCSETUP();
311     yoffset = y ? bitsStride : 0;
312     dyoffset = 0;
313     mask = info.initialMask;
314 
315     if (!(arc->width & 1)) {
316         if (andBits == 0) {
317             if (mask & 2)
318                 ARCCOPY(yorgp + info.xorgo);
319             if (mask & 8)
320                 ARCCOPY(yorgop + info.xorgo);
321         }
322         else {
323             if (mask & 2)
324                 ARCRROP(yorgp + info.xorgo);
325             if (mask & 8)
326                 ARCRROP(yorgop + info.xorgo);
327         }
328     }
329     if (!info.end.x || !info.end.y) {
330         mask = info.end.mask;
331         info.end = info.altend;
332     }
333     if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
334         int xoffset = bitsStride;
335         UNIT *yorghb = yorgp + (info.h * bitsStride) + info.xorg;
336         UNIT *yorgohb = yorghb - info.h;
337 
338         yorgp += info.xorg;
339         yorgop += info.xorg;
340         yorghb += info.h;
341         while (1) {
342             if (andBits == 0) {
343                 ARCCOPY(yorgp + yoffset + x);
344                 ARCCOPY(yorgp + yoffset - x);
345                 ARCCOPY(yorgop - yoffset - x);
346                 ARCCOPY(yorgop - yoffset + x);
347             }
348             else {
349                 ARCRROP(yorgp + yoffset + x);
350                 ARCRROP(yorgp + yoffset - x);
351                 ARCRROP(yorgop - yoffset - x);
352                 ARCRROP(yorgop - yoffset + x);
353             }
354             if (a < 0)
355                 break;
356             if (andBits == 0) {
357                 ARCCOPY(yorghb - xoffset - y);
358                 ARCCOPY(yorgohb - xoffset + y);
359                 ARCCOPY(yorgohb + xoffset + y);
360                 ARCCOPY(yorghb + xoffset - y);
361             }
362             else {
363                 ARCRROP(yorghb - xoffset - y);
364                 ARCRROP(yorgohb - xoffset + y);
365                 ARCRROP(yorgohb + xoffset + y);
366                 ARCRROP(yorghb + xoffset - y);
367             }
368             xoffset += bitsStride;
369             MIARCCIRCLESTEP(yoffset += bitsStride;
370                 );
371         }
372         yorgp -= info.xorg;
373         yorgop -= info.xorg;
374         x = info.w;
375         yoffset = info.h * bitsStride;
376     }
377     else if (do360) {
378         while (y < info.h || x < info.w) {
379             MIARCOCTANTSHIFT(dyoffset = bitsStride;
380                 );
381             if (andBits == 0) {
382                 ARCCOPY(yorgp + yoffset + info.xorg + x);
383                 ARCCOPY(yorgp + yoffset + info.xorgo - x);
384                 ARCCOPY(yorgop - yoffset + info.xorgo - x);
385                 ARCCOPY(yorgop - yoffset + info.xorg + x);
386             }
387             else {
388                 ARCRROP(yorgp + yoffset + info.xorg + x);
389                 ARCRROP(yorgp + yoffset + info.xorgo - x);
390                 ARCRROP(yorgop - yoffset + info.xorgo - x);
391                 ARCRROP(yorgop - yoffset + info.xorg + x);
392             }
393             MIARCSTEP(yoffset += dyoffset;
394                       , yoffset += bitsStride;
395                 );
396         }
397     }
398     else {
399         while (y < info.h || x < info.w) {
400             MIARCOCTANTSHIFT(dyoffset = bitsStride;
401                 );
402             if ((x == info.start.x) || (y == info.start.y)) {
403                 mask = info.start.mask;
404                 info.start = info.altstart;
405             }
406             if (andBits == 0) {
407                 if (mask & 1)
408                     ARCCOPY(yorgp + yoffset + info.xorg + x);
409                 if (mask & 2)
410                     ARCCOPY(yorgp + yoffset + info.xorgo - x);
411                 if (mask & 4)
412                     ARCCOPY(yorgop - yoffset + info.xorgo - x);
413                 if (mask & 8)
414                     ARCCOPY(yorgop - yoffset + info.xorg + x);
415             }
416             else {
417                 if (mask & 1)
418                     ARCRROP(yorgp + yoffset + info.xorg + x);
419                 if (mask & 2)
420                     ARCRROP(yorgp + yoffset + info.xorgo - x);
421                 if (mask & 4)
422                     ARCRROP(yorgop - yoffset + info.xorgo - x);
423                 if (mask & 8)
424                     ARCRROP(yorgop - yoffset + info.xorg + x);
425             }
426             if ((x == info.end.x) || (y == info.end.y)) {
427                 mask = info.end.mask;
428                 info.end = info.altend;
429             }
430             MIARCSTEP(yoffset += dyoffset;
431                       , yoffset += bitsStride;
432                 );
433         }
434     }
435     if ((x == info.start.x) || (y == info.start.y))
436         mask = info.start.mask;
437     if (andBits == 0) {
438         if (mask & 1)
439             ARCCOPY(yorgp + yoffset + info.xorg + x);
440         if (mask & 4)
441             ARCCOPY(yorgop - yoffset + info.xorgo - x);
442         if (arc->height & 1) {
443             if (mask & 2)
444                 ARCCOPY(yorgp + yoffset + info.xorgo - x);
445             if (mask & 8)
446                 ARCCOPY(yorgop - yoffset + info.xorg + x);
447         }
448     }
449     else {
450         if (mask & 1)
451             ARCRROP(yorgp + yoffset + info.xorg + x);
452         if (mask & 4)
453             ARCRROP(yorgop - yoffset + info.xorgo - x);
454         if (arc->height & 1) {
455             if (mask & 2)
456                 ARCRROP(yorgp + yoffset + info.xorgo - x);
457             if (mask & 8)
458                 ARCRROP(yorgop - yoffset + info.xorg + x);
459         }
460     }
461 }
462 
463 #undef ARCCOPY
464 #undef ARCRROP
465 #endif
466 
467 #ifdef GLYPH
468 #if BITMAP_BIT_ORDER == LSBFirst
469 #define WRITE_ADDR1(n)	    (n)
470 #define WRITE_ADDR2(n)	    (n)
471 #define WRITE_ADDR4(n)	    (n)
472 #else
473 #define WRITE_ADDR1(n)	    ((n) ^ 3)
474 #define WRITE_ADDR2(n)	    ((n) ^ 2)
475 #define WRITE_ADDR4(n)	    ((n))
476 #endif
477 
478 #define WRITE1(d,n,fg)	    WRITE(d + WRITE_ADDR1(n), (BITS) (fg))
479 
480 #ifdef BITS2
481 #define WRITE2(d,n,fg)	    WRITE((BITS2 *) &((d)[WRITE_ADDR2(n)]), (BITS2) (fg))
482 #else
483 #define WRITE2(d,n,fg)	    (WRITE1(d,n,fg), WRITE1(d,(n)+1,fg))
484 #endif
485 
486 #ifdef BITS4
487 #define WRITE4(d,n,fg)	    WRITE((BITS4 *) &((d)[WRITE_ADDR4(n)]), (BITS4) (fg))
488 #else
489 #define WRITE4(d,n,fg)	    (WRITE2(d,n,fg), WRITE2(d,(n)+2,fg))
490 #endif
491 
492 void
GLYPH(FbBits * dstBits,FbStride dstStride,int dstBpp,FbStip * stipple,FbBits fg,int x,int height)493 GLYPH(FbBits * dstBits,
494       FbStride dstStride,
495       int dstBpp, FbStip * stipple, FbBits fg, int x, int height)
496 {
497     int lshift;
498     FbStip bits;
499     BITS *dstLine;
500     BITS *dst;
501     int n;
502     int shift;
503 
504     dstLine = (BITS *) dstBits;
505     dstLine += x & ~3;
506     dstStride *= (sizeof(FbBits) / sizeof(BITS));
507     shift = x & 3;
508     lshift = 4 - shift;
509     while (height--) {
510         bits = *stipple++;
511         dst = (BITS *) dstLine;
512         n = lshift;
513         while (bits) {
514             switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) {
515             case 0:
516                 break;
517             case 1:
518                 WRITE1(dst, 0, fg);
519                 break;
520             case 2:
521                 WRITE1(dst, 1, fg);
522                 break;
523             case 3:
524                 WRITE2(dst, 0, fg);
525                 break;
526             case 4:
527                 WRITE1(dst, 2, fg);
528                 break;
529             case 5:
530                 WRITE1(dst, 0, fg);
531                 WRITE1(dst, 2, fg);
532                 break;
533             case 6:
534                 WRITE1(dst, 1, fg);
535                 WRITE1(dst, 2, fg);
536                 break;
537             case 7:
538                 WRITE2(dst, 0, fg);
539                 WRITE1(dst, 2, fg);
540                 break;
541             case 8:
542                 WRITE1(dst, 3, fg);
543                 break;
544             case 9:
545                 WRITE1(dst, 0, fg);
546                 WRITE1(dst, 3, fg);
547                 break;
548             case 10:
549                 WRITE1(dst, 1, fg);
550                 WRITE1(dst, 3, fg);
551                 break;
552             case 11:
553                 WRITE2(dst, 0, fg);
554                 WRITE1(dst, 3, fg);
555                 break;
556             case 12:
557                 WRITE2(dst, 2, fg);
558                 break;
559             case 13:
560                 WRITE1(dst, 0, fg);
561                 WRITE2(dst, 2, fg);
562                 break;
563             case 14:
564                 WRITE1(dst, 1, fg);
565                 WRITE2(dst, 2, fg);
566                 break;
567             case 15:
568                 WRITE4(dst, 0, fg);
569                 break;
570             }
571             bits = FbStipLeft(bits, n);
572             n = 4;
573             dst += 4;
574         }
575         dstLine += dstStride;
576     }
577 }
578 
579 #undef WRITE_ADDR1
580 #undef WRITE_ADDR2
581 #undef WRITE_ADDR4
582 #undef WRITE1
583 #undef WRITE2
584 #undef WRITE4
585 
586 #endif
587 
588 #ifdef POLYLINE
589 void
POLYLINE(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr ptsOrig)590 POLYLINE(DrawablePtr pDrawable,
591          GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig)
592 {
593     INT32 *pts = (INT32 *) ptsOrig;
594     int xoff = pDrawable->x;
595     int yoff = pDrawable->y;
596     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
597     BoxPtr pBox = RegionExtents(fbGetCompositeClip(pGC));
598 
599     FbBits *dst;
600     int dstStride;
601     int dstBpp;
602     int dstXoff, dstYoff;
603 
604     UNIT *bits, *bitsBase;
605     FbStride bitsStride;
606     BITS xor = fbGetGCPrivate(pGC)->xor;
607     BITS and = fbGetGCPrivate(pGC)->and;
608     int dashoffset = 0;
609 
610     INT32 ul, lr;
611     INT32 pt1, pt2;
612 
613     int e, e1, e3, len;
614     int stepmajor, stepminor;
615     int octant;
616 
617     if (mode == CoordModePrevious)
618         fbFixCoordModePrevious(npt, ptsOrig);
619 
620     fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
621     bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT));
622     bitsBase =
623         ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff);
624     ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff);
625     lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1);
626 
627     pt1 = *pts++;
628     npt--;
629     pt2 = *pts++;
630     npt--;
631     for (;;) {
632         if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) {
633             fbSegment(pDrawable, pGC,
634                       intToX(pt1) + xoff, intToY(pt1) + yoff,
635                       intToX(pt2) + xoff, intToY(pt2) + yoff,
636                       npt == 0 && pGC->capStyle != CapNotLast, &dashoffset);
637             if (!npt) {
638                 fbFinishAccess(pDrawable);
639                 return;
640             }
641             pt1 = pt2;
642             pt2 = *pts++;
643             npt--;
644         }
645         else {
646             bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1);
647             for (;;) {
648                 CalcLineDeltas(intToX(pt1), intToY(pt1),
649                                intToX(pt2), intToY(pt2),
650                                len, e1, stepmajor, stepminor, 1, bitsStride,
651                                octant);
652                 if (len < e1) {
653                     e3 = len;
654                     len = e1;
655                     e1 = e3;
656 
657                     e3 = stepminor;
658                     stepminor = stepmajor;
659                     stepmajor = e3;
660                     SetYMajorOctant(octant);
661                 }
662                 e = -len;
663                 e1 <<= 1;
664                 e3 = e << 1;
665                 FIXUP_ERROR(e, octant, bias);
666                 if (and == 0) {
667                     while (len--) {
668                         STORE(bits, xor);
669                         bits += stepmajor;
670                         e += e1;
671                         if (e >= 0) {
672                             bits += stepminor;
673                             e += e3;
674                         }
675                     }
676                 }
677                 else {
678                     while (len--) {
679                         RROP(bits, and, xor);
680                         bits += stepmajor;
681                         e += e1;
682                         if (e >= 0) {
683                             bits += stepminor;
684                             e += e3;
685                         }
686                     }
687                 }
688                 if (!npt) {
689                     if (pGC->capStyle != CapNotLast &&
690                         pt2 != *((INT32 *) ptsOrig)) {
691                         RROP(bits, and, xor);
692                     }
693                     fbFinishAccess(pDrawable);
694                     return;
695                 }
696                 pt1 = pt2;
697                 pt2 = *pts++;
698                 --npt;
699                 if (isClipped(pt2, ul, lr))
700                     break;
701             }
702         }
703     }
704 
705     fbFinishAccess(pDrawable);
706 }
707 #endif
708 
709 #ifdef POLYSEGMENT
710 void
POLYSEGMENT(DrawablePtr pDrawable,GCPtr pGC,int nseg,xSegment * pseg)711 POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg)
712 {
713     INT32 *pts = (INT32 *) pseg;
714     int xoff = pDrawable->x;
715     int yoff = pDrawable->y;
716     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
717     BoxPtr pBox = RegionExtents(fbGetCompositeClip(pGC));
718 
719     FbBits *dst;
720     int dstStride;
721     int dstBpp;
722     int dstXoff, dstYoff;
723 
724     UNIT *bits, *bitsBase;
725     FbStride bitsStride;
726     FbBits xorBits = fbGetGCPrivate(pGC)->xor;
727     FbBits andBits = fbGetGCPrivate(pGC)->and;
728     BITS xor = xorBits;
729     BITS and = andBits;
730     int dashoffset = 0;
731 
732     INT32 ul, lr;
733     INT32 pt1, pt2;
734 
735     int e, e1, e3, len;
736     int stepmajor, stepminor;
737     int octant;
738     Bool capNotLast;
739 
740     fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
741     bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT));
742     bitsBase =
743         ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff);
744     ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff);
745     lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1);
746 
747     capNotLast = pGC->capStyle == CapNotLast;
748 
749     while (nseg--) {
750         pt1 = *pts++;
751         pt2 = *pts++;
752         if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) {
753             fbSegment(pDrawable, pGC,
754                       intToX(pt1) + xoff, intToY(pt1) + yoff,
755                       intToX(pt2) + xoff, intToY(pt2) + yoff,
756                       !capNotLast, &dashoffset);
757         }
758         else {
759             CalcLineDeltas(intToX(pt1), intToY(pt1),
760                            intToX(pt2), intToY(pt2),
761                            len, e1, stepmajor, stepminor, 1, bitsStride,
762                            octant);
763             if (e1 == 0 && len > 3) {
764                 int x1, x2;
765                 FbBits *dstLine;
766                 int dstX, width;
767                 FbBits startmask, endmask;
768                 int nmiddle;
769 
770                 if (stepmajor < 0) {
771                     x1 = intToX(pt2);
772                     x2 = intToX(pt1) + 1;
773                     if (capNotLast)
774                         x1++;
775                 }
776                 else {
777                     x1 = intToX(pt1);
778                     x2 = intToX(pt2);
779                     if (!capNotLast)
780                         x2++;
781                 }
782                 dstX = (x1 + xoff + dstXoff) * (sizeof(UNIT) * 8);
783                 width = (x2 - x1) * (sizeof(UNIT) * 8);
784 
785                 dstLine = dst + (intToY(pt1) + yoff + dstYoff) * dstStride;
786                 dstLine += dstX >> FB_SHIFT;
787                 dstX &= FB_MASK;
788                 FbMaskBits(dstX, width, startmask, nmiddle, endmask);
789                 if (startmask) {
790                     WRITE(dstLine,
791                           FbDoMaskRRop(READ(dstLine), andBits, xorBits,
792                                        startmask));
793                     dstLine++;
794                 }
795                 if (!andBits)
796                     while (nmiddle--)
797                         WRITE(dstLine++, xorBits);
798                 else
799                     while (nmiddle--) {
800                         WRITE(dstLine,
801                               FbDoRRop(READ(dstLine), andBits, xorBits));
802                         dstLine++;
803                     }
804                 if (endmask)
805                     WRITE(dstLine,
806                           FbDoMaskRRop(READ(dstLine), andBits, xorBits,
807                                        endmask));
808             }
809             else {
810                 bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1);
811                 if (len < e1) {
812                     e3 = len;
813                     len = e1;
814                     e1 = e3;
815 
816                     e3 = stepminor;
817                     stepminor = stepmajor;
818                     stepmajor = e3;
819                     SetYMajorOctant(octant);
820                 }
821                 e = -len;
822                 e1 <<= 1;
823                 e3 = e << 1;
824                 FIXUP_ERROR(e, octant, bias);
825                 if (!capNotLast)
826                     len++;
827                 if (and == 0) {
828                     while (len--) {
829                         STORE(bits, xor);
830                         bits += stepmajor;
831                         e += e1;
832                         if (e >= 0) {
833                             bits += stepminor;
834                             e += e3;
835                         }
836                     }
837                 }
838                 else {
839                     while (len--) {
840                         RROP(bits, and, xor);
841                         bits += stepmajor;
842                         e += e1;
843                         if (e >= 0) {
844                             bits += stepminor;
845                             e += e3;
846                         }
847                     }
848                 }
849             }
850         }
851     }
852 
853     fbFinishAccess(pDrawable);
854 }
855 #endif
856 
857 #undef STORE
858 #undef RROP
859 #undef UNIT
860 #undef USE_SOLID
861 
862 #undef isClipped
863