diff options
Diffstat (limited to 'xorg-server/fb/fbseg.c')
-rw-r--r-- | xorg-server/fb/fbseg.c | 1458 |
1 files changed, 722 insertions, 736 deletions
diff --git a/xorg-server/fb/fbseg.c b/xorg-server/fb/fbseg.c index 8a68857f7..5a458fe51 100644 --- a/xorg-server/fb/fbseg.c +++ b/xorg-server/fb/fbseg.c @@ -1,736 +1,722 @@ -/*
- * Copyright © 1998 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdlib.h>
-
-#include "fb.h"
-#include "miline.h"
-
-#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
- ((dir < 0) ? FbStipLeft(mask,bpp) : \
- FbStipRight(mask,bpp)))
-
-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)
-{
- FbStip *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- FbGCPrivPtr pPriv = fbGetGCPrivate (pGC);
- FbStip and = (FbStip) pPriv->and;
- FbStip xor = (FbStip) pPriv->xor;
- FbStip mask, mask0;
- FbStip bits;
-
- fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- dst += ((y1 + dstYoff) * dstStride);
- x1 = (x1 + dstXoff) * dstBpp;
- dst += x1 >> FB_STIP_SHIFT;
- x1 &= FB_STIP_MASK;
- mask0 = FbStipMask(0, dstBpp);
- mask = FbStipRight (mask0, x1);
- if (signdx < 0)
- mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp);
- if (signdy < 0)
- dstStride = -dstStride;
- if (axis == X_AXIS)
- {
- bits = 0;
- while (len--)
- {
- bits |= mask;
- mask = fbBresShiftMask(mask,signdx,dstBpp);
- if (!mask)
- {
- WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
- bits = 0;
- dst += signdx;
- mask = mask0;
- }
- e += e1;
- if (e >= 0)
- {
- WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
- bits = 0;
- dst += dstStride;
- e += e3;
- }
- }
- if (bits)
- WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
- }
- else
- {
- while (len--)
- {
- WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask));
- dst += dstStride;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- mask = fbBresShiftMask(mask,signdx,dstBpp);
- if (!mask)
- {
- dst += signdx;
- mask = mask0;
- }
- }
- }
- }
-
- fbFinishAccess (pDrawable);
-}
-
-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)
-{
- FbStip *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- FbGCPrivPtr pPriv = fbGetGCPrivate (pGC);
- FbStip and = (FbStip) pPriv->and;
- FbStip xor = (FbStip) pPriv->xor;
- FbStip bgand = (FbStip) pPriv->bgand;
- FbStip bgxor = (FbStip) pPriv->bgxor;
- FbStip mask, mask0;
- FbDashDeclare;
- int dashlen;
- Bool even;
- Bool doOdd;
-
- fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- doOdd = pGC->lineStyle == LineDoubleDash;
-
- FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
-
- dst += ((y1 + dstYoff) * dstStride);
- x1 = (x1 + dstXoff) * dstBpp;
- dst += x1 >> FB_STIP_SHIFT;
- x1 &= FB_STIP_MASK;
- mask0 = FbStipMask(0, dstBpp);
- mask = FbStipRight (mask0, x1);
- if (signdx < 0)
- mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp);
- if (signdy < 0)
- dstStride = -dstStride;
- while (len--)
- {
- if (even)
- WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask));
- else if (doOdd)
- WRITE(dst, FbDoMaskRRop (READ(dst), bgand, bgxor, mask));
- if (axis == X_AXIS)
- {
- mask = fbBresShiftMask(mask,signdx,dstBpp);
- if (!mask)
- {
- dst += signdx;
- mask = mask0;
- }
- e += e1;
- if (e >= 0)
- {
- dst += dstStride;
- e += e3;
- }
- }
- else
- {
- dst += dstStride;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- mask = fbBresShiftMask(mask,signdx,dstBpp);
- if (!mask)
- {
- dst += signdx;
- mask = mask0;
- }
- }
- }
- FbDashStep (dashlen, even);
- }
-
- fbFinishAccess (pDrawable);
-}
-
-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)
-{
- while (len--)
- {
- fbFill (pDrawable, pGC, x1, y1, 1, 1);
- if (axis == X_AXIS)
- {
- x1 += signdx;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- y1 += signdy;
- }
- }
- else
- {
- y1 += signdy;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- x1 += signdx;
- }
- }
- }
-}
-
-static void
-fbSetFg (DrawablePtr pDrawable,
- GCPtr pGC,
- Pixel fg)
-{
- if (fg != pGC->fgPixel)
- {
- ChangeGCVal val;
- val.val = fg;
- ChangeGC (NullClient, pGC, GCForeground, &val);
- ValidateGC (pDrawable, pGC);
- }
-}
-
-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)
-{
- FbGCPrivPtr pPriv = fbGetGCPrivate (pGC);
- FbDashDeclare;
- int dashlen;
- Bool even;
- Bool doOdd;
- Bool doBg;
- Pixel fg, bg;
-
- fg = pGC->fgPixel;
- bg = pGC->bgPixel;
-
- /* whether to fill the odd dashes */
- doOdd = pGC->lineStyle == LineDoubleDash;
- /* whether to switch fg to bg when filling odd dashes */
- doBg = doOdd && (pGC->fillStyle == FillSolid ||
- pGC->fillStyle == FillStippled);
-
- /* compute current dash position */
- FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
-
- while (len--)
- {
- if (even || doOdd)
- {
- if (doBg)
- {
- if (even)
- fbSetFg (pDrawable, pGC, fg);
- else
- fbSetFg (pDrawable, pGC, bg);
- }
- fbFill (pDrawable, pGC, x1, y1, 1, 1);
- }
- if (axis == X_AXIS)
- {
- x1 += signdx;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- y1 += signdy;
- }
- }
- else
- {
- y1 += signdy;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- x1 += signdx;
- }
- }
- FbDashStep (dashlen, even);
- }
- if (doBg)
- fbSetFg (pDrawable, pGC, fg);
-}
-
-#ifdef FB_24BIT
-static void
-fbBresSolid24RRop (DrawablePtr pDrawable,
- GCPtr pGC,
- int dashOffset,
- int signdx,
- int signdy,
- int axis,
- int x1,
- int y1,
- int e,
- int e1,
- int e3,
- int len)
-{
- FbStip *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- FbGCPrivPtr pPriv = fbGetGCPrivate (pGC);
- FbStip and = pPriv->and;
- FbStip xor = pPriv->xor;
- FbStip leftMask, rightMask;
- int nl;
- FbStip *d;
- int x;
- int rot;
- FbStip andT, xorT;
-
- fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- dst += ((y1 + dstYoff) * dstStride);
- x1 = (x1 + dstXoff) * 24;
- if (signdy < 0)
- dstStride = -dstStride;
- signdx *= 24;
- while (len--)
- {
- d = dst + (x1 >> FB_STIP_SHIFT);
- x = x1 & FB_STIP_MASK;
- rot = FbFirst24Rot (x);
- andT = FbRot24Stip(and,rot);
- xorT = FbRot24Stip(xor,rot);
- FbMaskStip (x, 24, leftMask, nl, rightMask);
- if (leftMask)
- {
- WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask));
- d++;
- andT = FbNext24Stip (andT);
- xorT = FbNext24Stip (xorT);
- }
- if (rightMask)
- WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask));
- if (axis == X_AXIS)
- {
- x1 += signdx;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- dst += dstStride;
- }
- }
- else
- {
- dst += dstStride;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- x1 += signdx;
- }
- }
- }
-
- fbFinishAccess (pDrawable);
-}
-
-static void
-fbBresDash24RRop (DrawablePtr pDrawable,
- GCPtr pGC,
- int dashOffset,
- int signdx,
- int signdy,
- int axis,
- int x1,
- int y1,
- int e,
- int e1,
- int e3,
- int len)
-{
- FbStip *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- FbGCPrivPtr pPriv = fbGetGCPrivate (pGC);
- FbStip andT, xorT;
- FbStip fgand = pPriv->and;
- FbStip fgxor = pPriv->xor;
- FbStip bgand = pPriv->bgand;
- FbStip bgxor = pPriv->bgxor;
- FbStip leftMask, rightMask;
- int nl;
- FbStip *d;
- int x;
- int rot;
- FbDashDeclare;
- int dashlen;
- Bool even;
- Bool doOdd;
-
- fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- doOdd = pGC->lineStyle == LineDoubleDash;
-
- /* compute current dash position */
- FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
-
- dst += ((y1 + dstYoff) * dstStride);
- x1 = (x1 + dstXoff) * 24;
- if (signdy < 0)
- dstStride = -dstStride;
- signdx *= 24;
- while (len--)
- {
- if (even || doOdd)
- {
- if (even)
- {
- andT = fgand;
- xorT = fgxor;
- }
- else
- {
- andT = bgand;
- xorT = bgxor;
- }
- d = dst + (x1 >> FB_STIP_SHIFT);
- x = x1 & FB_STIP_MASK;
- rot = FbFirst24Rot (x);
- andT = FbRot24Stip (andT, rot);
- xorT = FbRot24Stip (xorT, rot);
- FbMaskStip (x, 24, leftMask, nl, rightMask);
- if (leftMask)
- {
- WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask));
- d++;
- andT = FbNext24Stip (andT);
- xorT = FbNext24Stip (xorT);
- }
- if (rightMask)
- WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask));
- }
- if (axis == X_AXIS)
- {
- x1 += signdx;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- dst += dstStride;
- }
- }
- else
- {
- dst += dstStride;
- e += e1;
- if (e >= 0)
- {
- e += e3;
- x1 += signdx;
- }
- }
- FbDashStep (dashlen, even);
- }
-
- fbFinishAccess (pDrawable);
-}
-#endif
-
-/*
- * For drivers that want to bail drawing some lines, this
- * function takes care of selecting the appropriate rasterizer
- * based on the contents of the specified GC.
- */
-
-FbBres *
-fbSelectBres (DrawablePtr pDrawable,
- GCPtr pGC)
-{
- FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
- int dstBpp = pDrawable->bitsPerPixel;
- FbBres * bres;
-
- if (pGC->lineStyle == LineSolid)
- {
- bres = fbBresFill;
- if (pGC->fillStyle == FillSolid)
- {
- bres = fbBresSolid;
-#ifdef FB_24BIT
- if (dstBpp == 24)
- bres = fbBresSolid24RRop;
-#endif
-#ifndef FBNOPIXADDR
- if (pPriv->and == 0)
- {
- switch (dstBpp) {
- case 8: bres = fbBresSolid8; break;
- case 16: bres = fbBresSolid16; break;
-#ifdef FB_24BIT
- case 24: bres = fbBresSolid24; break;
-#endif
- case 32: bres = fbBresSolid32; break;
- }
- }
-#endif
- }
- }
- else
- {
- bres = fbBresFillDash;
- if (pGC->fillStyle == FillSolid)
- {
- bres = fbBresDash;
-#ifdef FB_24BIT
- if (dstBpp == 24)
- bres = fbBresDash24RRop;
-#endif
-#ifndef FBNOPIXADDR
- if (pPriv->and == 0 &&
- (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0))
- {
- switch (dstBpp) {
- case 8: bres = fbBresDash8; break;
- case 16: bres = fbBresDash16; break;
-#ifdef FB_24BIT
- case 24: bres = fbBresDash24; break;
-#endif
- case 32: bres = fbBresDash32; break;
- }
- }
-#endif
- }
- }
- return bres;
-}
-
-void
-fbBres (DrawablePtr pDrawable,
- GCPtr pGC,
- int dashOffset,
- int signdx,
- int signdy,
- int axis,
- int x1,
- int y1,
- int e,
- int e1,
- int e3,
- int len)
-{
- (*fbSelectBres (pDrawable, pGC)) (pDrawable, pGC, dashOffset,
- signdx, signdy, axis, x1, y1,
- e, e1, e3, len);
-}
-
-void
-fbSegment (DrawablePtr pDrawable,
- GCPtr pGC,
- int x1,
- int y1,
- int x2,
- int y2,
- Bool drawLast,
- int *dashOffset)
-{
- FbBres * bres;
- RegionPtr pClip = fbGetCompositeClip(pGC);
- BoxPtr pBox;
- int nBox;
- int adx; /* abs values of dx and dy */
- int ady;
- int signdx; /* sign of dx and dy */
- int signdy;
- int e, e1, e2, e3; /* bresenham error and increments */
- int len; /* length of segment */
- int axis; /* major axis */
- int octant;
- int dashoff;
- int doff;
- unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
- unsigned int oc1; /* outcode of point 1 */
- unsigned int oc2; /* outcode of point 2 */
-
- nBox = RegionNumRects (pClip);
- pBox = RegionRects (pClip);
-
- bres = fbSelectBres (pDrawable, pGC);
-
- CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
- 1, 1, octant);
-
- if (adx > ady)
- {
- axis = X_AXIS;
- e1 = ady << 1;
- e2 = e1 - (adx << 1);
- e = e1 - adx;
- len = adx;
- }
- else
- {
- axis = Y_AXIS;
- e1 = adx << 1;
- e2 = e1 - (ady << 1);
- e = e1 - ady;
- SetYMajorOctant(octant);
- len = ady;
- }
-
- FIXUP_ERROR (e, octant, bias);
-
- /*
- * Adjust error terms to compare against zero
- */
- e3 = e2 - e1;
- e = e - e1;
-
- /* we have bresenham parameters and two points.
- all we have to do now is clip and draw.
- */
-
- if (drawLast)
- len++;
- dashoff = *dashOffset;
- *dashOffset = dashoff + len;
- while(nBox--)
- {
- oc1 = 0;
- oc2 = 0;
- OUTCODES(oc1, x1, y1, pBox);
- OUTCODES(oc2, x2, y2, pBox);
- if ((oc1 | oc2) == 0)
- {
- (*bres) (pDrawable, pGC, dashoff,
- signdx, signdy, axis, x1, y1,
- e, e1, e3, len);
- break;
- }
- else if (oc1 & oc2)
- {
- pBox++;
- }
- else
- {
- int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
- int clip1 = 0, clip2 = 0;
- int clipdx, clipdy;
- int err;
-
- if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1,
- pBox->y2-1,
- &new_x1, &new_y1, &new_x2, &new_y2,
- adx, ady, &clip1, &clip2,
- octant, bias, oc1, oc2) == -1)
- {
- pBox++;
- continue;
- }
-
- if (axis == X_AXIS)
- len = abs(new_x2 - new_x1);
- else
- len = abs(new_y2 - new_y1);
- if (clip2 != 0 || drawLast)
- len++;
- if (len)
- {
- /* unwind bresenham error term to first point */
- doff = dashoff;
- err = e;
- if (clip1)
- {
- clipdx = abs(new_x1 - x1);
- clipdy = abs(new_y1 - y1);
- if (axis == X_AXIS)
- {
- doff += clipdx;
- err += e3 * clipdy + e1 * clipdx;
- }
- else
- {
- doff += clipdy;
- err += e3 * clipdx + e1 * clipdy;
- }
- }
- (*bres) (pDrawable, pGC, doff,
- signdx, signdy, axis, new_x1, new_y1,
- err, e1, e3, len);
- }
- pBox++;
- }
- } /* while (nBox--) */
-}
+/* + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdlib.h> + +#include "fb.h" +#include "miline.h" + +#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \ + ((dir < 0) ? FbStipLeft(mask,bpp) : \ + FbStipRight(mask,bpp))) + +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) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip and = (FbStip) pPriv->and; + FbStip xor = (FbStip) pPriv->xor; + FbStip mask, mask0; + FbStip bits; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * dstBpp; + dst += x1 >> FB_STIP_SHIFT; + x1 &= FB_STIP_MASK; + mask0 = FbStipMask(0, dstBpp); + mask = FbStipRight (mask0, x1); + if (signdx < 0) + mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp); + if (signdy < 0) + dstStride = -dstStride; + if (axis == X_AXIS) + { + bits = 0; + while (len--) + { + bits |= mask; + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits)); + bits = 0; + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) + { + WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits)); + bits = 0; + dst += dstStride; + e += e3; + } + } + if (bits) + WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits)); + } + else + { + while (len--) + { + WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask)); + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + dst += signdx; + mask = mask0; + } + } + } + } + + fbFinishAccess (pDrawable); +} + +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) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip and = (FbStip) pPriv->and; + FbStip xor = (FbStip) pPriv->xor; + FbStip bgand = (FbStip) pPriv->bgand; + FbStip bgxor = (FbStip) pPriv->bgxor; + FbStip mask, mask0; + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + FbDashInit (pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * dstBpp; + dst += x1 >> FB_STIP_SHIFT; + x1 &= FB_STIP_MASK; + mask0 = FbStipMask(0, dstBpp); + mask = FbStipRight (mask0, x1); + if (signdx < 0) + mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp); + if (signdy < 0) + dstStride = -dstStride; + while (len--) + { + if (even) + WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask)); + else if (doOdd) + WRITE(dst, FbDoMaskRRop (READ(dst), bgand, bgxor, mask)); + if (axis == X_AXIS) + { + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) + { + dst += dstStride; + e += e3; + } + } + else + { + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + dst += signdx; + mask = mask0; + } + } + } + FbDashStep (dashlen, even); + } + + fbFinishAccess (pDrawable); +} + +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) +{ + while (len--) + { + fbFill (pDrawable, pGC, x1, y1, 1, 1); + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + y1 += signdy; + } + } + else + { + y1 += signdy; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + } +} + +static void +fbSetFg (DrawablePtr pDrawable, + GCPtr pGC, + Pixel fg) +{ + if (fg != pGC->fgPixel) + { + ChangeGCVal val; + val.val = fg; + ChangeGC (NullClient, pGC, GCForeground, &val); + ValidateGC (pDrawable, pGC); + } +} + +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) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + Bool doBg; + Pixel fg, bg; + + fg = pGC->fgPixel; + bg = pGC->bgPixel; + + /* whether to fill the odd dashes */ + doOdd = pGC->lineStyle == LineDoubleDash; + /* whether to switch fg to bg when filling odd dashes */ + doBg = doOdd && (pGC->fillStyle == FillSolid || + pGC->fillStyle == FillStippled); + + /* compute current dash position */ + FbDashInit (pGC, pPriv, dashOffset, dashlen, even); + + while (len--) + { + if (even || doOdd) + { + if (doBg) + { + if (even) + fbSetFg (pDrawable, pGC, fg); + else + fbSetFg (pDrawable, pGC, bg); + } + fbFill (pDrawable, pGC, x1, y1, 1, 1); + } + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + y1 += signdy; + } + } + else + { + y1 += signdy; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + FbDashStep (dashlen, even); + } + if (doBg) + fbSetFg (pDrawable, pGC, fg); +} + +static void +fbBresSolid24RRop (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip and = pPriv->and; + FbStip xor = pPriv->xor; + FbStip leftMask, rightMask; + int nl; + FbStip *d; + int x; + int rot; + FbStip andT, xorT; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) + { + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot (x); + andT = FbRot24Stip(and,rot); + xorT = FbRot24Stip(xor,rot); + FbMaskStip (x, 24, leftMask, nl, rightMask); + if (leftMask) + { + WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask)); + d++; + andT = FbNext24Stip (andT); + xorT = FbNext24Stip (xorT); + } + if (rightMask) + WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask)); + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + dst += dstStride; + } + } + else + { + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + } + + fbFinishAccess (pDrawable); +} + +static void +fbBresDash24RRop (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip andT, xorT; + FbStip fgand = pPriv->and; + FbStip fgxor = pPriv->xor; + FbStip bgand = pPriv->bgand; + FbStip bgxor = pPriv->bgxor; + FbStip leftMask, rightMask; + int nl; + FbStip *d; + int x; + int rot; + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + /* compute current dash position */ + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) + { + if (even || doOdd) + { + if (even) + { + andT = fgand; + xorT = fgxor; + } + else + { + andT = bgand; + xorT = bgxor; + } + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot (x); + andT = FbRot24Stip (andT, rot); + xorT = FbRot24Stip (xorT, rot); + FbMaskStip (x, 24, leftMask, nl, rightMask); + if (leftMask) + { + WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask)); + d++; + andT = FbNext24Stip (andT); + xorT = FbNext24Stip (xorT); + } + if (rightMask) + WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask)); + } + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + dst += dstStride; + } + } + else + { + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + FbDashStep (dashlen, even); + } + + fbFinishAccess (pDrawable); +} + +/* + * For drivers that want to bail drawing some lines, this + * function takes care of selecting the appropriate rasterizer + * based on the contents of the specified GC. + */ + +FbBres * +fbSelectBres (DrawablePtr pDrawable, + GCPtr pGC) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + int dstBpp = pDrawable->bitsPerPixel; + FbBres * bres; + + if (pGC->lineStyle == LineSolid) + { + bres = fbBresFill; + if (pGC->fillStyle == FillSolid) + { + bres = fbBresSolid; + if (dstBpp == 24) + bres = fbBresSolid24RRop; + if (pPriv->and == 0) + { + switch (dstBpp) { + case 8: bres = fbBresSolid8; break; + case 16: bres = fbBresSolid16; break; + case 24: bres = fbBresSolid24; break; + case 32: bres = fbBresSolid32; break; + } + } + } + } + else + { + bres = fbBresFillDash; + if (pGC->fillStyle == FillSolid) + { + bres = fbBresDash; + if (dstBpp == 24) + bres = fbBresDash24RRop; + if (pPriv->and == 0 && + (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) + { + switch (dstBpp) { + case 8: bres = fbBresDash8; break; + case 16: bres = fbBresDash16; break; + case 24: bres = fbBresDash24; break; + case 32: bres = fbBresDash32; break; + } + } + } + } + return bres; +} + +void +fbBres (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + (*fbSelectBres (pDrawable, pGC)) (pDrawable, pGC, dashOffset, + signdx, signdy, axis, x1, y1, + e, e1, e3, len); +} + +void +fbSegment (DrawablePtr pDrawable, + GCPtr pGC, + int x1, + int y1, + int x2, + int y2, + Bool drawLast, + int *dashOffset) +{ + FbBres * bres; + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pBox; + int nBox; + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2, e3; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + int dashoff; + int doff; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + unsigned int oc1; /* outcode of point 1 */ + unsigned int oc2; /* outcode of point 2 */ + + nBox = RegionNumRects (pClip); + pBox = RegionRects (pClip); + + bres = fbSelectBres (pDrawable, pGC); + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, + 1, 1, octant); + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + } + else + { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + len = ady; + } + + FIXUP_ERROR (e, octant, bias); + + /* + * Adjust error terms to compare against zero + */ + e3 = e2 - e1; + e = e - e1; + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + if (drawLast) + len++; + dashoff = *dashOffset; + *dashOffset = dashoff + len; + while(nBox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pBox); + OUTCODES(oc2, x2, y2, pBox); + if ((oc1 | oc2) == 0) + { + (*bres) (pDrawable, pGC, dashoff, + signdx, signdy, axis, x1, y1, + e, e1, e3, len); + break; + } + else if (oc1 & oc2) + { + pBox++; + } + else + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + + if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1, + pBox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pBox++; + continue; + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); + if (clip2 != 0 || drawLast) + len++; + if (len) + { + /* unwind bresenham error term to first point */ + doff = dashoff; + err = e; + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + { + doff += clipdx; + err += e3 * clipdy + e1 * clipdx; + } + else + { + doff += clipdy; + err += e3 * clipdx + e1 * clipdy; + } + } + (*bres) (pDrawable, pGC, doff, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e3, len); + } + pBox++; + } + } /* while (nBox--) */ +} |