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