xref: /OK3568_Linux_fs/external/xserver/fb/fbseg.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 1998 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that
7*4882a593Smuzhiyun  * copyright notice and this permission notice appear in supporting
8*4882a593Smuzhiyun  * documentation, and that the name of Keith Packard not be used in
9*4882a593Smuzhiyun  * advertising or publicity pertaining to distribution of the software without
10*4882a593Smuzhiyun  * specific, written prior permission.  Keith Packard makes no
11*4882a593Smuzhiyun  * representations about the suitability of this software for any purpose.  It
12*4882a593Smuzhiyun  * is provided "as is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20*4882a593Smuzhiyun  * PERFORMANCE OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
24*4882a593Smuzhiyun #include <dix-config.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <stdlib.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include "fb.h"
30*4882a593Smuzhiyun #include "miline.h"
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
33*4882a593Smuzhiyun 					((dir < 0) ? FbStipLeft(mask,bpp) : \
34*4882a593Smuzhiyun 					 FbStipRight(mask,bpp)))
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static void
fbBresSolid(DrawablePtr pDrawable,GCPtr pGC,int dashOffset,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e3,int len)37*4882a593Smuzhiyun fbBresSolid(DrawablePtr pDrawable,
38*4882a593Smuzhiyun             GCPtr pGC,
39*4882a593Smuzhiyun             int dashOffset,
40*4882a593Smuzhiyun             int signdx,
41*4882a593Smuzhiyun             int signdy,
42*4882a593Smuzhiyun             int axis, int x1, int y1, int e, int e1, int e3, int len)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun     FbStip *dst;
45*4882a593Smuzhiyun     FbStride dstStride;
46*4882a593Smuzhiyun     int dstBpp;
47*4882a593Smuzhiyun     int dstXoff, dstYoff;
48*4882a593Smuzhiyun     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
49*4882a593Smuzhiyun     FbStip and = (FbStip) pPriv->and;
50*4882a593Smuzhiyun     FbStip xor = (FbStip) pPriv->xor;
51*4882a593Smuzhiyun     FbStip mask, mask0;
52*4882a593Smuzhiyun     FbStip bits;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun     fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
55*4882a593Smuzhiyun     dst += ((y1 + dstYoff) * dstStride);
56*4882a593Smuzhiyun     x1 = (x1 + dstXoff) * dstBpp;
57*4882a593Smuzhiyun     dst += x1 >> FB_STIP_SHIFT;
58*4882a593Smuzhiyun     x1 &= FB_STIP_MASK;
59*4882a593Smuzhiyun     mask0 = FbStipMask(0, dstBpp);
60*4882a593Smuzhiyun     mask = FbStipRight(mask0, x1);
61*4882a593Smuzhiyun     if (signdx < 0)
62*4882a593Smuzhiyun         mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp);
63*4882a593Smuzhiyun     if (signdy < 0)
64*4882a593Smuzhiyun         dstStride = -dstStride;
65*4882a593Smuzhiyun     if (axis == X_AXIS) {
66*4882a593Smuzhiyun         bits = 0;
67*4882a593Smuzhiyun         while (len--) {
68*4882a593Smuzhiyun             bits |= mask;
69*4882a593Smuzhiyun             mask = fbBresShiftMask(mask, signdx, dstBpp);
70*4882a593Smuzhiyun             if (!mask) {
71*4882a593Smuzhiyun                 WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
72*4882a593Smuzhiyun                 bits = 0;
73*4882a593Smuzhiyun                 dst += signdx;
74*4882a593Smuzhiyun                 mask = mask0;
75*4882a593Smuzhiyun             }
76*4882a593Smuzhiyun             e += e1;
77*4882a593Smuzhiyun             if (e >= 0) {
78*4882a593Smuzhiyun                 if (bits) {
79*4882a593Smuzhiyun                     WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
80*4882a593Smuzhiyun                     bits = 0;
81*4882a593Smuzhiyun                 }
82*4882a593Smuzhiyun                 dst += dstStride;
83*4882a593Smuzhiyun                 e += e3;
84*4882a593Smuzhiyun             }
85*4882a593Smuzhiyun         }
86*4882a593Smuzhiyun         if (bits)
87*4882a593Smuzhiyun             WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
88*4882a593Smuzhiyun     }
89*4882a593Smuzhiyun     else {
90*4882a593Smuzhiyun         while (len--) {
91*4882a593Smuzhiyun             WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask));
92*4882a593Smuzhiyun             dst += dstStride;
93*4882a593Smuzhiyun             e += e1;
94*4882a593Smuzhiyun             if (e >= 0) {
95*4882a593Smuzhiyun                 e += e3;
96*4882a593Smuzhiyun                 mask = fbBresShiftMask(mask, signdx, dstBpp);
97*4882a593Smuzhiyun                 if (!mask) {
98*4882a593Smuzhiyun                     dst += signdx;
99*4882a593Smuzhiyun                     mask = mask0;
100*4882a593Smuzhiyun                 }
101*4882a593Smuzhiyun             }
102*4882a593Smuzhiyun         }
103*4882a593Smuzhiyun     }
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     fbFinishAccess(pDrawable);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static void
fbBresDash(DrawablePtr pDrawable,GCPtr pGC,int dashOffset,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e3,int len)109*4882a593Smuzhiyun fbBresDash(DrawablePtr pDrawable,
110*4882a593Smuzhiyun            GCPtr pGC,
111*4882a593Smuzhiyun            int dashOffset,
112*4882a593Smuzhiyun            int signdx,
113*4882a593Smuzhiyun            int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun     FbStip *dst;
116*4882a593Smuzhiyun     FbStride dstStride;
117*4882a593Smuzhiyun     int dstBpp;
118*4882a593Smuzhiyun     int dstXoff, dstYoff;
119*4882a593Smuzhiyun     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
120*4882a593Smuzhiyun     FbStip and = (FbStip) pPriv->and;
121*4882a593Smuzhiyun     FbStip xor = (FbStip) pPriv->xor;
122*4882a593Smuzhiyun     FbStip bgand = (FbStip) pPriv->bgand;
123*4882a593Smuzhiyun     FbStip bgxor = (FbStip) pPriv->bgxor;
124*4882a593Smuzhiyun     FbStip mask, mask0;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     FbDashDeclare;
127*4882a593Smuzhiyun     int dashlen;
128*4882a593Smuzhiyun     Bool even;
129*4882a593Smuzhiyun     Bool doOdd;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
132*4882a593Smuzhiyun     doOdd = pGC->lineStyle == LineDoubleDash;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun     dst += ((y1 + dstYoff) * dstStride);
137*4882a593Smuzhiyun     x1 = (x1 + dstXoff) * dstBpp;
138*4882a593Smuzhiyun     dst += x1 >> FB_STIP_SHIFT;
139*4882a593Smuzhiyun     x1 &= FB_STIP_MASK;
140*4882a593Smuzhiyun     mask0 = FbStipMask(0, dstBpp);
141*4882a593Smuzhiyun     mask = FbStipRight(mask0, x1);
142*4882a593Smuzhiyun     if (signdx < 0)
143*4882a593Smuzhiyun         mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp);
144*4882a593Smuzhiyun     if (signdy < 0)
145*4882a593Smuzhiyun         dstStride = -dstStride;
146*4882a593Smuzhiyun     while (len--) {
147*4882a593Smuzhiyun         if (even)
148*4882a593Smuzhiyun             WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask));
149*4882a593Smuzhiyun         else if (doOdd)
150*4882a593Smuzhiyun             WRITE(dst, FbDoMaskRRop(READ(dst), bgand, bgxor, mask));
151*4882a593Smuzhiyun         if (axis == X_AXIS) {
152*4882a593Smuzhiyun             mask = fbBresShiftMask(mask, signdx, dstBpp);
153*4882a593Smuzhiyun             if (!mask) {
154*4882a593Smuzhiyun                 dst += signdx;
155*4882a593Smuzhiyun                 mask = mask0;
156*4882a593Smuzhiyun             }
157*4882a593Smuzhiyun             e += e1;
158*4882a593Smuzhiyun             if (e >= 0) {
159*4882a593Smuzhiyun                 dst += dstStride;
160*4882a593Smuzhiyun                 e += e3;
161*4882a593Smuzhiyun             }
162*4882a593Smuzhiyun         }
163*4882a593Smuzhiyun         else {
164*4882a593Smuzhiyun             dst += dstStride;
165*4882a593Smuzhiyun             e += e1;
166*4882a593Smuzhiyun             if (e >= 0) {
167*4882a593Smuzhiyun                 e += e3;
168*4882a593Smuzhiyun                 mask = fbBresShiftMask(mask, signdx, dstBpp);
169*4882a593Smuzhiyun                 if (!mask) {
170*4882a593Smuzhiyun                     dst += signdx;
171*4882a593Smuzhiyun                     mask = mask0;
172*4882a593Smuzhiyun                 }
173*4882a593Smuzhiyun             }
174*4882a593Smuzhiyun         }
175*4882a593Smuzhiyun         FbDashStep(dashlen, even);
176*4882a593Smuzhiyun     }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun     fbFinishAccess(pDrawable);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun static void
fbBresFill(DrawablePtr pDrawable,GCPtr pGC,int dashOffset,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e3,int len)182*4882a593Smuzhiyun fbBresFill(DrawablePtr pDrawable,
183*4882a593Smuzhiyun            GCPtr pGC,
184*4882a593Smuzhiyun            int dashOffset,
185*4882a593Smuzhiyun            int signdx,
186*4882a593Smuzhiyun            int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun     while (len--) {
189*4882a593Smuzhiyun         fbFill(pDrawable, pGC, x1, y1, 1, 1);
190*4882a593Smuzhiyun         if (axis == X_AXIS) {
191*4882a593Smuzhiyun             x1 += signdx;
192*4882a593Smuzhiyun             e += e1;
193*4882a593Smuzhiyun             if (e >= 0) {
194*4882a593Smuzhiyun                 e += e3;
195*4882a593Smuzhiyun                 y1 += signdy;
196*4882a593Smuzhiyun             }
197*4882a593Smuzhiyun         }
198*4882a593Smuzhiyun         else {
199*4882a593Smuzhiyun             y1 += signdy;
200*4882a593Smuzhiyun             e += e1;
201*4882a593Smuzhiyun             if (e >= 0) {
202*4882a593Smuzhiyun                 e += e3;
203*4882a593Smuzhiyun                 x1 += signdx;
204*4882a593Smuzhiyun             }
205*4882a593Smuzhiyun         }
206*4882a593Smuzhiyun     }
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun static void
fbSetFg(DrawablePtr pDrawable,GCPtr pGC,Pixel fg)210*4882a593Smuzhiyun fbSetFg(DrawablePtr pDrawable, GCPtr pGC, Pixel fg)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun     if (fg != pGC->fgPixel) {
213*4882a593Smuzhiyun         ChangeGCVal val;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun         val.val = fg;
216*4882a593Smuzhiyun         ChangeGC(NullClient, pGC, GCForeground, &val);
217*4882a593Smuzhiyun         ValidateGC(pDrawable, pGC);
218*4882a593Smuzhiyun     }
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun static void
fbBresFillDash(DrawablePtr pDrawable,GCPtr pGC,int dashOffset,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e3,int len)222*4882a593Smuzhiyun fbBresFillDash(DrawablePtr pDrawable,
223*4882a593Smuzhiyun                GCPtr pGC,
224*4882a593Smuzhiyun                int dashOffset,
225*4882a593Smuzhiyun                int signdx,
226*4882a593Smuzhiyun                int signdy,
227*4882a593Smuzhiyun                int axis, int x1, int y1, int e, int e1, int e3, int len)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun     FbDashDeclare;
232*4882a593Smuzhiyun     int dashlen;
233*4882a593Smuzhiyun     Bool even;
234*4882a593Smuzhiyun     Bool doOdd;
235*4882a593Smuzhiyun     Bool doBg;
236*4882a593Smuzhiyun     Pixel fg, bg;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun     fg = pGC->fgPixel;
239*4882a593Smuzhiyun     bg = pGC->bgPixel;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun     /* whether to fill the odd dashes */
242*4882a593Smuzhiyun     doOdd = pGC->lineStyle == LineDoubleDash;
243*4882a593Smuzhiyun     /* whether to switch fg to bg when filling odd dashes */
244*4882a593Smuzhiyun     doBg = doOdd && (pGC->fillStyle == FillSolid ||
245*4882a593Smuzhiyun                      pGC->fillStyle == FillStippled);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     /* compute current dash position */
248*4882a593Smuzhiyun     FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun     while (len--) {
251*4882a593Smuzhiyun         if (even || doOdd) {
252*4882a593Smuzhiyun             if (doBg) {
253*4882a593Smuzhiyun                 if (even)
254*4882a593Smuzhiyun                     fbSetFg(pDrawable, pGC, fg);
255*4882a593Smuzhiyun                 else
256*4882a593Smuzhiyun                     fbSetFg(pDrawable, pGC, bg);
257*4882a593Smuzhiyun             }
258*4882a593Smuzhiyun             fbFill(pDrawable, pGC, x1, y1, 1, 1);
259*4882a593Smuzhiyun         }
260*4882a593Smuzhiyun         if (axis == X_AXIS) {
261*4882a593Smuzhiyun             x1 += signdx;
262*4882a593Smuzhiyun             e += e1;
263*4882a593Smuzhiyun             if (e >= 0) {
264*4882a593Smuzhiyun                 e += e3;
265*4882a593Smuzhiyun                 y1 += signdy;
266*4882a593Smuzhiyun             }
267*4882a593Smuzhiyun         }
268*4882a593Smuzhiyun         else {
269*4882a593Smuzhiyun             y1 += signdy;
270*4882a593Smuzhiyun             e += e1;
271*4882a593Smuzhiyun             if (e >= 0) {
272*4882a593Smuzhiyun                 e += e3;
273*4882a593Smuzhiyun                 x1 += signdx;
274*4882a593Smuzhiyun             }
275*4882a593Smuzhiyun         }
276*4882a593Smuzhiyun         FbDashStep(dashlen, even);
277*4882a593Smuzhiyun     }
278*4882a593Smuzhiyun     if (doBg)
279*4882a593Smuzhiyun         fbSetFg(pDrawable, pGC, fg);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun /*
283*4882a593Smuzhiyun  * For drivers that want to bail drawing some lines, this
284*4882a593Smuzhiyun  * function takes care of selecting the appropriate rasterizer
285*4882a593Smuzhiyun  * based on the contents of the specified GC.
286*4882a593Smuzhiyun  */
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun static FbBres *
fbSelectBres(DrawablePtr pDrawable,GCPtr pGC)289*4882a593Smuzhiyun fbSelectBres(DrawablePtr pDrawable, GCPtr pGC)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
292*4882a593Smuzhiyun     int dstBpp = pDrawable->bitsPerPixel;
293*4882a593Smuzhiyun     FbBres *bres;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun     if (pGC->lineStyle == LineSolid) {
296*4882a593Smuzhiyun         bres = fbBresFill;
297*4882a593Smuzhiyun         if (pGC->fillStyle == FillSolid) {
298*4882a593Smuzhiyun             bres = fbBresSolid;
299*4882a593Smuzhiyun             if (pPriv->and == 0) {
300*4882a593Smuzhiyun                 switch (dstBpp) {
301*4882a593Smuzhiyun                 case 8:
302*4882a593Smuzhiyun                     bres = fbBresSolid8;
303*4882a593Smuzhiyun                     break;
304*4882a593Smuzhiyun                 case 16:
305*4882a593Smuzhiyun                     bres = fbBresSolid16;
306*4882a593Smuzhiyun                     break;
307*4882a593Smuzhiyun                 case 32:
308*4882a593Smuzhiyun                     bres = fbBresSolid32;
309*4882a593Smuzhiyun                     break;
310*4882a593Smuzhiyun                 }
311*4882a593Smuzhiyun             }
312*4882a593Smuzhiyun         }
313*4882a593Smuzhiyun     }
314*4882a593Smuzhiyun     else {
315*4882a593Smuzhiyun         bres = fbBresFillDash;
316*4882a593Smuzhiyun         if (pGC->fillStyle == FillSolid) {
317*4882a593Smuzhiyun             bres = fbBresDash;
318*4882a593Smuzhiyun             if (pPriv->and == 0 &&
319*4882a593Smuzhiyun                 (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) {
320*4882a593Smuzhiyun                 switch (dstBpp) {
321*4882a593Smuzhiyun                 case 8:
322*4882a593Smuzhiyun                     bres = fbBresDash8;
323*4882a593Smuzhiyun                     break;
324*4882a593Smuzhiyun                 case 16:
325*4882a593Smuzhiyun                     bres = fbBresDash16;
326*4882a593Smuzhiyun                     break;
327*4882a593Smuzhiyun                 case 32:
328*4882a593Smuzhiyun                     bres = fbBresDash32;
329*4882a593Smuzhiyun                     break;
330*4882a593Smuzhiyun                 }
331*4882a593Smuzhiyun             }
332*4882a593Smuzhiyun         }
333*4882a593Smuzhiyun     }
334*4882a593Smuzhiyun     return bres;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun void
fbSegment(DrawablePtr pDrawable,GCPtr pGC,int x1,int y1,int x2,int y2,Bool drawLast,int * dashOffset)338*4882a593Smuzhiyun fbSegment(DrawablePtr pDrawable,
339*4882a593Smuzhiyun           GCPtr pGC,
340*4882a593Smuzhiyun           int x1, int y1, int x2, int y2, Bool drawLast, int *dashOffset)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun     FbBres *bres;
343*4882a593Smuzhiyun     RegionPtr pClip = fbGetCompositeClip(pGC);
344*4882a593Smuzhiyun     BoxPtr pBox;
345*4882a593Smuzhiyun     int nBox;
346*4882a593Smuzhiyun     int adx;                    /* abs values of dx and dy */
347*4882a593Smuzhiyun     int ady;
348*4882a593Smuzhiyun     int signdx;                 /* sign of dx and dy */
349*4882a593Smuzhiyun     int signdy;
350*4882a593Smuzhiyun     int e, e1, e2, e3;          /* bresenham error and increments */
351*4882a593Smuzhiyun     int len;                    /* length of segment */
352*4882a593Smuzhiyun     int axis;                   /* major axis */
353*4882a593Smuzhiyun     int octant;
354*4882a593Smuzhiyun     int dashoff;
355*4882a593Smuzhiyun     int doff;
356*4882a593Smuzhiyun     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
357*4882a593Smuzhiyun     unsigned int oc1;           /* outcode of point 1 */
358*4882a593Smuzhiyun     unsigned int oc2;           /* outcode of point 2 */
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun     nBox = RegionNumRects(pClip);
361*4882a593Smuzhiyun     pBox = RegionRects(pClip);
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun     bres = fbSelectBres(pDrawable, pGC);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun     if (adx > ady) {
368*4882a593Smuzhiyun         axis = X_AXIS;
369*4882a593Smuzhiyun         e1 = ady << 1;
370*4882a593Smuzhiyun         e2 = e1 - (adx << 1);
371*4882a593Smuzhiyun         e = e1 - adx;
372*4882a593Smuzhiyun         len = adx;
373*4882a593Smuzhiyun     }
374*4882a593Smuzhiyun     else {
375*4882a593Smuzhiyun         axis = Y_AXIS;
376*4882a593Smuzhiyun         e1 = adx << 1;
377*4882a593Smuzhiyun         e2 = e1 - (ady << 1);
378*4882a593Smuzhiyun         e = e1 - ady;
379*4882a593Smuzhiyun         SetYMajorOctant(octant);
380*4882a593Smuzhiyun         len = ady;
381*4882a593Smuzhiyun     }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun     FIXUP_ERROR(e, octant, bias);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun     /*
386*4882a593Smuzhiyun      * Adjust error terms to compare against zero
387*4882a593Smuzhiyun      */
388*4882a593Smuzhiyun     e3 = e2 - e1;
389*4882a593Smuzhiyun     e = e - e1;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     /* we have bresenham parameters and two points.
392*4882a593Smuzhiyun        all we have to do now is clip and draw.
393*4882a593Smuzhiyun      */
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun     if (drawLast)
396*4882a593Smuzhiyun         len++;
397*4882a593Smuzhiyun     dashoff = *dashOffset;
398*4882a593Smuzhiyun     *dashOffset = dashoff + len;
399*4882a593Smuzhiyun     while (nBox--) {
400*4882a593Smuzhiyun         oc1 = 0;
401*4882a593Smuzhiyun         oc2 = 0;
402*4882a593Smuzhiyun         OUTCODES(oc1, x1, y1, pBox);
403*4882a593Smuzhiyun         OUTCODES(oc2, x2, y2, pBox);
404*4882a593Smuzhiyun         if ((oc1 | oc2) == 0) {
405*4882a593Smuzhiyun             (*bres) (pDrawable, pGC, dashoff,
406*4882a593Smuzhiyun                      signdx, signdy, axis, x1, y1, e, e1, e3, len);
407*4882a593Smuzhiyun             break;
408*4882a593Smuzhiyun         }
409*4882a593Smuzhiyun         else if (oc1 & oc2) {
410*4882a593Smuzhiyun             pBox++;
411*4882a593Smuzhiyun         }
412*4882a593Smuzhiyun         else {
413*4882a593Smuzhiyun             int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
414*4882a593Smuzhiyun             int clip1 = 0, clip2 = 0;
415*4882a593Smuzhiyun             int clipdx, clipdy;
416*4882a593Smuzhiyun             int err;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun             if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2 - 1,
419*4882a593Smuzhiyun                                pBox->y2 - 1,
420*4882a593Smuzhiyun                                &new_x1, &new_y1, &new_x2, &new_y2,
421*4882a593Smuzhiyun                                adx, ady, &clip1, &clip2,
422*4882a593Smuzhiyun                                octant, bias, oc1, oc2) == -1) {
423*4882a593Smuzhiyun                 pBox++;
424*4882a593Smuzhiyun                 continue;
425*4882a593Smuzhiyun             }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun             if (axis == X_AXIS)
428*4882a593Smuzhiyun                 len = abs(new_x2 - new_x1);
429*4882a593Smuzhiyun             else
430*4882a593Smuzhiyun                 len = abs(new_y2 - new_y1);
431*4882a593Smuzhiyun             if (clip2 != 0 || drawLast)
432*4882a593Smuzhiyun                 len++;
433*4882a593Smuzhiyun             if (len) {
434*4882a593Smuzhiyun                 /* unwind bresenham error term to first point */
435*4882a593Smuzhiyun                 doff = dashoff;
436*4882a593Smuzhiyun                 err = e;
437*4882a593Smuzhiyun                 if (clip1) {
438*4882a593Smuzhiyun                     clipdx = abs(new_x1 - x1);
439*4882a593Smuzhiyun                     clipdy = abs(new_y1 - y1);
440*4882a593Smuzhiyun                     if (axis == X_AXIS) {
441*4882a593Smuzhiyun                         doff += clipdx;
442*4882a593Smuzhiyun                         err += e3 * clipdy + e1 * clipdx;
443*4882a593Smuzhiyun                     }
444*4882a593Smuzhiyun                     else {
445*4882a593Smuzhiyun                         doff += clipdy;
446*4882a593Smuzhiyun                         err += e3 * clipdx + e1 * clipdy;
447*4882a593Smuzhiyun                     }
448*4882a593Smuzhiyun                 }
449*4882a593Smuzhiyun                 (*bres) (pDrawable, pGC, doff,
450*4882a593Smuzhiyun                          signdx, signdy, axis, new_x1, new_y1,
451*4882a593Smuzhiyun                          err, e1, e3, len);
452*4882a593Smuzhiyun             }
453*4882a593Smuzhiyun             pBox++;
454*4882a593Smuzhiyun         }
455*4882a593Smuzhiyun     }                           /* while (nBox--) */
456*4882a593Smuzhiyun }
457