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