2 * Copyright © 1998 Keith Packard
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.
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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
32 #define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
33 ((dir < 0) ? FbStipLeft(mask,bpp) : \
34 FbStipRight(mask,bpp)))
37 fbBresSolid(DrawablePtr pDrawable
,
42 int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
48 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
49 FbStip
and = (FbStip
) pPriv
->and;
50 FbStip
xor = (FbStip
) pPriv
->xor;
54 fbGetStipDrawable(pDrawable
, dst
, dstStride
, dstBpp
, dstXoff
, dstYoff
);
55 dst
+= ((y1
+ dstYoff
) * dstStride
);
56 x1
= (x1
+ dstXoff
) * dstBpp
;
57 dst
+= x1
>> FB_STIP_SHIFT
;
59 mask0
= FbStipMask(0, dstBpp
);
60 mask
= FbStipRight(mask0
, x1
);
62 mask0
= FbStipRight(mask0
, FB_STIP_UNIT
- dstBpp
);
64 dstStride
= -dstStride
;
69 mask
= fbBresShiftMask(mask
, signdx
, dstBpp
);
71 WRITE(dst
, FbDoMaskRRop(READ(dst
), and, xor, bits
));
78 WRITE(dst
, FbDoMaskRRop(READ(dst
), and, xor, bits
));
85 WRITE(dst
, FbDoMaskRRop(READ(dst
), and, xor, bits
));
89 WRITE(dst
, FbDoMaskRRop(READ(dst
), and, xor, mask
));
94 mask
= fbBresShiftMask(mask
, signdx
, dstBpp
);
103 fbFinishAccess(pDrawable
);
107 fbBresDash(DrawablePtr pDrawable
,
111 int signdy
, int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
116 int dstXoff
, dstYoff
;
117 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
118 FbStip
and = (FbStip
) pPriv
->and;
119 FbStip
xor = (FbStip
) pPriv
->xor;
120 FbStip bgand
= (FbStip
) pPriv
->bgand
;
121 FbStip bgxor
= (FbStip
) pPriv
->bgxor
;
129 fbGetStipDrawable(pDrawable
, dst
, dstStride
, dstBpp
, dstXoff
, dstYoff
);
130 doOdd
= pGC
->lineStyle
== LineDoubleDash
;
132 FbDashInit(pGC
, pPriv
, dashOffset
, dashlen
, even
);
134 dst
+= ((y1
+ dstYoff
) * dstStride
);
135 x1
= (x1
+ dstXoff
) * dstBpp
;
136 dst
+= x1
>> FB_STIP_SHIFT
;
138 mask0
= FbStipMask(0, dstBpp
);
139 mask
= FbStipRight(mask0
, x1
);
141 mask0
= FbStipRight(mask0
, FB_STIP_UNIT
- dstBpp
);
143 dstStride
= -dstStride
;
146 WRITE(dst
, FbDoMaskRRop(READ(dst
), and, xor, mask
));
148 WRITE(dst
, FbDoMaskRRop(READ(dst
), bgand
, bgxor
, mask
));
149 if (axis
== X_AXIS
) {
150 mask
= fbBresShiftMask(mask
, signdx
, dstBpp
);
166 mask
= fbBresShiftMask(mask
, signdx
, dstBpp
);
173 FbDashStep(dashlen
, even
);
176 fbFinishAccess(pDrawable
);
180 fbBresFill(DrawablePtr pDrawable
,
184 int signdy
, int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
187 fbFill(pDrawable
, pGC
, x1
, y1
, 1, 1);
188 if (axis
== X_AXIS
) {
208 fbSetFg(DrawablePtr pDrawable
, GCPtr pGC
, Pixel fg
)
210 if (fg
!= pGC
->fgPixel
) {
214 ChangeGC(NullClient
, pGC
, GCForeground
, &val
);
215 ValidateGC(pDrawable
, pGC
);
220 fbBresFillDash(DrawablePtr pDrawable
,
225 int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
227 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
239 /* whether to fill the odd dashes */
240 doOdd
= pGC
->lineStyle
== LineDoubleDash
;
241 /* whether to switch fg to bg when filling odd dashes */
242 doBg
= doOdd
&& (pGC
->fillStyle
== FillSolid
||
243 pGC
->fillStyle
== FillStippled
);
245 /* compute current dash position */
246 FbDashInit(pGC
, pPriv
, dashOffset
, dashlen
, even
);
252 fbSetFg(pDrawable
, pGC
, fg
);
254 fbSetFg(pDrawable
, pGC
, bg
);
256 fbFill(pDrawable
, pGC
, x1
, y1
, 1, 1);
258 if (axis
== X_AXIS
) {
274 FbDashStep(dashlen
, even
);
277 fbSetFg(pDrawable
, pGC
, fg
);
281 fbBresSolid24RRop(DrawablePtr pDrawable
,
286 int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
291 int dstXoff
, dstYoff
;
292 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
293 FbStip
and = pPriv
->and;
294 FbStip
xor = pPriv
->xor;
295 FbStip leftMask
, rightMask
;
302 fbGetStipDrawable(pDrawable
, dst
, dstStride
, dstBpp
, dstXoff
, dstYoff
);
303 dst
+= ((y1
+ dstYoff
) * dstStride
);
304 x1
= (x1
+ dstXoff
) * 24;
306 dstStride
= -dstStride
;
309 d
= dst
+ (x1
>> FB_STIP_SHIFT
);
310 x
= x1
& FB_STIP_MASK
;
311 rot
= FbFirst24Rot(x
);
312 andT
= FbRot24Stip(and, rot
);
313 xorT
= FbRot24Stip(xor, rot
);
314 FbMaskStip(x
, 24, leftMask
, nl
, rightMask
);
316 WRITE(d
, FbDoMaskRRop(READ(d
), andT
, xorT
, leftMask
));
318 andT
= FbNext24Stip(andT
);
319 xorT
= FbNext24Stip(xorT
);
322 WRITE(d
, FbDoMaskRRop(READ(d
), andT
, xorT
, rightMask
));
323 if (axis
== X_AXIS
) {
341 fbFinishAccess(pDrawable
);
345 fbBresDash24RRop(DrawablePtr pDrawable
,
350 int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
355 int dstXoff
, dstYoff
;
356 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
358 FbStip fgand
= pPriv
->and;
359 FbStip fgxor
= pPriv
->xor;
360 FbStip bgand
= pPriv
->bgand
;
361 FbStip bgxor
= pPriv
->bgxor
;
362 FbStip leftMask
, rightMask
;
373 fbGetStipDrawable(pDrawable
, dst
, dstStride
, dstBpp
, dstXoff
, dstYoff
);
374 doOdd
= pGC
->lineStyle
== LineDoubleDash
;
376 /* compute current dash position */
377 FbDashInit(pGC
, pPriv
, dashOffset
, dashlen
, even
);
379 dst
+= ((y1
+ dstYoff
) * dstStride
);
380 x1
= (x1
+ dstXoff
) * 24;
382 dstStride
= -dstStride
;
394 d
= dst
+ (x1
>> FB_STIP_SHIFT
);
395 x
= x1
& FB_STIP_MASK
;
396 rot
= FbFirst24Rot(x
);
397 andT
= FbRot24Stip(andT
, rot
);
398 xorT
= FbRot24Stip(xorT
, rot
);
399 FbMaskStip(x
, 24, leftMask
, nl
, rightMask
);
401 WRITE(d
, FbDoMaskRRop(READ(d
), andT
, xorT
, leftMask
));
403 andT
= FbNext24Stip(andT
);
404 xorT
= FbNext24Stip(xorT
);
407 WRITE(d
, FbDoMaskRRop(READ(d
), andT
, xorT
, rightMask
));
409 if (axis
== X_AXIS
) {
425 FbDashStep(dashlen
, even
);
428 fbFinishAccess(pDrawable
);
432 * For drivers that want to bail drawing some lines, this
433 * function takes care of selecting the appropriate rasterizer
434 * based on the contents of the specified GC.
438 fbSelectBres(DrawablePtr pDrawable
, GCPtr pGC
)
440 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
441 int dstBpp
= pDrawable
->bitsPerPixel
;
444 if (pGC
->lineStyle
== LineSolid
) {
446 if (pGC
->fillStyle
== FillSolid
) {
449 bres
= fbBresSolid24RRop
;
450 if (pPriv
->and == 0) {
456 bres
= fbBresSolid16
;
459 bres
= fbBresSolid24
;
462 bres
= fbBresSolid32
;
469 bres
= fbBresFillDash
;
470 if (pGC
->fillStyle
== FillSolid
) {
473 bres
= fbBresDash24RRop
;
474 if (pPriv
->and == 0 &&
475 (pGC
->lineStyle
== LineOnOffDash
|| pPriv
->bgand
== 0)) {
497 fbBres(DrawablePtr pDrawable
,
501 int signdy
, int axis
, int x1
, int y1
, int e
, int e1
, int e3
, int len
)
503 (*fbSelectBres(pDrawable
, pGC
)) (pDrawable
, pGC
, dashOffset
,
504 signdx
, signdy
, axis
, x1
, y1
,
509 fbSegment(DrawablePtr pDrawable
,
511 int x1
, int y1
, int x2
, int y2
, Bool drawLast
, int *dashOffset
)
514 RegionPtr pClip
= fbGetCompositeClip(pGC
);
517 int adx
; /* abs values of dx and dy */
519 int signdx
; /* sign of dx and dy */
521 int e
, e1
, e2
, e3
; /* bresenham error and increments */
522 int len
; /* length of segment */
523 int axis
; /* major axis */
527 unsigned int bias
= miGetZeroLineBias(pDrawable
->pScreen
);
528 unsigned int oc1
; /* outcode of point 1 */
529 unsigned int oc2
; /* outcode of point 2 */
531 nBox
= RegionNumRects(pClip
);
532 pBox
= RegionRects(pClip
);
534 bres
= fbSelectBres(pDrawable
, pGC
);
536 CalcLineDeltas(x1
, y1
, x2
, y2
, adx
, ady
, signdx
, signdy
, 1, 1, octant
);
541 e2
= e1
- (adx
<< 1);
548 e2
= e1
- (ady
<< 1);
550 SetYMajorOctant(octant
);
554 FIXUP_ERROR(e
, octant
, bias
);
557 * Adjust error terms to compare against zero
562 /* we have bresenham parameters and two points.
563 all we have to do now is clip and draw.
568 dashoff
= *dashOffset
;
569 *dashOffset
= dashoff
+ len
;
573 OUTCODES(oc1
, x1
, y1
, pBox
);
574 OUTCODES(oc2
, x2
, y2
, pBox
);
575 if ((oc1
| oc2
) == 0) {
576 (*bres
) (pDrawable
, pGC
, dashoff
,
577 signdx
, signdy
, axis
, x1
, y1
, e
, e1
, e3
, len
);
580 else if (oc1
& oc2
) {
584 int new_x1
= x1
, new_y1
= y1
, new_x2
= x2
, new_y2
= y2
;
585 int clip1
= 0, clip2
= 0;
589 if (miZeroClipLine(pBox
->x1
, pBox
->y1
, pBox
->x2
- 1,
591 &new_x1
, &new_y1
, &new_x2
, &new_y2
,
592 adx
, ady
, &clip1
, &clip2
,
593 octant
, bias
, oc1
, oc2
) == -1) {
599 len
= abs(new_x2
- new_x1
);
601 len
= abs(new_y2
- new_y1
);
602 if (clip2
!= 0 || drawLast
)
605 /* unwind bresenham error term to first point */
609 clipdx
= abs(new_x1
- x1
);
610 clipdy
= abs(new_y1
- y1
);
611 if (axis
== X_AXIS
) {
613 err
+= e3
* clipdy
+ e1
* clipdx
;
617 err
+= e3
* clipdx
+ e1
* clipdy
;
620 (*bres
) (pDrawable
, pGC
, doff
,
621 signdx
, signdy
, axis
, new_x1
, new_y1
,
626 } /* while (nBox--) */