diff options
author | Dave Airlie <airlied@redhat.com> | 2011-04-21 10:04:00 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-04-21 10:04:00 +1000 |
commit | ddeddda20779bd1843503f40f880ca8b785548ef (patch) | |
tree | 259bc09247028c825f654867691e0a60ffc515dc | |
parent | 08255ec621eff77a9a259234061c482ab39884b5 (diff) |
migrate the rest of the mi stuff below the drv boundary.
now impedance has all the GC entry points, and fb points at the drv
fallbacks.
-rw-r--r-- | dix/impedgc.c | 114 | ||||
-rw-r--r-- | dix/impedscrn.c | 18 | ||||
-rw-r--r-- | drv/Makefile.am | 12 | ||||
-rw-r--r-- | drv/drv_mi.h | 88 | ||||
-rw-r--r-- | drv/drvfillarc.c | 174 | ||||
-rw-r--r-- | drv/drvfillarc.h | 2 | ||||
-rw-r--r-- | drv/drvline.h | 173 | ||||
-rw-r--r-- | drv/drvpoly.c | 123 | ||||
-rw-r--r-- | drv/drvpoly.h | 207 | ||||
-rw-r--r-- | drv/drvpolycon.c | 247 | ||||
-rw-r--r-- | drv/drvpolygen.c | 230 | ||||
-rw-r--r-- | drv/drvpolyrect.c | 187 | ||||
-rw-r--r-- | drv/drvpolyseg.c (renamed from drv/mipolyseg.c) | 0 | ||||
-rw-r--r-- | drv/drvpolytext.c | 130 | ||||
-rw-r--r-- | drv/drvpolyutil.c | 385 | ||||
-rw-r--r-- | drv/drvscanfill.h | 147 | ||||
-rw-r--r-- | drv/drvwideline.c | 2 | ||||
-rw-r--r-- | drv/drvzerclip.c | 630 | ||||
-rw-r--r-- | drv/drvzerline.c | 378 | ||||
-rw-r--r-- | fb/fbarc.c | 4 | ||||
-rw-r--r-- | fb/fbbits.c | 4 | ||||
-rw-r--r-- | fb/fbbits.h | 20 | ||||
-rw-r--r-- | fb/fbgc.c | 14 | ||||
-rw-r--r-- | fb/fbseg.c | 6 | ||||
-rw-r--r-- | mi/Makefile.am | 1 | ||||
-rw-r--r-- | mi/mipolyrect.c (renamed from drv/mipolyrect.c) | 0 |
26 files changed, 3171 insertions, 125 deletions
diff --git a/dix/impedgc.c b/dix/impedgc.c index b19997af3..12ad969ca 100644 --- a/dix/impedgc.c +++ b/dix/impedgc.c @@ -38,6 +38,7 @@ static void SyncDrvGC(GCPtr pGC, DrvGCPtr pDrvGC, int index) pDrvGC->joinStyle = pGC->joinStyle; pDrvGC->capStyle = pGC->capStyle; pDrvGC->lineWidth = pGC->lineWidth; + pDrvGC->font = pGC->font; if (pGC->stipple) pDrvGC->stipple = pGC->stipple->gpu[index]; } @@ -231,6 +232,18 @@ impedPolySegment (DrawablePtr pDrawable, pDrvGC, nseg, pSegs); } +static void +impedPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *pRects) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + pDrvGC = pGC->gpu[0]; + pDrvGC->ops->PolyRectangle(pPixmap->gpu[0], pDrvGC, nrects, pRects); +} + static void impedPolyArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, @@ -250,6 +263,25 @@ static void impedPolyArc (DrawablePtr pDrawable, pDrvGC->ops->PolyArc(pPixmap->gpu[0], pDrvGC, narcs, parcs); } +static void impedFillPolygon( DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, + int count, DDXPointPtr pPts) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + + for (i = 0; i < count; i++) { + pPts[i].x += x_off; + pPts[i].y += y_off; + } + pDrvGC = pGC->gpu[0]; + pDrvGC->ops->FillPolygon(pPixmap->gpu[0], pDrvGC, shape, + mode, count, pPts); +} + static void impedPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, @@ -265,10 +297,73 @@ static void impedPolyFillRect(DrawablePtr pDrawable, prectInit[i].y += y_off; } pDrvGC = pGC->gpu[0]; - SyncDrvGC(pGC, pDrvGC, 0); pDrvGC->ops->PolyFillRect(pPixmap->gpu[0], pDrvGC, nrectFill, prectInit); } +static void impedPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + + pDrvGC = pGC->gpu[0]; + pDrvGC->ops->PolyFillArc(pPixmap->gpu[0], pDrvGC, narcs, parcs); +} + +static int +impedPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + + pDrvGC = pGC->gpu[0]; + return pDrvGC->ops->PolyText8(pPixmap->gpu[0], pDrvGC, x, y, count, chars); +} + +static int +impedPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + + pDrvGC = pGC->gpu[0]; + return pDrvGC->ops->PolyText16(pPixmap->gpu[0], pDrvGC, x, y, count, chars); +} + +static void +impedImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + + pDrvGC = pGC->gpu[0]; + pDrvGC->ops->ImageText8(pPixmap->gpu[0], pDrvGC, x, y, count, chars); +} + +static void +impedImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + int i; + ProtoPixmapPtr pPixmap = (ProtoPixmapPtr)GetDrawablePixmap(pDrawable); + int x_off, y_off; + DrvGCPtr pDrvGC; + impedGetDrawableDeltas(pDrawable, pPixmap, &x_off, &y_off); + + pDrvGC = pGC->gpu[0]; + pDrvGC->ops->ImageText16(pPixmap->gpu[0], pDrvGC, x, y, count, chars); +} + static void impedPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, @@ -290,7 +385,7 @@ impedPolyGlyphBlt (DrawablePtr pDrawable, ppci, pglyphBase); } -void +static void impedImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, @@ -405,6 +500,7 @@ impedCopyPlaneNtoN (DrawablePtr pSrcDrawable, upsidedown, bitplane, closure); } + static RegionPtr impedCopyPlane (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, @@ -472,15 +568,15 @@ const ProtocolGCOps impedGCOps = { impedPolyPoint, impedPolyLines, impedPolySegment, - miPolyRectangle, + impedPolyRectangle, impedPolyArc, - miFillPolygon, + impedFillPolygon, impedPolyFillRect, - miPolyFillArc, - miPolyText8, - miPolyText16, - miImageText8, - miImageText16, + impedPolyFillArc, + impedPolyText8, + impedPolyText16, + impedImageText8, + impedImageText16, impedImageGlyphBlt, impedPolyGlyphBlt, impedPushPixels, diff --git a/dix/impedscrn.c b/dix/impedscrn.c index f91b1f88a..51322f2b3 100644 --- a/dix/impedscrn.c +++ b/dix/impedscrn.c @@ -9,9 +9,11 @@ #include "servermd.h" #include "imped.h" - +#include "drvline.h" #include "micmap.h" +DevPrivateKeyRec drvZeroLineScreenKeyRec; + static DevPrivateKeyRec impedWinPrivateKeyRec; static DevPrivateKey impedGetWinPrivateKey (void) { return &impedWinPrivateKeyRec; } @@ -303,5 +305,19 @@ impedScreenInit(ScreenPtr pScreen) /* replace miCloseScreen */ pScreen->CloseScreen = impedCloseScreen; + drvSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS); return TRUE; } + + +DevPrivateKeyRec drvZeroLineScreenKeyRec; + +void +drvSetZeroLineBias(ScreenPtr pScreen, unsigned int bias) +{ + if (!dixRegisterPrivateKey(&drvZeroLineScreenKeyRec, PRIVATE_SCREEN, 0)) + return; + + dixSetPrivate(&pScreen->devPrivates, drvZeroLineScreenKey, + (unsigned long *)(unsigned long)bias); +} diff --git a/drv/Makefile.am b/drv/Makefile.am index 3666c77ae..dde0d7287 100644 --- a/drv/Makefile.am +++ b/drv/Makefile.am @@ -10,14 +10,22 @@ libdrv_la_SOURCES = \ drv_mi.h \ drvarc.c \ mifpolycon.c \ - mipolyseg.c \ - mipolyrect.c \ + drvpolyseg.c \ + drvpolyrect.c \ drvspans.c \ drvdash.c \ drvwideline.c \ + drvfillarc.c\ drvzerarc.c\ drvfpolycon.c\ + drvpolycon.c\ + drvpolygen.c\ + drvpolyutil.c\ + drvpolytext.c\ drvclear.c\ + drvzerclip.c\ + drvzerline.c\ + drvpoly.c\ drv_gc.c \ drv_pixmap.c \ drv_picture.c diff --git a/drv/drv_mi.h b/drv/drv_mi.h index 12aa2f9f5..151399d64 100644 --- a/drv/drv_mi.h +++ b/drv/drv_mi.h @@ -18,6 +18,35 @@ extern _X_EXPORT void drvPolyArc( xArc * /*parcs*/ ); +/* drvpoly.c */ + +extern _X_EXPORT void drvFillPolygon( + PixmapPtr /*dst*/, + DrvGCPtr /*pgc*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*pPts*/ +); + +/* drvpolycon.c */ + +extern _X_EXPORT Bool drvFillConvexPoly( + PixmapPtr /*dst*/, + DrvGCPtr /*pgc*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +); + +/* drvpolygen.c */ + +extern _X_EXPORT Bool drvFillGeneralPoly( + PixmapPtr /*dst*/, + DrvGCPtr /*pgc*/, + int /*count*/, + DDXPointPtr /*ptsIn*/ +); + /* drvpolyrect.c */ @@ -37,6 +66,43 @@ extern _X_EXPORT void drvPolySegment( xSegment * /*pSegs*/ ); +/* drvpolytext.c */ + +extern _X_EXPORT int drvPolyText8( + PixmapPtr /*pDraw*/, + DrvGCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/ +); + +extern _X_EXPORT int drvPolyText16( + PixmapPtr /*pDraw*/, + DrvGCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/ +); + +extern _X_EXPORT void drvImageText8( + PixmapPtr /*pDraw*/, + DrvGCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/ +); + +extern _X_EXPORT void drvImageText16( + PixmapPtr /*pDraw*/, + DrvGCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/ +); /* drvzerarc.c */ @@ -58,4 +124,26 @@ drvStepDash ( void drvClearPixmap(PixmapPtr pPixmap, DrvGCPtr pGC); + + +/* mizerline.c */ + +extern _X_EXPORT void drvZeroLine( + PixmapPtr /*dst*/, + DrvGCPtr /*pgc*/, + int /*mode*/, + int /*nptInit*/, + DDXPointRec * /*pptInit*/ +); + +extern _X_EXPORT void drvZeroDashLine( + PixmapPtr /*dst*/, + DrvGCPtr /*pgc*/, + int /*mode*/, + int /*nptInit*/, + DDXPointRec * /*pptInit*/ +); + +void +drvPolyFillArc(PixmapPtr pPixmap, DrvGCPtr pGC, int narcs, xArc *parcs); #endif diff --git a/drv/drvfillarc.c b/drv/drvfillarc.c index 6eca13692..38b66c14c 100644 --- a/drv/drvfillarc.c +++ b/drv/drvfillarc.c @@ -35,9 +35,9 @@ Author: Bob Scheifler, MIT X Consortium #include <X11/X.h> #include <X11/Xprotostr.h> #include "regionstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "mifpoly.h" +#include "drv_gcstruct.h" +#include "drv_pixmapstr.h" +#include "drvfpoly.h" #include "drv_mi.h" #include "drvfillarc.h" @@ -53,7 +53,7 @@ Author: Bob Scheifler, MIT X Consortium #define Dcos(d) cos((double)d*(M_PI/11520.0)) void -miFillArcSetup(xArc *arc, miFillArcRec *info) +drvFillArcSetup(xArc *arc, drvFillArcRec *info) { info->y = arc->height >> 1; info->dy = arc->height & 1; @@ -106,7 +106,7 @@ miFillArcSetup(xArc *arc, miFillArcRec *info) } static void -miFillArcDSetup(xArc *arc, miFillArcDRec *info) +drvFillArcDSetup(xArc *arc, drvFillArcDRec *info) { /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ @@ -136,9 +136,9 @@ miFillArcDSetup(xArc *arc, miFillArcDRec *info) } static void -miGetArcEdge( +drvGetArcEdge( xArc *arc, - miSliceEdgePtr edge, + drvSliceEdgePtr edge, int k, Bool top, Bool left ) @@ -185,7 +185,7 @@ miGetArcEdge( } static void -miEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp, +drvEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp, double *d_dxp, double *d_dyp) { int dx, dy; @@ -260,17 +260,17 @@ miEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp, } static void -miGetPieEdge( +drvGetPieEdge( xArc *arc, int angle, - miSliceEdgePtr edge, + drvSliceEdgePtr edge, Bool top, Bool left ) { int k; int dx, dy; - miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0); + drvEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0); if (dy == 0) { @@ -301,11 +301,11 @@ miGetPieEdge( k += dy; edge->dx = dx << 1; edge->dy = dy << 1; - miGetArcEdge(arc, edge, k, top, left); + drvGetArcEdge(arc, edge, k, top, left); } void -miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) +drvFillArcSliceSetup(xArc *arc, drvArcSliceRec *slice, DrvGCPtr pGC) { int angle1, angle2; @@ -369,9 +369,9 @@ miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) slice->min_top_y = arc->height; } } - miGetPieEdge(arc, angle1, &slice->edge1, + drvGetPieEdge(arc, angle1, &slice->edge1, slice->edge1_top, !slice->edge1_top); - miGetPieEdge(arc, angle2, &slice->edge2, + drvGetPieEdge(arc, angle2, &slice->edge2, slice->edge2_top, slice->edge2_top); } else @@ -509,9 +509,9 @@ miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) slice->edge2.dy = slice->edge1.dy; slice->edge1_top = signdy < 0; slice->edge2_top = !slice->edge1_top; - miGetArcEdge(arc, &slice->edge1, k, + drvGetArcEdge(arc, &slice->edge1, k, slice->edge1_top, !slice->edge1_top); - miGetArcEdge(arc, &slice->edge2, k, + drvGetArcEdge(arc, &slice->edge2, k, slice->edge2_top, slice->edge2_top); } } @@ -523,7 +523,7 @@ miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) *wids = slw; \ pts++; \ wids++; \ - if (miFillArcLower(slw)) \ + if (drvFillArcLower(slw)) \ { \ pts->x = xorg - x; \ pts->y = yorg + y + dy; \ @@ -532,15 +532,15 @@ miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) } static void -miFillEllipseI( - DrawablePtr pDraw, - GCPtr pGC, +drvFillEllipseI( + PixmapPtr pPixmap, + DrvGCPtr pGC, xArc *arc ) { int x, y, e; int yk, xk, ym, xm, dx, dy, xorg, yorg; int slw; - miFillArcRec info; + drvFillArcRec info; DDXPointPtr points; DDXPointPtr pts; int *widths; @@ -555,35 +555,35 @@ miFillEllipseI( free(points); return; } - miFillArcSetup(arc, &info); - MIFILLARCSETUP(); + drvFillArcSetup(arc, &info); + DRVFILLARCSETUP(); if (pGC->miTranslate) { - xorg += pDraw->x; - yorg += pDraw->y; + xorg += 0; + yorg += 0; } pts = points; wids = widths; while (y > 0) { - MIFILLARCSTEP(slw); + DRVFILLARCSTEP(slw); ADDSPANS(); } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + (*pGC->ops->FillSpans)(pPixmap, pGC, pts - points, points, widths, FALSE); free(widths); free(points); } static void -miFillEllipseD( - DrawablePtr pDraw, - GCPtr pGC, +drvFillEllipseD( + PixmapPtr pPixmap, + DrvGCPtr pGC, xArc *arc ) { int x, y; int xorg, yorg, dx, dy, slw; double e, yk, xk, ym, xm; - miFillArcDRec info; + drvFillArcDRec info; DDXPointPtr points; DDXPointPtr pts; int *widths; @@ -598,21 +598,21 @@ miFillEllipseD( free(points); return; } - miFillArcDSetup(arc, &info); - MIFILLARCSETUP(); + drvFillArcDSetup(arc, &info); + DRVFILLARCSETUP(); if (pGC->miTranslate) { - xorg += pDraw->x; - yorg += pDraw->y; + xorg += 0; + yorg += 0; } pts = points; wids = widths; while (y > 0) { - MIFILLARCSTEP(slw); + DRVFILLARCSTEP(slw); ADDSPANS(); } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + (*pGC->ops->FillSpans)(pPixmap, pGC, pts - points, points, widths, FALSE); free(widths); free(points); } @@ -640,24 +640,24 @@ miFillEllipseD( } static void -miFillArcSliceI( - DrawablePtr pDraw, - GCPtr pGC, +drvFillArcSliceI( + PixmapPtr pPixmap, + DrvGCPtr pGC, xArc *arc ) { int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; int x, y, e; - miFillArcRec info; - miArcSliceRec slice; + drvFillArcRec info; + drvArcSliceRec slice; int ya, xl, xr, xc; DDXPointPtr points; DDXPointPtr pts; int *widths; int *wids; - miFillArcSetup(arc, &info); - miFillArcSliceSetup(arc, &slice, pGC); - MIFILLARCSETUP(); + drvFillArcSetup(arc, &info); + drvFillArcSliceSetup(arc, &slice, pGC); + DRVFILLARCSETUP(); slw = arc->height; if (slice.flip_top || slice.flip_bot) slw += (arc->height >> 1) + 1; @@ -672,56 +672,56 @@ miFillArcSliceI( } if (pGC->miTranslate) { - xorg += pDraw->x; - yorg += pDraw->y; - slice.edge1.x += pDraw->x; - slice.edge2.x += pDraw->x; + xorg += 0; + yorg += 0; + slice.edge1.x += 0; + slice.edge2.x += 0; } pts = points; wids = widths; while (y > 0) { - MIFILLARCSTEP(slw); - MIARCSLICESTEP(slice.edge1); - MIARCSLICESTEP(slice.edge2); - if (miFillSliceUpper(slice)) + DRVFILLARCSTEP(slw); + DRVARCSLICESTEP(slice.edge1); + DRVARCSLICESTEP(slice.edge2); + if (drvFillSliceUpper(slice)) { ya = yorg - y; - MIARCSLICEUPPER(xl, xr, slice, slw); + DRVARCSLICEUPPER(xl, xr, slice, slw); ADDSLICESPANS(slice.flip_top); } - if (miFillSliceLower(slice)) + if (drvFillSliceLower(slice)) { ya = yorg + y + dy; - MIARCSLICELOWER(xl, xr, slice, slw); + DRVARCSLICELOWER(xl, xr, slice, slw); ADDSLICESPANS(slice.flip_bot); } } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + (*pGC->ops->FillSpans)(pPixmap, pGC, pts - points, points, widths, FALSE); free(widths); free(points); } static void -miFillArcSliceD( - DrawablePtr pDraw, - GCPtr pGC, +drvFillArcSliceD( + PixmapPtr pPixmap, + DrvGCPtr pGC, xArc *arc ) { int x, y; int dx, dy, xorg, yorg, slw; double e, yk, xk, ym, xm; - miFillArcDRec info; - miArcSliceRec slice; + drvFillArcDRec info; + drvArcSliceRec slice; int ya, xl, xr, xc; DDXPointPtr points; DDXPointPtr pts; int *widths; int *wids; - miFillArcDSetup(arc, &info); - miFillArcSliceSetup(arc, &slice, pGC); - MIFILLARCSETUP(); + drvFillArcDSetup(arc, &info); + drvFillArcSliceSetup(arc, &slice, pGC); + DRVFILLARCSETUP(); slw = arc->height; if (slice.flip_top || slice.flip_bot) slw += (arc->height >> 1) + 1; @@ -736,63 +736,63 @@ miFillArcSliceD( } if (pGC->miTranslate) { - xorg += pDraw->x; - yorg += pDraw->y; - slice.edge1.x += pDraw->x; - slice.edge2.x += pDraw->x; + xorg += 0; + yorg += 0; + slice.edge1.x += 0; + slice.edge2.x += 0; } pts = points; wids = widths; while (y > 0) { - MIFILLARCSTEP(slw); - MIARCSLICESTEP(slice.edge1); - MIARCSLICESTEP(slice.edge2); - if (miFillSliceUpper(slice)) + DRVFILLARCSTEP(slw); + DRVARCSLICESTEP(slice.edge1); + DRVARCSLICESTEP(slice.edge2); + if (drvFillSliceUpper(slice)) { ya = yorg - y; - MIARCSLICEUPPER(xl, xr, slice, slw); + DRVARCSLICEUPPER(xl, xr, slice, slw); ADDSLICESPANS(slice.flip_top); } - if (miFillSliceLower(slice)) + if (drvFillSliceLower(slice)) { ya = yorg + y + dy; - MIARCSLICELOWER(xl, xr, slice, slw); + DRVARCSLICELOWER(xl, xr, slice, slw); ADDSLICESPANS(slice.flip_bot); } } - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + (*pGC->ops->FillSpans)(pPixmap, pGC, pts - points, points, widths, FALSE); free(widths); free(points); } -/* MIPOLYFILLARC -- The public entry for the PolyFillArc request. +/* DRVPOLYFILLARC -- The public entry for the PolyFillArc request. * Since we don't have to worry about overlapping segments, we can just * fill each arc as it comes. */ void -miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) +drvPolyFillArc(PixmapPtr pPixmap, DrvGCPtr pGC, int narcs, xArc *parcs) { int i; xArc *arc; for(i = narcs, arc = parcs; --i >= 0; arc++) { - if (miFillArcEmpty(arc)) + if (drvFillArcEmpty(arc)) continue; if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) { - if (miCanFillArc(arc)) - miFillEllipseI(pDraw, pGC, arc); + if (drvCanFillArc(arc)) + drvFillEllipseI(pPixmap, pGC, arc); else - miFillEllipseD(pDraw, pGC, arc); + drvFillEllipseD(pPixmap, pGC, arc); } else { - if (miCanFillArc(arc)) - miFillArcSliceI(pDraw, pGC, arc); + if (drvCanFillArc(arc)) + drvFillArcSliceI(pPixmap, pGC, arc); else - miFillArcSliceD(pDraw, pGC, arc); + drvFillArcSliceD(pPixmap, pGC, arc); } } } diff --git a/drv/drvfillarc.h b/drv/drvfillarc.h index beead2350..4a33658c9 100644 --- a/drv/drvfillarc.h +++ b/drv/drvfillarc.h @@ -184,7 +184,7 @@ extern _X_EXPORT void drvFillArcSetup( extern _X_EXPORT void drvFillArcSliceSetup( xArc * /*arc*/, drvArcSliceRec * /*slice*/, - GCPtr /*pGC*/ + DrvGCPtr /*pGC*/ ); #endif /* __DRVFILLARC_H__ */ diff --git a/drv/drvline.h b/drv/drvline.h new file mode 100644 index 000000000..87196c553 --- /dev/null +++ b/drv/drvline.h @@ -0,0 +1,173 @@ + +/* + +Copyright 1994, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifndef MILINE_H + +#include "screenint.h" +#include "privates.h" + +/* + * Public definitions used for configuring basic pixelization aspects + * of the sample implementation line-drawing routines provided in + * {mfb,mi,cfb*} at run-time. + */ + +#define XDECREASING 4 +#define YDECREASING 2 +#define YMAJOR 1 + +#define OCTANT1 (1 << (YDECREASING)) +#define OCTANT2 (1 << (YDECREASING|YMAJOR)) +#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR)) +#define OCTANT4 (1 << (XDECREASING|YDECREASING)) +#define OCTANT5 (1 << (XDECREASING)) +#define OCTANT6 (1 << (XDECREASING|YMAJOR)) +#define OCTANT7 (1 << (YMAJOR)) +#define OCTANT8 (1 << (0)) + +#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8) + +#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5) + +/* + * Devices can configure the rendering of routines in mi, mfb, and cfb* + * by specifying a thin line bias to be applied to a particular screen + * using the following function. The bias parameter is an OR'ing of + * the appropriate OCTANT constants defined above to indicate which + * octants to bias a line to prefer an axial step when the Bresenham + * error term is exactly zero. The octants are mapped as follows: + * + * \ | / + * \ 3 | 2 / + * \ | / + * 4 \ | / 1 + * \|/ + * ----------- + * /|\ + * 5 / | \ 8 + * / | \ + * / 6 | 7 \ + * / | \ + * + * For more information, see "Ambiguities in Incremental Line Rastering," + * Jack E. Bresenham, IEEE CG&A, May 1987. + */ + +extern _X_EXPORT void miSetZeroLineBias( + ScreenPtr /* pScreen */, + unsigned int /* bias */ +); + +/* + * Private definitions needed for drawing thin (zero width) lines + * Used by the mi, mfb, and all cfb* components. + */ + +#define X_AXIS 0 +#define Y_AXIS 1 + +#define OUT_LEFT 0x08 +#define OUT_RIGHT 0x04 +#define OUT_ABOVE 0x02 +#define OUT_BELOW 0x01 + +#define OUTCODES(_result, _x, _y, _pbox) \ + if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \ + else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \ + if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \ + else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW; + +#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \ +{\ + if (x < xmin) outcode |= OUT_LEFT;\ + if (x > xmax) outcode |= OUT_RIGHT;\ + if (y < ymin) outcode |= OUT_ABOVE;\ + if (y > ymax) outcode |= OUT_BELOW;\ +} + +#define SWAPINT(i, j) \ +{ int _t = i; i = j; j = _t; } + +#define SWAPPT(i, j) \ +{ DDXPointRec _t; _t = i; i = j; j = _t; } + +#define SWAPINT_PAIR(x1, y1, x2, y2)\ +{ int t = x1; x1 = x2; x2 = t;\ + t = y1; y1 = y2; y2 = t;\ +} + +#define drvGetZeroLineBias(_pScreen) ((unsigned long) (unsigned long*)\ + dixLookupPrivate(&(_pScreen)->devPrivates, drvZeroLineScreenKey)) + +#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \ + (_octant) = 0; \ + (_sx) = (_SX); \ + if (((_adx) = (_x2) - (_x1)) < 0) { \ + (_adx) = -(_adx); \ + (_sx = -(_sx)); \ + (_octant) |= XDECREASING; \ + } \ + (_sy) = (_SY); \ + if (((_ady) = (_y2) - (_y1)) < 0) { \ + (_ady) = -(_ady); \ + (_sy = -(_sy)); \ + (_octant) |= YDECREASING; \ + } + +#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR) + +#define FIXUP_ERROR(_e, _octant, _bias) \ + (_e) -= (((_bias) >> (_octant)) & 1) + +#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR)) +#define IsYMajorOctant(_octant) ((_octant) & YMAJOR) +#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING) +#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING) + +extern _X_EXPORT DevPrivateKeyRec drvZeroLineScreenKeyRec; +#define drvZeroLineScreenKey (&drvZeroLineScreenKeyRec) + +extern _X_EXPORT int drvZeroClipLine( + int /*xmin*/, + int /*ymin*/, + int /*xmax*/, + int /*ymax*/, + int * /*new_x1*/, + int * /*new_y1*/, + int * /*new_x2*/, + int * /*new_y2*/, + unsigned int /*adx*/, + unsigned int /*ady*/, + int * /*pt1_clipped*/, + int * /*pt2_clipped*/, + int /*octant*/, + unsigned int /*bias*/, + int /*oc1*/, + int /*oc2*/ +); + +#endif /* MILINE_H */ diff --git a/drv/drvpoly.c b/drv/drvpoly.c new file mode 100644 index 000000000..012ff5ade --- /dev/null +++ b/drv/drvpoly.c @@ -0,0 +1,123 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ +/* + * mipoly.c + * + * Written by Brian Kelleher; June 1986 + * + * Draw polygons. This routine translates the point by the + * origin if pGC->miTranslate is non-zero, and calls + * to the appropriate routine to actually scan convert the + * polygon. + */ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "drv_gcstruct.h" +#include "drv_pixmapstr.h" +#include "drv_mi.h" +#include "regionstr.h" + + +void +drvFillPolygon( PixmapPtr dst, DrvGCPtr pgc, + int shape, int mode, + int count, DDXPointPtr pPts) +{ + int i; + int xorg, yorg; + DDXPointPtr ppt; + + if (count == 0) + return; + + ppt = pPts; + if (pgc->miTranslate) + { + xorg = 0; + yorg = 0; + + if (mode == CoordModeOrigin) + { + for (i = 0; i<count; i++) + { + ppt->x += xorg; + ppt++->y += yorg; + } + } + else + { + ppt->x += xorg; + ppt++->y += yorg; + for (i = 1; i<count; i++) + { + ppt->x += (ppt-1)->x; + ppt->y += (ppt-1)->y; + ppt++; + } + } + } + else + { + if (mode == CoordModePrevious) + { + ppt++; + for (i = 1; i<count; i++) + { + ppt->x += (ppt-1)->x; + ppt->y += (ppt-1)->y; + ppt++; + } + } + } + if (shape == Convex) + drvFillConvexPoly(dst, pgc, count, pPts); + else + drvFillGeneralPoly(dst, pgc, count, pPts); +} diff --git a/drv/drvpoly.h b/drv/drvpoly.h new file mode 100644 index 000000000..5a84af9da --- /dev/null +++ b/drv/drvpoly.h @@ -0,0 +1,207 @@ +/* + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +/* + * fill.h + * + * Created by Brian Kelleher; Oct 1985 + * + * Include file for filled polygon routines. + * + * These are the data structures needed to scan + * convert regions. Two different scan conversion + * methods are available -- the even-odd method, and + * the winding number method. + * The even-odd rule states that a point is inside + * the polygon if a ray drawn from that point in any + * direction will pass through an odd number of + * path segments. + * By the winding number rule, a point is decided + * to be inside the polygon if a ray drawn from that + * point in any direction passes through a different + * number of clockwise and counter-clockwise path + * segments. + * + * These data structures are adapted somewhat from + * the algorithm in (Foley/Van Dam) for scan converting + * polygons. + * The basic algorithm is to start at the top (smallest y) + * of the polygon, stepping down to the bottom of + * the polygon by incrementing the y coordinate. We + * keep a list of edges which the current scanline crosses, + * sorted by x. This list is called the Active Edge Table (AET) + * As we change the y-coordinate, we update each entry in + * in the active edge table to reflect the edges new xcoord. + * This list must be sorted at each scanline in case + * two edges intersect. + * We also keep a data structure known as the Edge Table (ET), + * which keeps track of all the edges which the current + * scanline has not yet reached. The ET is basically a + * list of ScanLineList structures containing a list of + * edges which are entered at a given scanline. There is one + * ScanLineList per scanline at which an edge is entered. + * When we enter a new edge, we move it from the ET to the AET. + * + * From the AET, we can implement the even-odd rule as in + * (Foley/Van Dam). + * The winding number rule is a little trickier. We also + * keep the EdgeTableEntries in the AET linked by the + * nextWETE (winding EdgeTableEntry) link. This allows + * the edges to be linked just as before for updating + * purposes, but only uses the edges linked by the nextWETE + * link as edges representing spans of the polygon to + * drawn (as with the even-odd rule). + */ + +/* + * for the winding number rule + */ +#define CLOCKWISE 1 +#define COUNTERCLOCKWISE -1 + +typedef struct _EdgeTableEntry { + int ymax; /* ycoord at which we exit this edge. */ + BRESINFO bres; /* Bresenham info to run the edge */ + struct _EdgeTableEntry *next; /* next in the list */ + struct _EdgeTableEntry *back; /* for insertion sort */ + struct _EdgeTableEntry *nextWETE; /* for winding num rule */ + int ClockWise; /* flag for winding number rule */ +} EdgeTableEntry; + + +typedef struct _ScanLineList{ + int scanline; /* the scanline represented */ + EdgeTableEntry *edgelist; /* header node */ + struct _ScanLineList *next; /* next in the list */ +} ScanLineList; + + +typedef struct { + int ymax; /* ymax for the polygon */ + int ymin; /* ymin for the polygon */ + ScanLineList scanlines; /* header node */ +} EdgeTable; + + +/* + * Here is a struct to help with storage allocation + * so we can allocate a big chunk at a time, and then take + * pieces from this heap when we need to. + */ +#define SLLSPERBLOCK 25 + +typedef struct _ScanLineListBlock { + ScanLineList SLLs[SLLSPERBLOCK]; + struct _ScanLineListBlock *next; +} ScanLineListBlock; + +/* + * number of points to buffer before sending them off + * to scanlines() : Must be an even number + */ +#define NUMPTSTOBUFFER 200 + + +/* + * + * a few macros for the inner loops of the fill code where + * performance considerations don't allow a procedure call. + * + * Evaluate the given edge at the given scanline. + * If the edge has expired, then we leave it and fix up + * the active edge table; otherwise, we increment the + * x value to be ready for the next scanline. + * The winding number rule is in effect, so we must notify + * the caller when the edge has been removed so he + * can reorder the Winding Active Edge Table. + */ +#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ + if (pAET->ymax == y) { /* leaving this edge */ \ + pPrevAET->next = pAET->next; \ + pAET = pPrevAET->next; \ + fixWAET = 1; \ + if (pAET) \ + pAET->back = pPrevAET; \ + } \ + else { \ + BRESINCRPGONSTRUCT(pAET->bres); \ + pPrevAET = pAET; \ + pAET = pAET->next; \ + } \ +} + + +/* + * Evaluate the given edge at the given scanline. + * If the edge has expired, then we leave it and fix up + * the active edge table; otherwise, we increment the + * x value to be ready for the next scanline. + * The even-odd rule is in effect. + */ +#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ + if (pAET->ymax == y) { /* leaving this edge */ \ + pPrevAET->next = pAET->next; \ + pAET = pPrevAET->next; \ + if (pAET) \ + pAET->back = pPrevAET; \ + } \ + else { \ + BRESINCRPGONSTRUCT(pAET->bres); \ + pPrevAET = pAET; \ + pAET = pAET->next; \ + } \ +} + +/* mipolyutil.c */ + +extern _X_EXPORT Bool drvCreateETandAET( + int /*count*/, + DDXPointPtr /*pts*/, + EdgeTable * /*ET*/, + EdgeTableEntry * /*AET*/, + EdgeTableEntry * /*pETEs*/, + ScanLineListBlock * /*pSLLBlock*/ +); + +extern _X_EXPORT void drvloadAET( + EdgeTableEntry * /*AET*/, + EdgeTableEntry * /*ETEs*/ +); + +extern _X_EXPORT void drvcomputeWAET( + EdgeTableEntry * /*AET*/ +); + +extern _X_EXPORT int drvInsertionSort( + EdgeTableEntry * /*AET*/ +); + +extern _X_EXPORT void drvFreeStorage( + ScanLineListBlock * /*pSLLBlock*/ +); diff --git a/drv/drvpolycon.c b/drv/drvpolycon.c new file mode 100644 index 000000000..70b5052ce --- /dev/null +++ b/drv/drvpolycon.c @@ -0,0 +1,247 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 "drv_gcstruct.h" +#include "drv_pixmap.h" +#include "drv_mi.h" +#include "drvscanfill.h" + +static int getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty); + +/* + * convexpoly.c + * + * Written by Brian Kelleher; Dec. 1985. + * + * Fill a convex polygon. If the given polygon + * is not convex, then the result is undefined. + * The algorithm is to order the edges from smallest + * y to largest by partitioning the array into a left + * edge list and a right edge list. The algorithm used + * to traverse each edge is an extension of Bresenham's + * line algorithm with y as the major axis. + * For a derivation of the algorithm, see the author of + * this code. + */ +Bool +drvFillConvexPoly( + PixmapPtr pPixmap, + DrvGCPtr pgc, + int count, /* number of points */ + DDXPointPtr ptsIn /* the points */ + ) +{ + int xl = 0, xr = 0; /* x vals of left and right edges */ + int dl = 0, dr = 0; /* decision variables */ + int ml = 0, m1l = 0;/* left edge slope and slope+1 */ + int mr = 0, m1r = 0; /* right edge slope and slope+1 */ + int incr1l = 0, incr2l = 0; /* left edge error increments */ + int incr1r = 0, incr2r = 0; /* right edge error increments */ + int dy; /* delta y */ + int y; /* current scanline */ + int left, right; /* indices to first endpoints */ + int i; /* loop counter */ + int nextleft, nextright; /* indices to second endpoints */ + DDXPointPtr ptsOut, FirstPoint; /* output buffer */ + int *width, *FirstWidth; /* output buffer */ + int imin; /* index of smallest vertex (in y) */ + int ymin; /* y-extents of polygon */ + int ymax; + + /* + * find leftx, bottomy, rightx, topy, and the index + * of bottomy. Also translate the points. + */ + imin = getPolyYBounds(ptsIn, count, &ymin, &ymax); + + dy = ymax - ymin + 1; + if ((count < 3) || (dy < 0)) + return TRUE; + ptsOut = FirstPoint = malloc(sizeof(DDXPointRec)*dy); + width = FirstWidth = malloc(sizeof(int) * dy); + if(!FirstPoint || !FirstWidth) + { + free(FirstWidth); + free(FirstPoint); + return FALSE; + } + + nextleft = nextright = imin; + y = ptsIn[nextleft].y; + + /* + * loop through all edges of the polygon + */ + do { + /* + * add a left edge if we need to + */ + if (ptsIn[nextleft].y == y) { + left = nextleft; + + /* + * find the next edge, considering the end + * conditions of the array. + */ + nextleft++; + if (nextleft >= count) + nextleft = 0; + + /* + * now compute all of the random information + * needed to run the iterative algorithm. + */ + BRESINITPGON(ptsIn[nextleft].y-ptsIn[left].y, + ptsIn[left].x,ptsIn[nextleft].x, + xl, dl, ml, m1l, incr1l, incr2l); + } + + /* + * add a right edge if we need to + */ + if (ptsIn[nextright].y == y) { + right = nextright; + + /* + * find the next edge, considering the end + * conditions of the array. + */ + nextright--; + if (nextright < 0) + nextright = count-1; + + /* + * now compute all of the random information + * needed to run the iterative algorithm. + */ + BRESINITPGON(ptsIn[nextright].y-ptsIn[right].y, + ptsIn[right].x,ptsIn[nextright].x, + xr, dr, mr, m1r, incr1r, incr2r); + } + + /* + * generate scans to fill while we still have + * a right edge as well as a left edge. + */ + i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y; + /* in case we're called with non-convex polygon */ + if(i < 0) + { + free(FirstWidth); + free(FirstPoint); + return TRUE; + } + while (i-- > 0) + { + ptsOut->y = y; + + /* + * reverse the edges if necessary + */ + if (xl < xr) + { + *(width++) = xr - xl; + (ptsOut++)->x = xl; + } + else + { + *(width++) = xl - xr; + (ptsOut++)->x = xr; + } + y++; + + /* increment down the edges */ + BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l); + BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r); + } + } while (y != ymax); + + /* + * Finally, fill the <remaining> spans + */ + (*pgc->ops->FillSpans)(pPixmap, pgc, + ptsOut-FirstPoint,FirstPoint,FirstWidth, + 1); + free(FirstWidth); + free(FirstPoint); + return TRUE; +} + + +/* + * Find the index of the point with the smallest y. + */ +static int +getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty) +{ + DDXPointPtr ptMin; + int ymin, ymax; + DDXPointPtr ptsStart = pts; + + ptMin = pts; + ymin = ymax = (pts++)->y; + + while (--n > 0) { + if (pts->y < ymin) + { + ptMin = pts; + ymin = pts->y; + } + if(pts->y > ymax) + ymax = pts->y; + + pts++; + } + + *by = ymin; + *ty = ymax; + return ptMin-ptsStart; +} diff --git a/drv/drvpolygen.c b/drv/drvpolygen.c new file mode 100644 index 000000000..98c9aa485 --- /dev/null +++ b/drv/drvpolygen.c @@ -0,0 +1,230 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include "drv_gcstruct.h" +#include "drvscanfill.h" +#include "drvpoly.h" +#include "drv_pixmap.h" +#include "drv_mi.h" + +/* + * + * Written by Brian Kelleher; Oct. 1985 + * + * Routine to fill a polygon. Two fill rules are + * supported: frWINDING and frEVENODD. + * + * See fillpoly.h for a complete description of the algorithm. + */ + +Bool +drvFillGeneralPoly( + PixmapPtr pPixmap, + DrvGCPtr pgc, + int count, /* number of points */ + DDXPointPtr ptsIn /* the points */ + ) +{ + EdgeTableEntry *pAET; /* the Active Edge Table */ + int y; /* the current scanline */ + int nPts = 0; /* number of pts in buffer */ + EdgeTableEntry *pWETE; /* Winding Edge Table */ + ScanLineList *pSLL; /* Current ScanLineList */ + DDXPointPtr ptsOut; /* ptr to output buffers */ + int *width; + DDXPointRec FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */ + int FirstWidth[NUMPTSTOBUFFER]; + EdgeTableEntry *pPrevAET; /* previous AET entry */ + EdgeTable ET; /* Edge Table header node */ + EdgeTableEntry AET; /* Active ET header node */ + EdgeTableEntry *pETEs; /* Edge Table Entries buff */ + ScanLineListBlock SLLBlock; /* header for ScanLineList */ + int fixWAET = 0; + + if (count < 3) + return TRUE; + + if(!(pETEs = malloc(sizeof(EdgeTableEntry) * count))) + return FALSE; + ptsOut = FirstPoint; + width = FirstWidth; + if (!drvCreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock)) + { + free(pETEs); + return FALSE; + } + pSLL = ET.scanlines.next; + + if (pgc->fillRule == EvenOddRule) + { + /* + * for each scanline + */ + for (y = ET.ymin; y < ET.ymax; y++) + { + /* + * Add a new edge to the active edge table when we + * get to the next edge. + */ + if (pSLL && y == pSLL->scanline) + { + drvloadAET(&AET, pSLL->edgelist); + pSLL = pSLL->next; + } + pPrevAET = &AET; + pAET = AET.next; + + /* + * for each active edge + */ + while (pAET) + { + ptsOut->x = pAET->bres.minor; + ptsOut++->y = y; + *width++ = pAET->next->bres.minor - pAET->bres.minor; + nPts++; + + /* + * send out the buffer when its full + */ + if (nPts == NUMPTSTOBUFFER) + { + (*pgc->ops->FillSpans)(pPixmap, pgc, + nPts, FirstPoint, FirstWidth, + 1); + ptsOut = FirstPoint; + width = FirstWidth; + nPts = 0; + } + EVALUATEEDGEEVENODD(pAET, pPrevAET, y) + EVALUATEEDGEEVENODD(pAET, pPrevAET, y); + } + drvInsertionSort(&AET); + } + } + else /* default to WindingNumber */ + { + /* + * for each scanline + */ + for (y = ET.ymin; y < ET.ymax; y++) + { + /* + * Add a new edge to the active edge table when we + * get to the next edge. + */ + if (pSLL && y == pSLL->scanline) + { + drvloadAET(&AET, pSLL->edgelist); + drvcomputeWAET(&AET); + pSLL = pSLL->next; + } + pPrevAET = &AET; + pAET = AET.next; + pWETE = pAET; + + /* + * for each active edge + */ + while (pAET) + { + /* + * if the next edge in the active edge table is + * also the next edge in the winding active edge + * table. + */ + if (pWETE == pAET) + { + ptsOut->x = pAET->bres.minor; + ptsOut++->y = y; + *width++ = pAET->nextWETE->bres.minor - pAET->bres.minor; + nPts++; + + /* + * send out the buffer + */ + if (nPts == NUMPTSTOBUFFER) + { + (*pgc->ops->FillSpans)(pPixmap, pgc, nPts, FirstPoint, + FirstWidth, 1); + ptsOut = FirstPoint; + width = FirstWidth; + nPts = 0; + } + + pWETE = pWETE->nextWETE; + while (pWETE != pAET) + EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); + pWETE = pWETE->nextWETE; + } + EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); + } + + /* + * reevaluate the Winding active edge table if we + * just had to resort it or if we just exited an edge. + */ + if (drvInsertionSort(&AET) || fixWAET) + { + drvcomputeWAET(&AET); + fixWAET = 0; + } + } + } + + /* + * Get any spans that we missed by buffering + */ + (*pgc->ops->FillSpans)(pPixmap, pgc, nPts, FirstPoint, FirstWidth, 1); + free(pETEs); + drvFreeStorage(SLLBlock.next); + return TRUE; +} diff --git a/drv/drvpolyrect.c b/drv/drvpolyrect.c new file mode 100644 index 000000000..55b8e1030 --- /dev/null +++ b/drv/drvpolyrect.c @@ -0,0 +1,187 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> +#include <X11/Xprotostr.h> +#include "regionstr.h" +#include "drv_gcstruct.h" +#include "drv_pixmap.h" +#include "drv_mi.h" + +void +drvPolyRectangle(PixmapPtr pPixmap, DrvGCPtr pGC, int nrects, xRectangle *pRects) +{ + int i; + xRectangle *pR = pRects; + DDXPointRec rect[5]; + int bound_tmp; + +#define MINBOUND(dst,eqn) bound_tmp = eqn; \ + if (bound_tmp < -32768) \ + bound_tmp = -32768; \ + dst = bound_tmp; + +#define MAXBOUND(dst,eqn) bound_tmp = eqn; \ + if (bound_tmp > 32767) \ + bound_tmp = 32767; \ + dst = bound_tmp; + +#define MAXUBOUND(dst,eqn) bound_tmp = eqn; \ + if (bound_tmp > 65535) \ + bound_tmp = 65535; \ + dst = bound_tmp; + + if (pGC->lineStyle == LineSolid && pGC->joinStyle == JoinMiter && + pGC->lineWidth != 0) + { + xRectangle *tmp, *t; + int ntmp; + int offset1, offset2, offset3; + int x, y, width, height; + + ntmp = (nrects << 2); + offset2 = pGC->lineWidth; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + tmp = malloc(ntmp * sizeof (xRectangle)); + if (!tmp) + return; + t = tmp; + for (i = 0; i < nrects; i++) + { + x = pR->x; + y = pR->y; + width = pR->width; + height = pR->height; + pR++; + if (width == 0 && height == 0) + { + rect[0].x = x; + rect[0].y = y; + rect[1].x = x; + rect[1].y = y; + (*pGC->ops->Polylines)(pPixmap, pGC, CoordModeOrigin, 2, rect); + } + else if (height < offset2 || width < offset1) + { + if (height == 0) + { + t->x = x; + t->width = width; + } + else + { + MINBOUND (t->x, x - offset1) + MAXUBOUND (t->width, width + offset2) + } + if (width == 0) + { + t->y = y; + t->height = height; + } + else + { + MINBOUND (t->y, y - offset1) + MAXUBOUND (t->height, height + offset2) + } + t++; + } + else + { + MINBOUND(t->x, x - offset1) + MINBOUND(t->y, y - offset1) + MAXUBOUND(t->width, width + offset2) + t->height = offset2; + t++; + MINBOUND(t->x, x - offset1) + MAXBOUND(t->y, y + offset3); + t->width = offset2; + t->height = height - offset2; + t++; + MAXBOUND(t->x, x + width - offset1); + MAXBOUND(t->y, y + offset3) + t->width = offset2; + t->height = height - offset2; + t++; + MINBOUND(t->x, x - offset1) + MAXBOUND(t->y, y + height - offset1) + MAXUBOUND(t->width, width + offset2) + t->height = offset2; + t++; + } + } + (*pGC->ops->PolyFillRect) (pPixmap, pGC, t - tmp, tmp); + free((pointer) tmp); + } + else + { + + for (i=0; i<nrects; i++) + { + rect[0].x = pR->x; + rect[0].y = pR->y; + + MAXBOUND(rect[1].x, pR->x + (int) pR->width) + rect[1].y = rect[0].y; + + rect[2].x = rect[1].x; + MAXBOUND(rect[2].y, pR->y + (int) pR->height); + + rect[3].x = rect[0].x; + rect[3].y = rect[2].y; + + rect[4].x = rect[0].x; + rect[4].y = rect[0].y; + + (*pGC->ops->Polylines)(pPixmap, pGC, CoordModeOrigin, 5, rect); + pR++; + } + } +} diff --git a/drv/mipolyseg.c b/drv/drvpolyseg.c index 1ad354c89..1ad354c89 100644 --- a/drv/mipolyseg.c +++ b/drv/drvpolyseg.c diff --git a/drv/drvpolytext.c b/drv/drvpolytext.c new file mode 100644 index 000000000..d275d7f52 --- /dev/null +++ b/drv/drvpolytext.c @@ -0,0 +1,130 @@ +/******************************************************************* + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +************************************************************************/ +/* + * mipolytext.c - text routines + * + * Author: haynes + * Digital Equipment Corporation + * Western Software Laboratory + * Date: Thu Feb 5 1987 + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "drv_gcstruct.h" +#include <X11/fonts/fontstruct.h> +#include "dixfontstr.h" +#include "drv_mi.h" + +int +drvPolyText8(PixmapPtr pPixmap, DrvGCPtr pGC, int x, int y, int count, char *chars) +{ + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, + Linear8Bit, &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + (*pGC->ops->PolyGlyphBlt)( + pPixmap, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); + return x+w; +} + +int +drvPolyText16(PixmapPtr pPixmap, DrvGCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + w = 0; + for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth; + if (n != 0) + (*pGC->ops->PolyGlyphBlt)( + pPixmap, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font)); + return x+w; +} + +void +drvImageText8(PixmapPtr pPixmap, DrvGCPtr pGC, int x, int y, int count, char *chars) +{ + unsigned long n; + FontPtr font = pGC->font; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(font, (unsigned long)count, (unsigned char *)chars, + Linear8Bit, &n, charinfo); + if (n !=0 ) + (*pGC->ops->ImageGlyphBlt)(pPixmap, pGC, x, y, n, charinfo, FONTGLYPHS(font)); +} + +void +drvImageText16(PixmapPtr pPixmap, DrvGCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + unsigned long n; + FontPtr font = pGC->font; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, charinfo); + if (n !=0 ) + (*pGC->ops->ImageGlyphBlt)(pPixmap, pGC, x, y, n, charinfo, FONTGLYPHS(font)); +} diff --git a/drv/drvpolyutil.c b/drv/drvpolyutil.c new file mode 100644 index 000000000..7f7b6628c --- /dev/null +++ b/drv/drvpolyutil.c @@ -0,0 +1,385 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 "regionstr.h" +#include "drv_gc.h" +#include "drvscanfill.h" +#include "drvpoly.h" +#include "misc.h" /* MAXINT */ + +/* + * fillUtils.c + * + * Written by Brian Kelleher; Oct. 1985 + * + * This module contains all of the utility functions + * needed to scan convert a polygon. + * + */ + +/* + * InsertEdgeInET + * + * Insert the given edge into the edge table. + * First we must find the correct bucket in the + * Edge table, then find the right slot in the + * bucket. Finally, we can insert it. + * + */ +static Bool +drvInsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline, + ScanLineListBlock **SLLBlock, int *iSLLBlock) +{ + EdgeTableEntry *start, *prev; + ScanLineList *pSLL, *pPrevSLL; + ScanLineListBlock *tmpSLLBlock; + + /* + * find the right bucket to put the edge into + */ + pPrevSLL = &ET->scanlines; + pSLL = pPrevSLL->next; + while (pSLL && (pSLL->scanline < scanline)) + { + pPrevSLL = pSLL; + pSLL = pSLL->next; + } + + /* + * reassign pSLL (pointer to ScanLineList) if necessary + */ + if ((!pSLL) || (pSLL->scanline > scanline)) + { + if (*iSLLBlock > SLLSPERBLOCK-1) + { + tmpSLLBlock = malloc(sizeof(ScanLineListBlock)); + if (!tmpSLLBlock) + return FALSE; + (*SLLBlock)->next = tmpSLLBlock; + tmpSLLBlock->next = NULL; + *SLLBlock = tmpSLLBlock; + *iSLLBlock = 0; + } + pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]); + + pSLL->next = pPrevSLL->next; + pSLL->edgelist = NULL; + pPrevSLL->next = pSLL; + } + pSLL->scanline = scanline; + + /* + * now insert the edge in the right bucket + */ + prev = NULL; + start = pSLL->edgelist; + while (start && (start->bres.minor < ETE->bres.minor)) + { + prev = start; + start = start->next; + } + ETE->next = start; + + if (prev) + prev->next = ETE; + else + pSLL->edgelist = ETE; + return TRUE; +} + +/* + * CreateEdgeTable + * + * This routine creates the edge table for + * scan converting polygons. + * The Edge Table (ET) looks like: + * + * EdgeTable + * -------- + * | ymax | ScanLineLists + * |scanline|-->------------>-------------->... + * -------- |scanline| |scanline| + * |edgelist| |edgelist| + * --------- --------- + * | | + * | | + * V V + * list of ETEs list of ETEs + * + * where ETE is an EdgeTableEntry data structure, + * and there is one ScanLineList per scanline at + * which an edge is initially entered. + * + */ + +Bool +drvCreateETandAET(int count, DDXPointPtr pts, EdgeTable *ET, EdgeTableEntry *AET, + EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock) +{ + DDXPointPtr top, bottom; + DDXPointPtr PrevPt, CurrPt; + int iSLLBlock = 0; + + int dy; + + if (count < 2) return TRUE; + + /* + * initialize the Active Edge Table + */ + AET->next = NULL; + AET->back = NULL; + AET->nextWETE = NULL; + AET->bres.minor = MININT; + + /* + * initialize the Edge Table. + */ + ET->scanlines.next = NULL; + ET->ymax = MININT; + ET->ymin = MAXINT; + pSLLBlock->next = NULL; + + PrevPt = &pts[count-1]; + + /* + * for each vertex in the array of points. + * In this loop we are dealing with two vertices at + * a time -- these make up one edge of the polygon. + */ + while (count--) + { + CurrPt = pts++; + + /* + * find out which point is above and which is below. + */ + if (PrevPt->y > CurrPt->y) + { + bottom = PrevPt, top = CurrPt; + pETEs->ClockWise = 0; + } + else + { + bottom = CurrPt, top = PrevPt; + pETEs->ClockWise = 1; + } + + /* + * don't add horizontal edges to the Edge table. + */ + if (bottom->y != top->y) + { + pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ + + /* + * initialize integer edge algorithm + */ + dy = bottom->y - top->y; + BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); + + if (!drvInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock)) + { + drvFreeStorage(pSLLBlock->next); + return FALSE; + } + + ET->ymax = max(ET->ymax, PrevPt->y); + ET->ymin = min(ET->ymin, PrevPt->y); + pETEs++; + } + + PrevPt = CurrPt; + } + return TRUE; +} + +/* + * loadAET + * + * This routine moves EdgeTableEntries from the + * EdgeTable into the Active Edge Table, + * leaving them sorted by smaller x coordinate. + * + */ + +void +drvloadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs) +{ + EdgeTableEntry *pPrevAET; + EdgeTableEntry *tmp; + + pPrevAET = AET; + AET = AET->next; + while (ETEs) + { + while (AET && (AET->bres.minor < ETEs->bres.minor)) + { + pPrevAET = AET; + AET = AET->next; + } + tmp = ETEs->next; + ETEs->next = AET; + if (AET) + AET->back = ETEs; + ETEs->back = pPrevAET; + pPrevAET->next = ETEs; + pPrevAET = ETEs; + + ETEs = tmp; + } +} + +/* + * computeWAET + * + * This routine links the AET by the + * nextWETE (winding EdgeTableEntry) link for + * use by the winding number rule. The final + * Active Edge Table (AET) might look something + * like: + * + * AET + * ---------- --------- --------- + * |ymax | |ymax | |ymax | + * | ... | |... | |... | + * |next |->|next |->|next |->... + * |nextWETE| |nextWETE| |nextWETE| + * --------- --------- ^-------- + * | | | + * V-------------------> V---> ... + * + */ +void +drvcomputeWAET(EdgeTableEntry *AET) +{ + EdgeTableEntry *pWETE; + int inside = 1; + int isInside = 0; + + AET->nextWETE = NULL; + pWETE = AET; + AET = AET->next; + while (AET) + { + if (AET->ClockWise) + isInside++; + else + isInside--; + + if ((!inside && !isInside) || + ( inside && isInside)) + { + pWETE->nextWETE = AET; + pWETE = AET; + inside = !inside; + } + AET = AET->next; + } + pWETE->nextWETE = NULL; +} + +/* + * InsertionSort + * + * Just a simple insertion sort using + * pointers and back pointers to sort the Active + * Edge Table. + * + */ + +int +drvInsertionSort(EdgeTableEntry *AET) +{ + EdgeTableEntry *pETEchase; + EdgeTableEntry *pETEinsert; + EdgeTableEntry *pETEchaseBackTMP; + int changed = 0; + + AET = AET->next; + while (AET) + { + pETEinsert = AET; + pETEchase = AET; + while (pETEchase->back->bres.minor > AET->bres.minor) + pETEchase = pETEchase->back; + + AET = AET->next; + if (pETEchase != pETEinsert) + { + pETEchaseBackTMP = pETEchase->back; + pETEinsert->back->next = AET; + if (AET) + AET->back = pETEinsert->back; + pETEinsert->next = pETEchase; + pETEchase->back->next = pETEinsert; + pETEchase->back = pETEinsert; + pETEinsert->back = pETEchaseBackTMP; + changed = 1; + } + } + return changed; +} + +/* + * Clean up our act. + */ +void +drvFreeStorage(ScanLineListBlock *pSLLBlock) +{ + ScanLineListBlock *tmpSLLBlock; + + while (pSLLBlock) + { + tmpSLLBlock = pSLLBlock->next; + free(pSLLBlock); + pSLLBlock = tmpSLLBlock; + } +} diff --git a/drv/drvscanfill.h b/drv/drvscanfill.h new file mode 100644 index 000000000..e318c45b4 --- /dev/null +++ b/drv/drvscanfill.h @@ -0,0 +1,147 @@ +/* + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef SCANFILLINCLUDED +#define SCANFILLINCLUDED +/* + * scanfill.h + * + * Written by Brian Kelleher; Jan 1985 + * + * This file contains a few macros to help track + * the edge of a filled object. The object is assumed + * to be filled in scanline order, and thus the + * algorithm used is an extension of Bresenham's line + * drawing algorithm which assumes that y is always the + * major axis. + * Since these pieces of code are the same for any filled shape, + * it is more convenient to gather the library in one + * place, but since these pieces of code are also in + * the inner loops of output primitives, procedure call + * overhead is out of the question. + * See the author for a derivation if needed. + */ + + +/* + * In scan converting polygons, we want to choose those pixels + * which are inside the polygon. Thus, we add .5 to the starting + * x coordinate for both left and right edges. Now we choose the + * first pixel which is inside the pgon for the left edge and the + * first pixel which is outside the pgon for the right edge. + * Draw the left pixel, but not the right. + * + * How to add .5 to the starting x coordinate: + * If the edge is moving to the right, then subtract dy from the + * error term from the general form of the algorithm. + * If the edge is moving to the left, then add dy to the error term. + * + * The reason for the difference between edges moving to the left + * and edges moving to the right is simple: If an edge is moving + * to the right, then we want the algorithm to flip immediately. + * If it is moving to the left, then we don't want it to flip until + * we traverse an entire pixel. + */ +#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \ + int dx; /* local storage */ \ +\ + /* \ + * if the edge is horizontal, then it is ignored \ + * and assumed not to be processed. Otherwise, do this stuff. \ + */ \ + if ((dy) != 0) { \ + xStart = (x1); \ + dx = (x2) - xStart; \ + if (dx < 0) { \ + m = dx / (dy); \ + m1 = m - 1; \ + incr1 = -2 * dx + 2 * (dy) * m1; \ + incr2 = -2 * dx + 2 * (dy) * m; \ + d = 2 * m * (dy) - 2 * dx - 2 * (dy); \ + } else { \ + m = dx / (dy); \ + m1 = m + 1; \ + incr1 = 2 * dx - 2 * (dy) * m1; \ + incr2 = 2 * dx - 2 * (dy) * m; \ + d = -2 * m * (dy) + 2 * dx; \ + } \ + } \ +} + +#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \ + if (m1 > 0) { \ + if (d > 0) { \ + minval += m1; \ + d += incr1; \ + } \ + else { \ + minval += m; \ + d += incr2; \ + } \ + } else {\ + if (d >= 0) { \ + minval += m1; \ + d += incr1; \ + } \ + else { \ + minval += m; \ + d += incr2; \ + } \ + } \ +} + + +/* + * This structure contains all of the information needed + * to run the bresenham algorithm. + * The variables may be hardcoded into the declarations + * instead of using this structure to make use of + * register declarations. + */ +typedef struct { + int minor; /* minor axis */ + int d; /* decision variable */ + int m, m1; /* slope and slope+1 */ + int incr1, incr2; /* error increments */ +} BRESINFO; + + +#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \ + BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, \ + bres.m, bres.m1, bres.incr1, bres.incr2) + +#define BRESINCRPGONSTRUCT(bres) \ + BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2) + + +#endif diff --git a/drv/drvwideline.c b/drv/drvwideline.c index cfa8d3308..299361bae 100644 --- a/drv/drvwideline.c +++ b/drv/drvwideline.c @@ -2082,7 +2082,7 @@ drvWideDash (PixmapPtr pPixmap, DrvGCPtr pGC, projectRight = FALSE; dashIndex = 0; dashOffset = 0; - miStepDash ((int)pGC->dashOffset, &dashIndex, + drvStepDash ((int)pGC->dashOffset, &dashIndex, pGC->dash, (int)pGC->numInDashList, &dashOffset); while (--npt) { diff --git a/drv/drvzerclip.c b/drv/drvzerclip.c new file mode 100644 index 000000000..fc16f8b0e --- /dev/null +++ b/drv/drvzerclip.c @@ -0,0 +1,630 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> + +#include "misc.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "mi.h" +#include "miline.h" + +/* + +The bresenham error equation used in the mi/mfb/cfb line routines is: + + e = error + dx = difference in raw X coordinates + dy = difference in raw Y coordinates + M = # of steps in X direction + N = # of steps in Y direction + B = 0 to prefer diagonal steps in a given octant, + 1 to prefer axial steps in a given octant + + For X major lines: + e = 2Mdy - 2Ndx - dx - B + -2dx <= e < 0 + + For Y major lines: + e = 2Ndx - 2Mdy - dy - B + -2dy <= e < 0 + +At the start of the line, we have taken 0 X steps and 0 Y steps, +so M = 0 and N = 0: + + X major e = 2Mdy - 2Ndx - dx - B + = -dx - B + + Y major e = 2Ndx - 2Mdy - dy - B + = -dy - B + +At the end of the line, we have taken dx X steps and dy Y steps, +so M = dx and N = dy: + + X major e = 2Mdy - 2Ndx - dx - B + = 2dxdy - 2dydx - dx - B + = -dx - B + Y major e = 2Ndx - 2Mdy - dy - B + = 2dydx - 2dxdy - dy - B + = -dy - B + +Thus, the error term is the same at the start and end of the line. + +Let us consider clipping an X coordinate. There are 4 cases which +represent the two independent cases of clipping the start vs. the +end of the line and an X major vs. a Y major line. In any of these +cases, we know the number of X steps (M) and we wish to find the +number of Y steps (N). Thus, we will solve our error term equation. +If we are clipping the start of the line, we will find the smallest +N that satisfies our error term inequality. If we are clipping the +end of the line, we will find the largest number of Y steps that +satisfies the inequality. In that case, since we are representing +the Y steps as (dy - N), we will actually want to solve for the +smallest N in that equation. + +Case 1: X major, starting X coordinate moved by M steps + + -2dx <= 2Mdy - 2Ndx - dx - B < 0 + 2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B + 2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx + N <= (2Mdy + dx - B) / 2dx + +Since we are trying to find the smallest N that satisfies these +equations, we should use the > inequality to find the smallest: + + N = floor((2Mdy - dx - B) / 2dx) + 1 + = floor((2Mdy - dx - B + 2dx) / 2dx) + = floor((2Mdy + dx - B) / 2dx) + +Case 1b: X major, ending X coordinate moved to M steps + +Same derivations as Case 1, but we want the largest N that satisfies +the equations, so we use the <= inequality: + + N = floor((2Mdy + dx - B) / 2dx) + +Case 2: X major, ending X coordinate moved by M steps + + -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 + -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 + -2dx <= 2Ndx - 2Mdy - dx - B < 0 + 2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B + 2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx + N >= (2Mdy - dx + B) / 2dx + +Since we are trying to find the highest number of Y steps that +satisfies these equations, we need to find the smallest N, so +we should use the >= inequality to find the smallest: + + N = ceiling((2Mdy - dx + B) / 2dx) + = floor((2Mdy - dx + B + 2dx - 1) / 2dx) + = floor((2Mdy + dx + B - 1) / 2dx) + +Case 2b: X major, starting X coordinate moved to M steps from end + +Same derivations as Case 2, but we want the smallest number of Y +steps, so we want the highest N, so we use the < inequality: + + N = ceiling((2Mdy + dx + B) / 2dx) - 1 + = floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1 + = floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx) + = floor((2Mdy + dx + B - 1) / 2dx) + +Case 3: Y major, starting X coordinate moved by M steps + + -2dy <= 2Ndx - 2Mdy - dy - B < 0 + 2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B + 2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx + N >= (2Mdy - dy + B) / 2dx + +Since we are trying to find the smallest N that satisfies these +equations, we should use the >= inequality to find the smallest: + + N = ceiling((2Mdy - dy + B) / 2dx) + = floor((2Mdy - dy + B + 2dx - 1) / 2dx) + = floor((2Mdy - dy + B - 1) / 2dx) + 1 + +Case 3b: Y major, ending X coordinate moved to M steps + +Same derivations as Case 3, but we want the largest N that satisfies +the equations, so we use the < inequality: + + N = ceiling((2Mdy + dy + B) / 2dx) - 1 + = floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1 + = floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx) + = floor((2Mdy + dy + B - 1) / 2dx) + +Case 4: Y major, ending X coordinate moved by M steps + + -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 + -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 + -2dy <= 2Mdy - 2Ndx - dy - B < 0 + 2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B + 2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx + N <= (2Mdy + dy - B) / 2dx + +Since we are trying to find the highest number of Y steps that +satisfies these equations, we need to find the smallest N, so +we should use the > inequality to find the smallest: + + N = floor((2Mdy - dy - B) / 2dx) + 1 + +Case 4b: Y major, starting X coordinate moved to M steps from end + +Same analysis as Case 4, but we want the smallest number of Y steps +which means the largest N, so we use the <= inequality: + + N = floor((2Mdy + dy - B) / 2dx) + +Now let's try the Y coordinates, we have the same 4 cases. + +Case 5: X major, starting Y coordinate moved by N steps + + -2dx <= 2Mdy - 2Ndx - dx - B < 0 + 2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B + 2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy + M >= (2Ndx - dx + B) / 2dy + +Since we are trying to find the smallest M, we use the >= inequality: + + M = ceiling((2Ndx - dx + B) / 2dy) + = floor((2Ndx - dx + B + 2dy - 1) / 2dy) + = floor((2Ndx - dx + B - 1) / 2dy) + 1 + +Case 5b: X major, ending Y coordinate moved to N steps + +Same derivations as Case 5, but we want the largest M that satisfies +the equations, so we use the < inequality: + + M = ceiling((2Ndx + dx + B) / 2dy) - 1 + = floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1 + = floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy) + = floor((2Ndx + dx + B - 1) / 2dy) + +Case 6: X major, ending Y coordinate moved by N steps + + -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 + -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 + -2dx <= 2Ndx - 2Mdy - dx - B < 0 + 2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B + 2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy + M <= (2Ndx + dx - B) / 2dy + +Largest # of X steps means smallest M, so use the > inequality: + + M = floor((2Ndx - dx - B) / 2dy) + 1 + +Case 6b: X major, starting Y coordinate moved to N steps from end + +Same derivations as Case 6, but we want the smallest # of X steps +which means the largest M, so use the <= inequality: + + M = floor((2Ndx + dx - B) / 2dy) + +Case 7: Y major, starting Y coordinate moved by N steps + + -2dy <= 2Ndx - 2Mdy - dy - B < 0 + 2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B + 2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy + M <= (2Ndx + dy - B) / 2dy + +To find the smallest M, use the > inequality: + + M = floor((2Ndx - dy - B) / 2dy) + 1 + = floor((2Ndx - dy - B + 2dy) / 2dy) + = floor((2Ndx + dy - B) / 2dy) + +Case 7b: Y major, ending Y coordinate moved to N steps + +Same derivations as Case 7, but we want the largest M that satisfies +the equations, so use the <= inequality: + + M = floor((2Ndx + dy - B) / 2dy) + +Case 8: Y major, ending Y coordinate moved by N steps + + -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 + -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 + -2dy <= 2Mdy - 2Ndx - dy - B < 0 + 2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B + 2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy + M >= (2Ndx - dy + B) / 2dy + +To find the highest X steps, find the smallest M, use the >= inequality: + + M = ceiling((2Ndx - dy + B) / 2dy) + = floor((2Ndx - dy + B + 2dy - 1) / 2dy) + = floor((2Ndx + dy + B - 1) / 2dy) + +Case 8b: Y major, starting Y coordinate moved to N steps from the end + +Same derivations as Case 8, but we want to find the smallest # of X +steps which means the largest M, so we use the < inequality: + + M = ceiling((2Ndx + dy + B) / 2dy) - 1 + = floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1 + = floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy) + = floor((2Ndx + dy + B - 1) / 2dy) + +So, our equations are: + + 1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx) + 1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx) + 2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx) + 2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx) + + 3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1 + 3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx) + 4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1 + 4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx) + + 5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1 + 5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy) + 6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1 + 6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy) + + 7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy) + 7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy) + 8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy) + 8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy) + +We have the following constraints on all of the above terms: + + 0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine + 0 <= dx/dy <= 2^16 - 1 + 0 <= B <= 1 + +The floor in all of the above equations can be accomplished with a +simple C divide operation provided that both numerator and denominator +are positive. + +Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0 +and moving a Y coordinate implies dy != 0, we know that the denominators +are all > 0. + +For all lines, (-B) and (B-1) are both either 0 or -1, depending on the +bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1 +or > 0 to prove that the numerators are positive (or zero). + +For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the +constraints, the first four equations all have numerators >= 0. + +For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy +So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy +or (2Mdy + dy) > 0. So all of their numerators are >= 0. + +For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx) +>= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0. + +For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators +are > 0. + +To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This +is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1) + <= 2^16 * (2^16 - 1) + (2^16 - 1) + <= 2^32 - 2^16 + 2^16 - 1 + <= 2^32 - 1 +Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of +the numerator is therefore (2^32 - 1), which does not overflow an unsigned +32 bit variable. + +*/ + +/* Bit codes for the terms of the 16 clipping equations defined below. */ + +#define T_2NDX (1 << 0) +#define T_2MDY (0) /* implicit term */ +#define T_DXNOTY (1 << 1) +#define T_DYNOTX (0) /* implicit term */ +#define T_SUBDXORY (1 << 2) +#define T_ADDDX (T_DXNOTY) /* composite term */ +#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */ +#define T_ADDDY (T_DYNOTX) /* composite term */ +#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */ +#define T_BIASSUBONE (1 << 3) +#define T_SUBBIAS (0) /* implicit term */ +#define T_DIV2DX (1 << 4) +#define T_DIV2DY (0) /* implicit term */ +#define T_ADDONE (1 << 5) + +/* Bit masks defining the 16 equations used in miZeroClipLine. */ + +#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) +#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) +#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) +#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) + +#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE) +#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX) +#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE) +#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX) + +#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE) +#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY) +#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE) +#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY) + +#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) +#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) +#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) +#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) + +/* drvZeroClipLine + * + * returns: 1 for partially clipped line + * -1 for completely clipped line + * + */ +int +drvZeroClipLine(int xmin, int ymin, int xmax, int ymax, + int *new_x1, int *new_y1, int *new_x2, int *new_y2, + unsigned int adx, unsigned int ady, + int *pt1_clipped, int *pt2_clipped, + int octant, unsigned int bias, + int oc1, int oc2) +{ + int swapped = 0; + int clipDone = 0; + CARD32 utmp = 0; + int clip1, clip2; + int x1, y1, x2, y2; + int x1_orig, y1_orig, x2_orig, y2_orig; + int xmajor; + int negslope = 0, anchorval = 0; + unsigned int eqn = 0; + + x1 = x1_orig = *new_x1; + y1 = y1_orig = *new_y1; + x2 = x2_orig = *new_x2; + y2 = y2_orig = *new_y2; + + clip1 = 0; + clip2 = 0; + + xmajor = IsXMajorOctant(octant); + bias = ((bias >> octant) & 1); + + while (1) + { + if ((oc1 & oc2) != 0) /* trivial reject */ + { + clipDone = -1; + clip1 = oc1; + clip2 = oc2; + break; + } + else if ((oc1 | oc2) == 0) /* trivial accept */ + { + clipDone = 1; + if (swapped) + { + SWAPINT_PAIR(x1, y1, x2, y2); + SWAPINT(clip1, clip2); + } + break; + } + else /* have to clip */ + { + /* only clip one point at a time */ + if (oc1 == 0) + { + SWAPINT_PAIR(x1, y1, x2, y2); + SWAPINT_PAIR(x1_orig, y1_orig, x2_orig, y2_orig); + SWAPINT(oc1, oc2); + SWAPINT(clip1, clip2); + swapped = !swapped; + } + + clip1 |= oc1; + if (oc1 & OUT_LEFT) + { + negslope = IsYDecreasingOctant(octant); + utmp = xmin - x1_orig; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN2 : EQN1; + else + eqn = (swapped) ? EQN4 : EQN3; + anchorval = y1_orig; + } + else /* clip based on far endpt */ + { + utmp = x2_orig - xmin; + if (xmajor) + eqn = (swapped) ? EQN1B : EQN2B; + else + eqn = (swapped) ? EQN3B : EQN4B; + anchorval = y2_orig; + negslope = !negslope; + } + x1 = xmin; + } + else if (oc1 & OUT_ABOVE) + { + negslope = IsXDecreasingOctant(octant); + utmp = ymin - y1_orig; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN6 : EQN5; + else + eqn = (swapped) ? EQN8 : EQN7; + anchorval = x1_orig; + } + else /* clip based on far endpt */ + { + utmp = y2_orig - ymin; + if (xmajor) + eqn = (swapped) ? EQN5B : EQN6B; + else + eqn = (swapped) ? EQN7B : EQN8B; + anchorval = x2_orig; + negslope = !negslope; + } + y1 = ymin; + } + else if (oc1 & OUT_RIGHT) + { + negslope = IsYDecreasingOctant(octant); + utmp = x1_orig - xmax; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN2 : EQN1; + else + eqn = (swapped) ? EQN4 : EQN3; + anchorval = y1_orig; + } + else /* clip based on far endpt */ + { + /* + * Technically since the equations can handle + * utmp == 32768, this overflow code isn't + * needed since X11 protocol can't generate + * a line which goes more than 32768 pixels + * to the right of a clip rectangle. + */ + utmp = xmax - x2_orig; + if (xmajor) + eqn = (swapped) ? EQN1B : EQN2B; + else + eqn = (swapped) ? EQN3B : EQN4B; + anchorval = y2_orig; + negslope = !negslope; + } + x1 = xmax; + } + else if (oc1 & OUT_BELOW) + { + negslope = IsXDecreasingOctant(octant); + utmp = y1_orig - ymax; + if (utmp <= 32767) /* clip based on near endpt */ + { + if (xmajor) + eqn = (swapped) ? EQN6 : EQN5; + else + eqn = (swapped) ? EQN8 : EQN7; + anchorval = x1_orig; + } + else /* clip based on far endpt */ + { + /* + * Technically since the equations can handle + * utmp == 32768, this overflow code isn't + * needed since X11 protocol can't generate + * a line which goes more than 32768 pixels + * below the bottom of a clip rectangle. + */ + utmp = ymax - y2_orig; + if (xmajor) + eqn = (swapped) ? EQN5B : EQN6B; + else + eqn = (swapped) ? EQN7B : EQN8B; + anchorval = x2_orig; + negslope = !negslope; + } + y1 = ymax; + } + + if (swapped) + negslope = !negslope; + + utmp <<= 1; /* utmp = 2N or 2M */ + if (eqn & T_2NDX) + utmp = (utmp * adx); + else /* (eqn & T_2MDY) */ + utmp = (utmp * ady); + if (eqn & T_DXNOTY) + if (eqn & T_SUBDXORY) + utmp -= adx; + else + utmp += adx; + else /* (eqn & T_DYNOTX) */ + if (eqn & T_SUBDXORY) + utmp -= ady; + else + utmp += ady; + if (eqn & T_BIASSUBONE) + utmp += bias - 1; + else /* (eqn & T_SUBBIAS) */ + utmp -= bias; + if (eqn & T_DIV2DX) + utmp /= (adx << 1); + else /* (eqn & T_DIV2DY) */ + utmp /= (ady << 1); + if (eqn & T_ADDONE) + utmp++; + + if (negslope) + utmp = -utmp; + + if (eqn & T_2NDX) /* We are calculating X steps */ + x1 = anchorval + utmp; + else /* else, Y steps */ + y1 = anchorval + utmp; + + oc1 = 0; + MIOUTCODES(oc1, x1, y1, xmin, ymin, xmax, ymax); + } + } + + *new_x1 = x1; + *new_y1 = y1; + *new_x2 = x2; + *new_y2 = y2; + + *pt1_clipped = clip1; + *pt2_clipped = clip2; + + return clipDone; +} diff --git a/drv/drvzerline.c b/drv/drvzerline.c new file mode 100644 index 000000000..275bb3e30 --- /dev/null +++ b/drv/drvzerline.c @@ -0,0 +1,378 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 <X11/X.h> + +#include "misc.h" +#include "scrnintstr.h" +#include "drv_gcstruct.h" +#include "drv_pixmapstr.h" +#include "drv_mi.h" +#include "drvline.h" + +/* Draw lineSolid, fillStyle-independent zero width lines. + * + * Must keep X and Y coordinates in "ints" at least until after they're + * translated and clipped to accomodate CoordModePrevious lines with very + * large coordinates. + * + * Draws the same pixels regardless of sign(dx) or sign(dy). + * + * Ken Whaley + * + */ + +/* largest positive value that can fit into a component of a point. + * Assumes that the point structure is {type x, y;} where type is + * a signed type. + */ +#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1) + +#define MI_OUTPUT_POINT(xx, yy)\ +{\ + if ( !new_span && yy == current_y)\ + {\ + if (xx < spans->x)\ + spans->x = xx;\ + ++*widths;\ + }\ + else\ + {\ + ++Nspans;\ + ++spans;\ + ++widths;\ + spans->x = xx;\ + spans->y = yy;\ + *widths = 1;\ + current_y = yy;\ + new_span = FALSE;\ + }\ +} + +void +drvZeroLine( + PixmapPtr pDraw, + DrvGCPtr pGC, + int mode, /* Origin or Previous */ + int npt, /* number of points */ + DDXPointPtr pptInit) +{ + int Nspans, current_y = 0; + DDXPointPtr ppt; + DDXPointPtr pspanInit, spans; + int *pwidthInit, *widths, list_len; + int xleft, ytop, xright, ybottom; + int new_x1, new_y1, new_x2, new_y2; + int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart; + int oc1, oc2; + int result; + int pt1_clipped, pt2_clipped = 0; + Bool new_span; + int signdx, signdy; + int clipdx, clipdy; + int width, height; + int adx, ady; + int octant; + unsigned int bias = drvGetZeroLineBias(pDraw->pScreen); + int e, e1, e2, e3; /* Bresenham error terms */ + int length; /* length of lines == # of pixels on major axis */ + + xleft = 0; + ytop = 0; + xright = 0 + pDraw->width - 1; + ybottom = 0 + pDraw->height - 1; + + if (!pGC->miTranslate) + { + /* do everything in drawable-relative coordinates */ + xleft = 0; + ytop = 0; + xright -= 0; + ybottom -= 0; + } + + /* it doesn't matter whether we're in drawable or screen coordinates, + * FillSpans simply cannot take starting coordinates outside of the + * range of a DDXPointRec component. + */ + if (xright > MAX_COORDINATE) + xright = MAX_COORDINATE; + if (ybottom > MAX_COORDINATE) + ybottom = MAX_COORDINATE; + + /* since we're clipping to the drawable's boundaries & coordinate + * space boundaries, we're guaranteed that the larger of width/height + * is the longest span we'll need to output + */ + width = xright - xleft + 1; + height = ybottom - ytop + 1; + list_len = (height >= width) ? height : width; + pspanInit = malloc(list_len * sizeof(DDXPointRec)); + pwidthInit = malloc(list_len * sizeof(int)); + if (!pspanInit || !pwidthInit) + return; + + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + ppt = pptInit; + + xstart = ppt->x; + ystart = ppt->y; + if (pGC->miTranslate) + { + xstart += 0; + ystart += 0; + } + + /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify + * iteration logic + */ + x2 = xstart; + y2 = ystart; + oc2 = 0; + MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); + + while (--npt > 0) + { + if (Nspans > 0) + (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, + pwidthInit, FALSE); + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + + x1 = x2; + y1 = y2; + oc1 = oc2; + ++ppt; + + x2 = ppt->x; + y2 = ppt->y; + if (pGC->miTranslate && (mode != CoordModePrevious)) + { + x2 += 0; + y2 += 0; + } + else if (mode == CoordModePrevious) + { + x2 += x1; + y2 += y1; + } + + oc2 = 0; + MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) + { + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + length = adx; /* don't draw endpoint in main loop */ + + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) + { + result = drvZeroClipLine(xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs(new_x2 - new_x1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + e += (clipdy * e2) + ((clipdx - clipdy) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) + { + MI_OUTPUT_POINT(x, y); + e += e1; + if (e >= 0) + { + y += signdy; + e += e3; + } + x += signdx; + } + } + else /* Y major line */ + { + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + length = ady; /* don't draw endpoint in main loop */ + + SetYMajorOctant(octant); + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) + { + result = drvZeroClipLine(xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs(new_y2 - new_y1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + e += (clipdx * e2) + ((clipdy - clipdx) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) + { + MI_OUTPUT_POINT(x, y); + e += e1; + if (e >= 0) + { + x += signdx; + e += e3; + } + y += signdy; + } + } + } + + /* only do the capnotlast check on the last segment + * and only if the endpoint wasn't clipped. And then, if the last + * point is the same as the first point, do not draw it, unless the + * line is degenerate + */ + if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) && + (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) + { + MI_OUTPUT_POINT(x, y); + } + + if (Nspans > 0) + (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, + pwidthInit, FALSE); + + free(pwidthInit); + free(pspanInit); +} + +void +drvZeroDashLine( + PixmapPtr dst, + DrvGCPtr pgc, + int mode, + int nptInit, /* number of points in polyline */ + DDXPointRec *pptInit /* points in the polyline */ + ) +{ + /* XXX kludge until real zero-width dash code is written */ + pgc->lineWidth = 1; + drvWideDash (dst, pgc, mode, nptInit, pptInit); + pgc->lineWidth = 0; +} diff --git a/fb/fbarc.c b/fb/fbarc.c index d28125dc8..9831953c7 100644 --- a/fb/fbarc.c +++ b/fb/fbarc.c @@ -25,7 +25,7 @@ #endif #include "fb.h" -#include "mizerarc.h" +#include "drvzerarc.h" #include <limits.h> typedef void (*FbArc) (FbBits *dst, @@ -79,7 +79,7 @@ fbPolyArc (PixmapPtr pPixmap, #endif while (narcs--) { - if (miCanZeroArc (parcs)) + if (drvCanZeroArc (parcs)) { box.x1 = parcs->x; box.y1 = parcs->y; diff --git a/fb/fbbits.c b/fb/fbbits.c index 850d1632e..565b9c1b9 100644 --- a/fb/fbbits.c +++ b/fb/fbbits.c @@ -25,8 +25,8 @@ #endif #include "fb.h" -#include "miline.h" -#include "mizerarc.h" +#include "drvline.h" +#include "drvzerarc.h" #undef BRESSOLID #undef BRESDASH diff --git a/fb/fbbits.h b/fb/fbbits.h index 4ced7364b..249879dc7 100644 --- a/fb/fbbits.h +++ b/fb/fbbits.h @@ -341,7 +341,7 @@ ARC (FbBits *dst, { UNIT *bits; FbStride bitsStride; - miZeroArcRec info; + drvZeroArcRec info; Bool do360; int x; UNIT *yorgp, *yorgop; @@ -354,12 +354,12 @@ ARC (FbBits *dst, bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); andBits = (BITS) and; xorBits = (BITS) xor; - do360 = miZeroArcSetup(arc, &info, TRUE); + do360 = drvZeroArcSetup(arc, &info, TRUE); yorgp = bits + ((info.yorg + drawY) * bitsStride); yorgop = bits + ((info.yorgo + drawY) * bitsStride); info.xorg = (info.xorg + drawX) * MUL; info.xorgo = (info.xorgo + drawX) * MUL; - MIARCSETUP(); + DRVARCSETUP(); yoffset = y ? bitsStride : 0; dyoffset = 0; mask = info.initialMask; @@ -428,7 +428,7 @@ ARC (FbBits *dst, ARCRROP(yorghb + xoffset - y * MUL); } xoffset += bitsStride; - MIARCCIRCLESTEP(yoffset += bitsStride;); + DRVARCCIRCLESTEP(yoffset += bitsStride;); } yorgp -= info.xorg; yorgop -= info.xorg; @@ -439,7 +439,7 @@ ARC (FbBits *dst, { while (y < info.h || x < info.w) { - MIARCOCTANTSHIFT(dyoffset = bitsStride;); + DRVARCOCTANTSHIFT(dyoffset = bitsStride;); if (andBits == 0) { ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); @@ -454,14 +454,14 @@ ARC (FbBits *dst, ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); ARCRROP(yorgop - yoffset + info.xorg + x * MUL); } - MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;); + DRVARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;); } } else { while (y < info.h || x < info.w) { - MIARCOCTANTSHIFT(dyoffset = bitsStride;); + DRVARCOCTANTSHIFT(dyoffset = bitsStride;); if ((x == info.start.x) || (y == info.start.y)) { mask = info.start.mask; @@ -494,7 +494,7 @@ ARC (FbBits *dst, mask = info.end.mask; info.end = info.altend; } - MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;); + DRVARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;); } } if ((x == info.start.x) || (y == info.start.y)) @@ -669,7 +669,7 @@ POLYLINE (PixmapPtr pPixmap, INT32 *pts = (INT32 *) ptsOrig; int xoff = 0; int yoff = 0; - unsigned int bias = miGetZeroLineBias(pPixmap->pScreen); + unsigned int bias = drvGetZeroLineBias(pPixmap->pScreen); BoxPtr pBox = RegionExtents(fbGetCompositeClip (pGC)); FbBits *dst; @@ -806,7 +806,7 @@ POLYSEGMENT (PixmapPtr pPixmap, INT32 *pts = (INT32 *) pseg; int xoff = 0; int yoff = 0; - unsigned int bias = miGetZeroLineBias(pPixmap->pScreen); + unsigned int bias = drvGetZeroLineBias(pPixmap->pScreen); BoxPtr pBox = RegionExtents(fbGetCompositeClip (pGC)); FbBits *dst; @@ -39,15 +39,15 @@ const GCOps fbGCOps = { fbPolyPoint, fbPolyLine, fbPolySegment, - NULL, + drvPolyRectangle, fbPolyArc, - NULL, + drvFillPolygon, fbPolyFillRect, - NULL, - NULL, - NULL, - NULL, - NULL, + drvPolyFillArc, + drvPolyText8, + drvPolyText16, + drvImageText8, + drvImageText16, fbImageGlyphBlt, fbPolyGlyphBlt, fbPushPixels, diff --git a/fb/fbseg.c b/fb/fbseg.c index 23acf2437..b82607895 100644 --- a/fb/fbseg.c +++ b/fb/fbseg.c @@ -27,7 +27,7 @@ #include <stdlib.h> #include "fb.h" -#include "miline.h" +#include "drvline.h" #define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \ ((dir < 0) ? FbStipLeft(mask,bpp) : \ @@ -606,7 +606,7 @@ fbSegment (PixmapPtr pPixmap, int octant; int dashoff; int doff; - unsigned int bias = miGetZeroLineBias(pPixmap->pScreen); + unsigned int bias = drvGetZeroLineBias(pPixmap->pScreen); unsigned int oc1; /* outcode of point 1 */ unsigned int oc2; /* outcode of point 2 */ @@ -676,7 +676,7 @@ fbSegment (PixmapPtr pPixmap, int clipdx, clipdy; int err; - if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1, + if (drvZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1, pBox->y2-1, &new_x1, &new_y1, &new_x2, &new_y2, adx, ady, &clip1, &clip2, diff --git a/mi/Makefile.am b/mi/Makefile.am index 3821bbdc5..817d9d25b 100644 --- a/mi/Makefile.am +++ b/mi/Makefile.am @@ -40,6 +40,7 @@ libmi_la_SOURCES = \ mipolycon.c \ mipolygen.c \ mipolypnt.c \ + mipolyrect.c \ mipolyseg.c \ mipolytext.c \ mipolyutil.c \ diff --git a/drv/mipolyrect.c b/mi/mipolyrect.c index 9b0edc176..9b0edc176 100644 --- a/drv/mipolyrect.c +++ b/mi/mipolyrect.c |