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