1706f2543Smrg/*
2706f2543Smrg * Copyright © 1998 Keith Packard
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Keith Packard not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Keith Packard makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
24706f2543Smrg#include <dix-config.h>
25706f2543Smrg#endif
26706f2543Smrg
27706f2543Smrg#include <stdlib.h>
28706f2543Smrg
29706f2543Smrg#include "fb.h"
30706f2543Smrg#include "miline.h"
31706f2543Smrg
32706f2543Smrg#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
33706f2543Smrg					((dir < 0) ? FbStipLeft(mask,bpp) : \
34706f2543Smrg					 FbStipRight(mask,bpp)))
35706f2543Smrg
36706f2543Smrgvoid
37706f2543SmrgfbBresSolid (DrawablePtr    pDrawable,
38706f2543Smrg	     GCPtr	    pGC,
39706f2543Smrg	     int	    dashOffset,
40706f2543Smrg	     int	    signdx,
41706f2543Smrg	     int	    signdy,
42706f2543Smrg	     int	    axis,
43706f2543Smrg	     int	    x1,
44706f2543Smrg	     int	    y1,
45706f2543Smrg	     int	    e,
46706f2543Smrg	     int	    e1,
47706f2543Smrg	     int	    e3,
48706f2543Smrg	     int	    len)
49706f2543Smrg{
50706f2543Smrg    FbStip	*dst;
51706f2543Smrg    FbStride	dstStride;
52706f2543Smrg    int		dstBpp;
53706f2543Smrg    int		dstXoff, dstYoff;
54706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
55706f2543Smrg    FbStip	and = (FbStip) pPriv->and;
56706f2543Smrg    FbStip	xor = (FbStip) pPriv->xor;
57706f2543Smrg    FbStip	mask, mask0;
58706f2543Smrg    FbStip	bits;
59706f2543Smrg
60706f2543Smrg    fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
61706f2543Smrg    dst += ((y1 + dstYoff) * dstStride);
62706f2543Smrg    x1 = (x1 + dstXoff) * dstBpp;
63706f2543Smrg    dst += x1 >> FB_STIP_SHIFT;
64706f2543Smrg    x1 &= FB_STIP_MASK;
65706f2543Smrg    mask0 = FbStipMask(0, dstBpp);
66706f2543Smrg    mask = FbStipRight (mask0, x1);
67706f2543Smrg    if (signdx < 0)
68706f2543Smrg	mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp);
69706f2543Smrg    if (signdy < 0)
70706f2543Smrg	dstStride = -dstStride;
71706f2543Smrg    if (axis == X_AXIS)
72706f2543Smrg    {
73706f2543Smrg	bits = 0;
74706f2543Smrg	while (len--)
75706f2543Smrg	{
76706f2543Smrg	    bits |= mask;
77706f2543Smrg	    mask = fbBresShiftMask(mask,signdx,dstBpp);
78706f2543Smrg	    if (!mask)
79706f2543Smrg	    {
80706f2543Smrg		WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
81706f2543Smrg		bits = 0;
82706f2543Smrg		dst += signdx;
83706f2543Smrg		mask = mask0;
84706f2543Smrg	    }
85706f2543Smrg	    e += e1;
86706f2543Smrg	    if (e >= 0)
87706f2543Smrg	    {
88706f2543Smrg		WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
89706f2543Smrg		bits = 0;
90706f2543Smrg		dst += dstStride;
91706f2543Smrg		e += e3;
92706f2543Smrg	    }
93706f2543Smrg	}
94706f2543Smrg	if (bits)
95706f2543Smrg	    WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
96706f2543Smrg    }
97706f2543Smrg    else
98706f2543Smrg    {
99706f2543Smrg	while (len--)
100706f2543Smrg	{
101706f2543Smrg	    WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask));
102706f2543Smrg	    dst += dstStride;
103706f2543Smrg	    e += e1;
104706f2543Smrg	    if (e >= 0)
105706f2543Smrg	    {
106706f2543Smrg		e += e3;
107706f2543Smrg		mask = fbBresShiftMask(mask,signdx,dstBpp);
108706f2543Smrg		if (!mask)
109706f2543Smrg		{
110706f2543Smrg		    dst += signdx;
111706f2543Smrg		    mask = mask0;
112706f2543Smrg		}
113706f2543Smrg	    }
114706f2543Smrg	}
115706f2543Smrg    }
116706f2543Smrg
117706f2543Smrg    fbFinishAccess (pDrawable);
118706f2543Smrg}
119706f2543Smrg
120706f2543Smrgvoid
121706f2543SmrgfbBresDash (DrawablePtr	pDrawable,
122706f2543Smrg	    GCPtr	pGC,
123706f2543Smrg	    int		dashOffset,
124706f2543Smrg	    int		signdx,
125706f2543Smrg	    int		signdy,
126706f2543Smrg	    int		axis,
127706f2543Smrg	    int		x1,
128706f2543Smrg	    int		y1,
129706f2543Smrg	    int		e,
130706f2543Smrg	    int		e1,
131706f2543Smrg	    int		e3,
132706f2543Smrg	    int		len)
133706f2543Smrg{
134706f2543Smrg    FbStip	*dst;
135706f2543Smrg    FbStride	dstStride;
136706f2543Smrg    int		dstBpp;
137706f2543Smrg    int		dstXoff, dstYoff;
138706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
139706f2543Smrg    FbStip	and = (FbStip) pPriv->and;
140706f2543Smrg    FbStip	xor = (FbStip) pPriv->xor;
141706f2543Smrg    FbStip	bgand = (FbStip) pPriv->bgand;
142706f2543Smrg    FbStip	bgxor = (FbStip) pPriv->bgxor;
143706f2543Smrg    FbStip	mask, mask0;
144706f2543Smrg    FbDashDeclare;
145706f2543Smrg    int		dashlen;
146706f2543Smrg    Bool	even;
147706f2543Smrg    Bool	doOdd;
148706f2543Smrg
149706f2543Smrg    fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
150706f2543Smrg    doOdd = pGC->lineStyle == LineDoubleDash;
151706f2543Smrg
152706f2543Smrg    FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
153706f2543Smrg
154706f2543Smrg    dst += ((y1 + dstYoff) * dstStride);
155706f2543Smrg    x1 = (x1 + dstXoff) * dstBpp;
156706f2543Smrg    dst += x1 >> FB_STIP_SHIFT;
157706f2543Smrg    x1 &= FB_STIP_MASK;
158706f2543Smrg    mask0 = FbStipMask(0, dstBpp);
159706f2543Smrg    mask = FbStipRight (mask0, x1);
160706f2543Smrg    if (signdx < 0)
161706f2543Smrg	mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp);
162706f2543Smrg    if (signdy < 0)
163706f2543Smrg	dstStride = -dstStride;
164706f2543Smrg    while (len--)
165706f2543Smrg    {
166706f2543Smrg	if (even)
167706f2543Smrg	    WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask));
168706f2543Smrg	else if (doOdd)
169706f2543Smrg	    WRITE(dst, FbDoMaskRRop (READ(dst), bgand, bgxor, mask));
170706f2543Smrg	if (axis == X_AXIS)
171706f2543Smrg	{
172706f2543Smrg	    mask = fbBresShiftMask(mask,signdx,dstBpp);
173706f2543Smrg	    if (!mask)
174706f2543Smrg	    {
175706f2543Smrg		dst += signdx;
176706f2543Smrg		mask = mask0;
177706f2543Smrg	    }
178706f2543Smrg	    e += e1;
179706f2543Smrg	    if (e >= 0)
180706f2543Smrg	    {
181706f2543Smrg		dst += dstStride;
182706f2543Smrg		e += e3;
183706f2543Smrg	    }
184706f2543Smrg	}
185706f2543Smrg	else
186706f2543Smrg	{
187706f2543Smrg	    dst += dstStride;
188706f2543Smrg	    e += e1;
189706f2543Smrg	    if (e >= 0)
190706f2543Smrg	    {
191706f2543Smrg		e += e3;
192706f2543Smrg		mask = fbBresShiftMask(mask,signdx,dstBpp);
193706f2543Smrg		if (!mask)
194706f2543Smrg		{
195706f2543Smrg		    dst += signdx;
196706f2543Smrg		    mask = mask0;
197706f2543Smrg		}
198706f2543Smrg	    }
199706f2543Smrg	}
200706f2543Smrg	FbDashStep (dashlen, even);
201706f2543Smrg    }
202706f2543Smrg
203706f2543Smrg    fbFinishAccess (pDrawable);
204706f2543Smrg}
205706f2543Smrg
206706f2543Smrgvoid
207706f2543SmrgfbBresFill (DrawablePtr	pDrawable,
208706f2543Smrg	    GCPtr	pGC,
209706f2543Smrg	    int		dashOffset,
210706f2543Smrg	    int		signdx,
211706f2543Smrg	    int		signdy,
212706f2543Smrg	    int		axis,
213706f2543Smrg	    int		x1,
214706f2543Smrg	    int		y1,
215706f2543Smrg	    int		e,
216706f2543Smrg	    int		e1,
217706f2543Smrg	    int		e3,
218706f2543Smrg	    int		len)
219706f2543Smrg{
220706f2543Smrg    while (len--)
221706f2543Smrg    {
222706f2543Smrg	fbFill (pDrawable, pGC, x1, y1, 1, 1);
223706f2543Smrg	if (axis == X_AXIS)
224706f2543Smrg	{
225706f2543Smrg	    x1 += signdx;
226706f2543Smrg	    e += e1;
227706f2543Smrg	    if (e >= 0)
228706f2543Smrg	    {
229706f2543Smrg		e += e3;
230706f2543Smrg		y1 += signdy;
231706f2543Smrg	    }
232706f2543Smrg	}
233706f2543Smrg	else
234706f2543Smrg	{
235706f2543Smrg	    y1 += signdy;
236706f2543Smrg	    e += e1;
237706f2543Smrg	    if (e >= 0)
238706f2543Smrg	    {
239706f2543Smrg		e += e3;
240706f2543Smrg		x1 += signdx;
241706f2543Smrg	    }
242706f2543Smrg	}
243706f2543Smrg    }
244706f2543Smrg}
245706f2543Smrg
246706f2543Smrgstatic void
247706f2543SmrgfbSetFg (DrawablePtr	pDrawable,
248706f2543Smrg	 GCPtr		pGC,
249706f2543Smrg	 Pixel		fg)
250706f2543Smrg{
251706f2543Smrg    if (fg != pGC->fgPixel)
252706f2543Smrg    {
253706f2543Smrg	ChangeGCVal val;
254706f2543Smrg	val.val = fg;
255706f2543Smrg	ChangeGC (NullClient, pGC, GCForeground, &val);
256706f2543Smrg	ValidateGC (pDrawable, pGC);
257706f2543Smrg    }
258706f2543Smrg}
259706f2543Smrg
260706f2543Smrgvoid
261706f2543SmrgfbBresFillDash (DrawablePtr pDrawable,
262706f2543Smrg		GCPtr	    pGC,
263706f2543Smrg		int	    dashOffset,
264706f2543Smrg		int	    signdx,
265706f2543Smrg		int	    signdy,
266706f2543Smrg		int	    axis,
267706f2543Smrg		int	    x1,
268706f2543Smrg		int	    y1,
269706f2543Smrg		int	    e,
270706f2543Smrg		int	    e1,
271706f2543Smrg		int	    e3,
272706f2543Smrg		int	    len)
273706f2543Smrg{
274706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
275706f2543Smrg    FbDashDeclare;
276706f2543Smrg    int		dashlen;
277706f2543Smrg    Bool	even;
278706f2543Smrg    Bool	doOdd;
279706f2543Smrg    Bool	doBg;
280706f2543Smrg    Pixel	fg, bg;
281706f2543Smrg
282706f2543Smrg    fg = pGC->fgPixel;
283706f2543Smrg    bg = pGC->bgPixel;
284706f2543Smrg
285706f2543Smrg    /* whether to fill the odd dashes */
286706f2543Smrg    doOdd = pGC->lineStyle == LineDoubleDash;
287706f2543Smrg    /* whether to switch fg to bg when filling odd dashes */
288706f2543Smrg    doBg = doOdd && (pGC->fillStyle == FillSolid ||
289706f2543Smrg		     pGC->fillStyle == FillStippled);
290706f2543Smrg
291706f2543Smrg    /* compute current dash position */
292706f2543Smrg    FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
293706f2543Smrg
294706f2543Smrg    while (len--)
295706f2543Smrg    {
296706f2543Smrg	if (even || doOdd)
297706f2543Smrg	{
298706f2543Smrg	    if (doBg)
299706f2543Smrg	    {
300706f2543Smrg		if (even)
301706f2543Smrg		    fbSetFg (pDrawable, pGC, fg);
302706f2543Smrg		else
303706f2543Smrg		    fbSetFg (pDrawable, pGC, bg);
304706f2543Smrg	    }
305706f2543Smrg	    fbFill (pDrawable, pGC, x1, y1, 1, 1);
306706f2543Smrg	}
307706f2543Smrg	if (axis == X_AXIS)
308706f2543Smrg	{
309706f2543Smrg	    x1 += signdx;
310706f2543Smrg	    e += e1;
311706f2543Smrg	    if (e >= 0)
312706f2543Smrg	    {
313706f2543Smrg		e += e3;
314706f2543Smrg		y1 += signdy;
315706f2543Smrg	    }
316706f2543Smrg	}
317706f2543Smrg	else
318706f2543Smrg	{
319706f2543Smrg	    y1 += signdy;
320706f2543Smrg	    e += e1;
321706f2543Smrg	    if (e >= 0)
322706f2543Smrg	    {
323706f2543Smrg		e += e3;
324706f2543Smrg		x1 += signdx;
325706f2543Smrg	    }
326706f2543Smrg	}
327706f2543Smrg	FbDashStep (dashlen, even);
328706f2543Smrg    }
329706f2543Smrg    if (doBg)
330706f2543Smrg	fbSetFg (pDrawable, pGC, fg);
331706f2543Smrg}
332706f2543Smrg
333706f2543Smrg#ifdef FB_24BIT
334706f2543Smrgstatic void
335706f2543SmrgfbBresSolid24RRop (DrawablePtr  pDrawable,
336706f2543Smrg		   GCPtr	pGC,
337706f2543Smrg		   int		dashOffset,
338706f2543Smrg		   int		signdx,
339706f2543Smrg		   int		signdy,
340706f2543Smrg		   int		axis,
341706f2543Smrg		   int		x1,
342706f2543Smrg		   int		y1,
343706f2543Smrg		   int		e,
344706f2543Smrg		   int		e1,
345706f2543Smrg		   int		e3,
346706f2543Smrg		   int		len)
347706f2543Smrg{
348706f2543Smrg    FbStip	*dst;
349706f2543Smrg    FbStride	dstStride;
350706f2543Smrg    int		dstBpp;
351706f2543Smrg    int		dstXoff, dstYoff;
352706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
353706f2543Smrg    FbStip	and = pPriv->and;
354706f2543Smrg    FbStip	xor = pPriv->xor;
355706f2543Smrg    FbStip	leftMask, rightMask;
356706f2543Smrg    int		nl;
357706f2543Smrg    FbStip	*d;
358706f2543Smrg    int		x;
359706f2543Smrg    int		rot;
360706f2543Smrg    FbStip	andT, xorT;
361706f2543Smrg
362706f2543Smrg    fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
363706f2543Smrg    dst += ((y1 + dstYoff) * dstStride);
364706f2543Smrg    x1 = (x1 + dstXoff) * 24;
365706f2543Smrg    if (signdy < 0)
366706f2543Smrg	dstStride = -dstStride;
367706f2543Smrg    signdx *= 24;
368706f2543Smrg    while (len--)
369706f2543Smrg    {
370706f2543Smrg	d = dst + (x1 >> FB_STIP_SHIFT);
371706f2543Smrg	x = x1 & FB_STIP_MASK;
372706f2543Smrg	rot = FbFirst24Rot (x);
373706f2543Smrg	andT = FbRot24Stip(and,rot);
374706f2543Smrg	xorT = FbRot24Stip(xor,rot);
375706f2543Smrg	FbMaskStip (x, 24, leftMask, nl, rightMask);
376706f2543Smrg	if (leftMask)
377706f2543Smrg	{
378706f2543Smrg	    WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask));
379706f2543Smrg	    d++;
380706f2543Smrg	    andT = FbNext24Stip (andT);
381706f2543Smrg	    xorT = FbNext24Stip (xorT);
382706f2543Smrg	}
383706f2543Smrg	if (rightMask)
384706f2543Smrg	    WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask));
385706f2543Smrg	if (axis == X_AXIS)
386706f2543Smrg	{
387706f2543Smrg	    x1 += signdx;
388706f2543Smrg	    e += e1;
389706f2543Smrg	    if (e >= 0)
390706f2543Smrg	    {
391706f2543Smrg		e += e3;
392706f2543Smrg		dst += dstStride;
393706f2543Smrg	    }
394706f2543Smrg	}
395706f2543Smrg	else
396706f2543Smrg	{
397706f2543Smrg	    dst += dstStride;
398706f2543Smrg	    e += e1;
399706f2543Smrg	    if (e >= 0)
400706f2543Smrg	    {
401706f2543Smrg		e += e3;
402706f2543Smrg		x1 += signdx;
403706f2543Smrg	    }
404706f2543Smrg	}
405706f2543Smrg    }
406706f2543Smrg
407706f2543Smrg    fbFinishAccess (pDrawable);
408706f2543Smrg}
409706f2543Smrg
410706f2543Smrgstatic void
411706f2543SmrgfbBresDash24RRop (DrawablePtr	pDrawable,
412706f2543Smrg		  GCPtr		pGC,
413706f2543Smrg		  int		dashOffset,
414706f2543Smrg		  int		signdx,
415706f2543Smrg		  int		signdy,
416706f2543Smrg		  int		axis,
417706f2543Smrg		  int		x1,
418706f2543Smrg		  int		y1,
419706f2543Smrg		  int		e,
420706f2543Smrg		  int		e1,
421706f2543Smrg		  int		e3,
422706f2543Smrg		  int		len)
423706f2543Smrg{
424706f2543Smrg    FbStip	*dst;
425706f2543Smrg    FbStride	dstStride;
426706f2543Smrg    int		dstBpp;
427706f2543Smrg    int		dstXoff, dstYoff;
428706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
429706f2543Smrg    FbStip	andT, xorT;
430706f2543Smrg    FbStip	fgand = pPriv->and;
431706f2543Smrg    FbStip	fgxor = pPriv->xor;
432706f2543Smrg    FbStip	bgand = pPriv->bgand;
433706f2543Smrg    FbStip	bgxor = pPriv->bgxor;
434706f2543Smrg    FbStip	leftMask, rightMask;
435706f2543Smrg    int		nl;
436706f2543Smrg    FbStip	*d;
437706f2543Smrg    int		x;
438706f2543Smrg    int		rot;
439706f2543Smrg    FbDashDeclare;
440706f2543Smrg    int		dashlen;
441706f2543Smrg    Bool	even;
442706f2543Smrg    Bool	doOdd;
443706f2543Smrg
444706f2543Smrg    fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
445706f2543Smrg    doOdd = pGC->lineStyle == LineDoubleDash;
446706f2543Smrg
447706f2543Smrg    /* compute current dash position */
448706f2543Smrg    FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
449706f2543Smrg
450706f2543Smrg    dst += ((y1 + dstYoff) * dstStride);
451706f2543Smrg    x1 = (x1 + dstXoff) * 24;
452706f2543Smrg    if (signdy < 0)
453706f2543Smrg	dstStride = -dstStride;
454706f2543Smrg    signdx *= 24;
455706f2543Smrg    while (len--)
456706f2543Smrg    {
457706f2543Smrg	if (even || doOdd)
458706f2543Smrg	{
459706f2543Smrg	    if (even)
460706f2543Smrg	    {
461706f2543Smrg		andT = fgand;
462706f2543Smrg		xorT = fgxor;
463706f2543Smrg	    }
464706f2543Smrg	    else
465706f2543Smrg	    {
466706f2543Smrg		andT = bgand;
467706f2543Smrg		xorT = bgxor;
468706f2543Smrg	    }
469706f2543Smrg	    d = dst + (x1 >> FB_STIP_SHIFT);
470706f2543Smrg	    x = x1 & FB_STIP_MASK;
471706f2543Smrg	    rot = FbFirst24Rot (x);
472706f2543Smrg	    andT = FbRot24Stip (andT, rot);
473706f2543Smrg	    xorT = FbRot24Stip (xorT, rot);
474706f2543Smrg	    FbMaskStip (x, 24, leftMask, nl, rightMask);
475706f2543Smrg	    if (leftMask)
476706f2543Smrg	    {
477706f2543Smrg		WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask));
478706f2543Smrg		d++;
479706f2543Smrg		andT = FbNext24Stip (andT);
480706f2543Smrg		xorT = FbNext24Stip (xorT);
481706f2543Smrg	    }
482706f2543Smrg	    if (rightMask)
483706f2543Smrg		WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask));
484706f2543Smrg	}
485706f2543Smrg	if (axis == X_AXIS)
486706f2543Smrg	{
487706f2543Smrg	    x1 += signdx;
488706f2543Smrg	    e += e1;
489706f2543Smrg	    if (e >= 0)
490706f2543Smrg	    {
491706f2543Smrg		e += e3;
492706f2543Smrg		dst += dstStride;
493706f2543Smrg	    }
494706f2543Smrg	}
495706f2543Smrg	else
496706f2543Smrg	{
497706f2543Smrg	    dst += dstStride;
498706f2543Smrg	    e += e1;
499706f2543Smrg	    if (e >= 0)
500706f2543Smrg	    {
501706f2543Smrg		e += e3;
502706f2543Smrg		x1 += signdx;
503706f2543Smrg	    }
504706f2543Smrg	}
505706f2543Smrg	FbDashStep (dashlen, even);
506706f2543Smrg    }
507706f2543Smrg
508706f2543Smrg    fbFinishAccess (pDrawable);
509706f2543Smrg}
510706f2543Smrg#endif
511706f2543Smrg
512706f2543Smrg/*
513706f2543Smrg * For drivers that want to bail drawing some lines, this
514706f2543Smrg * function takes care of selecting the appropriate rasterizer
515706f2543Smrg * based on the contents of the specified GC.
516706f2543Smrg */
517706f2543Smrg
518706f2543SmrgFbBres *
519706f2543SmrgfbSelectBres (DrawablePtr   pDrawable,
520706f2543Smrg	      GCPtr	    pGC)
521706f2543Smrg{
522706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate(pGC);
523706f2543Smrg    int		dstBpp = pDrawable->bitsPerPixel;
524706f2543Smrg    FbBres *	bres;
525706f2543Smrg
526706f2543Smrg    if (pGC->lineStyle == LineSolid)
527706f2543Smrg    {
528706f2543Smrg	bres = fbBresFill;
529706f2543Smrg	if (pGC->fillStyle == FillSolid)
530706f2543Smrg	{
531706f2543Smrg	    bres = fbBresSolid;
532706f2543Smrg#ifdef FB_24BIT
533706f2543Smrg	    if (dstBpp == 24)
534706f2543Smrg		bres = fbBresSolid24RRop;
535706f2543Smrg#endif
536706f2543Smrg#ifndef FBNOPIXADDR
537706f2543Smrg	    if (pPriv->and == 0)
538706f2543Smrg	    {
539706f2543Smrg		switch (dstBpp) {
540706f2543Smrg		case 8:	bres = fbBresSolid8; break;
541706f2543Smrg		case 16: bres = fbBresSolid16; break;
542706f2543Smrg#ifdef FB_24BIT
543706f2543Smrg		case 24: bres = fbBresSolid24; break;
544706f2543Smrg#endif
545706f2543Smrg		case 32: bres = fbBresSolid32; break;
546706f2543Smrg		}
547706f2543Smrg	    }
548706f2543Smrg#endif
549706f2543Smrg	}
550706f2543Smrg    }
551706f2543Smrg    else
552706f2543Smrg    {
553706f2543Smrg	bres = fbBresFillDash;
554706f2543Smrg	if (pGC->fillStyle == FillSolid)
555706f2543Smrg	{
556706f2543Smrg	    bres = fbBresDash;
557706f2543Smrg#ifdef FB_24BIT
558706f2543Smrg	    if (dstBpp == 24)
559706f2543Smrg		bres = fbBresDash24RRop;
560706f2543Smrg#endif
561706f2543Smrg#ifndef FBNOPIXADDR
562706f2543Smrg	    if (pPriv->and == 0 &&
563706f2543Smrg		(pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0))
564706f2543Smrg	    {
565706f2543Smrg		switch (dstBpp) {
566706f2543Smrg		case 8:	bres = fbBresDash8; break;
567706f2543Smrg		case 16: bres = fbBresDash16; break;
568706f2543Smrg#ifdef FB_24BIT
569706f2543Smrg		case 24: bres = fbBresDash24; break;
570706f2543Smrg#endif
571706f2543Smrg		case 32: bres = fbBresDash32; break;
572706f2543Smrg		}
573706f2543Smrg	    }
574706f2543Smrg#endif
575706f2543Smrg	}
576706f2543Smrg    }
577706f2543Smrg    return bres;
578706f2543Smrg}
579706f2543Smrg
580706f2543Smrgvoid
581706f2543SmrgfbBres (DrawablePtr	pDrawable,
582706f2543Smrg	GCPtr		pGC,
583706f2543Smrg	int		dashOffset,
584706f2543Smrg	int		signdx,
585706f2543Smrg	int		signdy,
586706f2543Smrg	int		axis,
587706f2543Smrg	int		x1,
588706f2543Smrg	int		y1,
589706f2543Smrg	int		e,
590706f2543Smrg	int		e1,
591706f2543Smrg	int		e3,
592706f2543Smrg	int		len)
593706f2543Smrg{
594706f2543Smrg    (*fbSelectBres (pDrawable, pGC)) (pDrawable, pGC, dashOffset,
595706f2543Smrg				      signdx, signdy, axis, x1, y1,
596706f2543Smrg				      e, e1, e3, len);
597706f2543Smrg}
598706f2543Smrg
599706f2543Smrgvoid
600706f2543SmrgfbSegment (DrawablePtr	pDrawable,
601706f2543Smrg	   GCPtr	pGC,
602706f2543Smrg	   int		x1,
603706f2543Smrg	   int		y1,
604706f2543Smrg	   int		x2,
605706f2543Smrg	   int		y2,
606706f2543Smrg	   Bool		drawLast,
607706f2543Smrg	   int		*dashOffset)
608706f2543Smrg{
609706f2543Smrg    FbBres *	bres;
610706f2543Smrg    RegionPtr	pClip = fbGetCompositeClip(pGC);
611706f2543Smrg    BoxPtr	pBox;
612706f2543Smrg    int		nBox;
613706f2543Smrg    int		adx;		/* abs values of dx and dy */
614706f2543Smrg    int		ady;
615706f2543Smrg    int		signdx;		/* sign of dx and dy */
616706f2543Smrg    int		signdy;
617706f2543Smrg    int		e, e1, e2, e3;		/* bresenham error and increments */
618706f2543Smrg    int		len;			/* length of segment */
619706f2543Smrg    int		axis;			/* major axis */
620706f2543Smrg    int		octant;
621706f2543Smrg    int		dashoff;
622706f2543Smrg    int		doff;
623706f2543Smrg    unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
624706f2543Smrg    unsigned int oc1;	/* outcode of point 1 */
625706f2543Smrg    unsigned int oc2;	/* outcode of point 2 */
626706f2543Smrg
627706f2543Smrg    nBox = RegionNumRects (pClip);
628706f2543Smrg    pBox = RegionRects (pClip);
629706f2543Smrg
630706f2543Smrg    bres = fbSelectBres (pDrawable, pGC);
631706f2543Smrg
632706f2543Smrg    CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
633706f2543Smrg		   1, 1, octant);
634706f2543Smrg
635706f2543Smrg    if (adx > ady)
636706f2543Smrg    {
637706f2543Smrg	axis = X_AXIS;
638706f2543Smrg	e1 = ady << 1;
639706f2543Smrg	e2 = e1 - (adx << 1);
640706f2543Smrg	e = e1 - adx;
641706f2543Smrg	len = adx;
642706f2543Smrg    }
643706f2543Smrg    else
644706f2543Smrg    {
645706f2543Smrg	axis = Y_AXIS;
646706f2543Smrg	e1 = adx << 1;
647706f2543Smrg	e2 = e1 - (ady << 1);
648706f2543Smrg	e = e1 - ady;
649706f2543Smrg	SetYMajorOctant(octant);
650706f2543Smrg	len = ady;
651706f2543Smrg    }
652706f2543Smrg
653706f2543Smrg    FIXUP_ERROR (e, octant, bias);
654706f2543Smrg
655706f2543Smrg    /*
656706f2543Smrg     * Adjust error terms to compare against zero
657706f2543Smrg     */
658706f2543Smrg    e3 = e2 - e1;
659706f2543Smrg    e = e - e1;
660706f2543Smrg
661706f2543Smrg    /* we have bresenham parameters and two points.
662706f2543Smrg       all we have to do now is clip and draw.
663706f2543Smrg    */
664706f2543Smrg
665706f2543Smrg    if (drawLast)
666706f2543Smrg	len++;
667706f2543Smrg    dashoff = *dashOffset;
668706f2543Smrg    *dashOffset = dashoff + len;
669706f2543Smrg    while(nBox--)
670706f2543Smrg    {
671706f2543Smrg	oc1 = 0;
672706f2543Smrg	oc2 = 0;
673706f2543Smrg	OUTCODES(oc1, x1, y1, pBox);
674706f2543Smrg	OUTCODES(oc2, x2, y2, pBox);
675706f2543Smrg	if ((oc1 | oc2) == 0)
676706f2543Smrg	{
677706f2543Smrg	    (*bres) (pDrawable, pGC, dashoff,
678706f2543Smrg		     signdx, signdy, axis, x1, y1,
679706f2543Smrg		     e, e1, e3, len);
680706f2543Smrg	    break;
681706f2543Smrg	}
682706f2543Smrg	else if (oc1 & oc2)
683706f2543Smrg	{
684706f2543Smrg	    pBox++;
685706f2543Smrg	}
686706f2543Smrg	else
687706f2543Smrg	{
688706f2543Smrg	    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
689706f2543Smrg	    int clip1 = 0, clip2 = 0;
690706f2543Smrg	    int clipdx, clipdy;
691706f2543Smrg	    int err;
692706f2543Smrg
693706f2543Smrg	    if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1,
694706f2543Smrg			       pBox->y2-1,
695706f2543Smrg			       &new_x1, &new_y1, &new_x2, &new_y2,
696706f2543Smrg			       adx, ady, &clip1, &clip2,
697706f2543Smrg			       octant, bias, oc1, oc2) == -1)
698706f2543Smrg	    {
699706f2543Smrg		pBox++;
700706f2543Smrg		continue;
701706f2543Smrg	    }
702706f2543Smrg
703706f2543Smrg	    if (axis == X_AXIS)
704706f2543Smrg		len = abs(new_x2 - new_x1);
705706f2543Smrg	    else
706706f2543Smrg		len = abs(new_y2 - new_y1);
707706f2543Smrg	    if (clip2 != 0 || drawLast)
708706f2543Smrg		len++;
709706f2543Smrg	    if (len)
710706f2543Smrg	    {
711706f2543Smrg		/* unwind bresenham error term to first point */
712706f2543Smrg		doff = dashoff;
713706f2543Smrg		err = e;
714706f2543Smrg		if (clip1)
715706f2543Smrg		{
716706f2543Smrg		    clipdx = abs(new_x1 - x1);
717706f2543Smrg		    clipdy = abs(new_y1 - y1);
718706f2543Smrg		    if (axis == X_AXIS)
719706f2543Smrg		    {
720706f2543Smrg			doff += clipdx;
721706f2543Smrg			err  += e3 * clipdy + e1 * clipdx;
722706f2543Smrg		    }
723706f2543Smrg		    else
724706f2543Smrg		    {
725706f2543Smrg			doff += clipdy;
726706f2543Smrg			err  += e3 * clipdx + e1 * clipdy;
727706f2543Smrg		    }
728706f2543Smrg		}
729706f2543Smrg		(*bres) (pDrawable, pGC, doff,
730706f2543Smrg			 signdx, signdy, axis, new_x1, new_y1,
731706f2543Smrg			 err, e1, e3, len);
732706f2543Smrg	    }
733706f2543Smrg	    pBox++;
734706f2543Smrg	}
735706f2543Smrg    } /* while (nBox--) */
736706f2543Smrg}
737