diff options
author | marha <marha@users.sourceforge.net> | 2012-03-26 14:23:28 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-03-26 14:23:28 +0200 |
commit | 76bcc36ed305418a3ddc5752d287ede894243e1b (patch) | |
tree | bacb320c825768471ce56f058f17ce863d592376 /xorg-server/mi/miarc.c | |
parent | 7d894e32566b710952c44cbc71939ad1d9e2fa8d (diff) | |
parent | 0f834b91a4768673833ab4917e87d86c237bb1a6 (diff) | |
download | vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.gz vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.bz2 vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.zip |
Merge remote-tracking branch 'origin/released'
Conflicts:
pixman/pixman/pixman-mmx.c
xorg-server/Xext/shm.c
xorg-server/Xext/syncsrv.h
xorg-server/Xext/xvmain.c
xorg-server/Xi/exevents.c
xorg-server/Xi/opendev.c
xorg-server/composite/compalloc.c
xorg-server/composite/compoverlay.c
xorg-server/dix/colormap.c
xorg-server/dix/devices.c
xorg-server/dix/dispatch.c
xorg-server/dix/dixfonts.c
xorg-server/dix/eventconvert.c
xorg-server/dix/events.c
xorg-server/dix/gc.c
xorg-server/dix/getevents.c
xorg-server/dix/main.c
xorg-server/dix/privates.c
xorg-server/dix/registry.c
xorg-server/dix/resource.c
xorg-server/exa/exa_accel.c
xorg-server/exa/exa_migration_classic.c
xorg-server/exa/exa_unaccel.c
xorg-server/fb/fb.h
xorg-server/fb/fbcopy.c
xorg-server/fb/fbpixmap.c
xorg-server/glx/dispatch.h
xorg-server/glx/glapi.h
xorg-server/glx/glapi_gentable.c
xorg-server/glx/glapitable.h
xorg-server/glx/glprocs.h
xorg-server/glx/glxcmds.c
xorg-server/glx/glxcmdsswap.c
xorg-server/glx/glxdricommon.c
xorg-server/glx/glxdriswrast.c
xorg-server/glx/glxext.c
xorg-server/glx/indirect_dispatch.c
xorg-server/glx/indirect_dispatch.h
xorg-server/glx/indirect_dispatch_swap.c
xorg-server/glx/indirect_size.h
xorg-server/glx/indirect_size_get.h
xorg-server/glx/indirect_table.c
xorg-server/glx/indirect_util.c
xorg-server/glx/rensize.c
xorg-server/glx/single2swap.c
xorg-server/glx/singlepix.c
xorg-server/glx/singlepixswap.c
xorg-server/glx/singlesize.c
xorg-server/hw/dmx/dmxinit.c
xorg-server/hw/kdrive/ephyr/ephyr.c
xorg-server/hw/kdrive/ephyr/hostx.c
xorg-server/hw/kdrive/ephyr/hostx.h
xorg-server/hw/kdrive/src/kinput.c
xorg-server/hw/xfree86/common/compiler.h
xorg-server/hw/xwin/InitInput.c
xorg-server/hw/xwin/InitOutput.c
xorg-server/hw/xwin/ddraw.h
xorg-server/hw/xwin/glx/glwrap.c
xorg-server/hw/xwin/glx/indirect.c
xorg-server/hw/xwin/glx/wgl_ext_api.h
xorg-server/hw/xwin/glx/winpriv.c
xorg-server/hw/xwin/win.h
xorg-server/hw/xwin/winallpriv.c
xorg-server/hw/xwin/winauth.c
xorg-server/hw/xwin/winclipboard.h
xorg-server/hw/xwin/winclipboardinit.c
xorg-server/hw/xwin/winclipboardthread.c
xorg-server/hw/xwin/winclipboardunicode.c
xorg-server/hw/xwin/winclipboardwndproc.c
xorg-server/hw/xwin/winclipboardwrappers.c
xorg-server/hw/xwin/winclipboardxevents.c
xorg-server/hw/xwin/wincmap.c
xorg-server/hw/xwin/winconfig.c
xorg-server/hw/xwin/wincreatewnd.c
xorg-server/hw/xwin/wincursor.c
xorg-server/hw/xwin/windialogs.c
xorg-server/hw/xwin/winengine.c
xorg-server/hw/xwin/winerror.c
xorg-server/hw/xwin/wingc.c
xorg-server/hw/xwin/wingetsp.c
xorg-server/hw/xwin/winkeybd.c
xorg-server/hw/xwin/winkeybd.h
xorg-server/hw/xwin/winlayouts.h
xorg-server/hw/xwin/winmisc.c
xorg-server/hw/xwin/winmonitors.c
xorg-server/hw/xwin/winmouse.c
xorg-server/hw/xwin/winmsg.c
xorg-server/hw/xwin/winmsg.h
xorg-server/hw/xwin/winmultiwindowclass.c
xorg-server/hw/xwin/winmultiwindowicons.c
xorg-server/hw/xwin/winmultiwindowshape.c
xorg-server/hw/xwin/winmultiwindowwindow.c
xorg-server/hw/xwin/winmultiwindowwm.c
xorg-server/hw/xwin/winmultiwindowwndproc.c
xorg-server/hw/xwin/winnativegdi.c
xorg-server/hw/xwin/winpfbdd.c
xorg-server/hw/xwin/winpixmap.c
xorg-server/hw/xwin/winpolyline.c
xorg-server/hw/xwin/winprefs.c
xorg-server/hw/xwin/winprocarg.c
xorg-server/hw/xwin/winregistry.c
xorg-server/hw/xwin/winscrinit.c
xorg-server/hw/xwin/winsetsp.c
xorg-server/hw/xwin/winshaddd.c
xorg-server/hw/xwin/winshadddnl.c
xorg-server/hw/xwin/winshadgdi.c
xorg-server/hw/xwin/wintrayicon.c
xorg-server/hw/xwin/winwin32rootless.c
xorg-server/hw/xwin/winwin32rootlesswindow.c
xorg-server/hw/xwin/winwin32rootlesswndproc.c
xorg-server/hw/xwin/winwindow.c
xorg-server/hw/xwin/winwindow.h
xorg-server/hw/xwin/winwindowswm.c
xorg-server/hw/xwin/winwndproc.c
xorg-server/include/callback.h
xorg-server/include/dixstruct.h
xorg-server/include/misc.h
xorg-server/include/os.h
xorg-server/include/scrnintstr.h
xorg-server/mi/micmap.c
xorg-server/mi/miinitext.c
xorg-server/mi/mioverlay.c
xorg-server/mi/misprite.c
xorg-server/mi/mivaltree.c
xorg-server/mi/miwindow.c
xorg-server/miext/damage/damage.c
xorg-server/miext/rootless/rootlessGC.c
xorg-server/miext/rootless/rootlessWindow.c
xorg-server/os/WaitFor.c
xorg-server/os/access.c
xorg-server/os/connection.c
xorg-server/os/io.c
xorg-server/os/log.c
xorg-server/os/osinit.c
xorg-server/os/utils.c
xorg-server/os/xdmcp.c
xorg-server/os/xprintf.c
xorg-server/os/xstrans.c
xorg-server/render/mipict.c
xorg-server/xkb/xkbActions.c
xorg-server/xkb/xkbInit.c
xorg-server/xkeyboard-config/compat/default.in
Diffstat (limited to 'xorg-server/mi/miarc.c')
-rw-r--r-- | xorg-server/mi/miarc.c | 5238 |
1 files changed, 2525 insertions, 2713 deletions
diff --git a/xorg-server/mi/miarc.c b/xorg-server/mi/miarc.c index 9fc8f478c..a73bce9e6 100644 --- a/xorg-server/mi/miarc.c +++ b/xorg-server/mi/miarc.c @@ -22,7 +22,6 @@ 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 @@ -78,9 +77,9 @@ static double cbrt(double x) { if (x > 0.0) - return pow(x, 1.0/3.0); + return pow(x, 1.0 / 3.0); else - return -pow(-x, 1.0/3.0); + return -pow(-x, 1.0 / 3.0); } #endif @@ -107,30 +106,32 @@ cbrt(double x) #undef max #undef min -_X_INLINE static int max (const int x, const int y) +_X_INLINE static int +max(const int x, const int y) { - return x>y? x:y; + return x > y ? x : y; } -_X_INLINE static int min (const int x, const int y) +_X_INLINE static int +min(const int x, const int y) { - return x<y? x:y; + return x < y ? x : y; } struct bound { - double min, max; + double min, max; }; struct ibound { - int min, max; + int min, max; }; #define boundedLe(value, bounds)\ ((bounds).min <= (value) && (value) <= (bounds).max) struct line { - double m, b; - int valid; + double m, b; + int valid; }; #define intersectLine(y,line) (line.m * (y) + line.b) @@ -140,67 +141,67 @@ struct line { */ struct arc_bound { - struct bound ellipse; - struct bound inner; - struct bound outer; - struct bound right; - struct bound left; - struct ibound inneri; - struct ibound outeri; + struct bound ellipse; + struct bound inner; + struct bound outer; + struct bound right; + struct bound left; + struct ibound inneri; + struct ibound outeri; }; struct accelerators { - double tail_y; - double h2; - double w2; - double h4; - double w4; - double h2mw2; - double h2l; - double w2l; - double fromIntX; - double fromIntY; - struct line left, right; - int yorgu; - int yorgl; - int xorg; + double tail_y; + double h2; + double w2; + double h4; + double w4; + double h2mw2; + double h2l; + double w2l; + double fromIntX; + double fromIntY; + struct line left, right; + int yorgu; + int yorgl; + int xorg; }; struct arc_def { - double w, h, l; - double a0, a1; + double w, h, l; + double a0, a1; }; -# define todeg(xAngle) (((double) (xAngle)) / 64.0) +#define todeg(xAngle) (((double) (xAngle)) / 64.0) -# define RIGHT_END 0 -# define LEFT_END 1 +#define RIGHT_END 0 +#define LEFT_END 1 typedef struct _miArcJoin { - int arcIndex0, arcIndex1; - int phase0, phase1; - int end0, end1; + int arcIndex0, arcIndex1; + int phase0, phase1; + int end0, end1; } miArcJoinRec, *miArcJoinPtr; typedef struct _miArcCap { - int arcIndex; - int end; + int arcIndex; + int end; } miArcCapRec, *miArcCapPtr; typedef struct _miArcFace { - SppPointRec clock; - SppPointRec center; - SppPointRec counterClock; + SppPointRec clock; + SppPointRec center; + SppPointRec counterClock; } miArcFaceRec, *miArcFacePtr; typedef struct _miArcData { - xArc arc; - int render; /* non-zero means render after drawing */ - int join; /* related join */ - int cap; /* related cap */ - int selfJoin; /* final dash meets first dash */ - miArcFaceRec bounds[2]; - double x0, y0, x1, y1; + xArc arc; + int render; /* non-zero means render after drawing */ + int join; /* related join */ + int cap; /* related cap */ + int selfJoin; /* final dash meets first dash */ + miArcFaceRec bounds[2]; + double x0, y0, x1, y1; } miArcDataRec, *miArcDataPtr; /* @@ -209,101 +210,98 @@ typedef struct _miArcData { */ typedef struct _miPolyArc { - int narcs; - miArcDataPtr arcs; - int ncaps; - miArcCapPtr caps; - int njoins; - miArcJoinPtr joins; + int narcs; + miArcDataPtr arcs; + int ncaps; + miArcCapPtr caps; + int njoins; + miArcJoinPtr joins; } miPolyArcRec, *miPolyArcPtr; static void fillSpans(DrawablePtr pDrawable, GCPtr pGC); static void newFinalSpan(int y, int xmin, int xmax); -static void drawArc(xArc *tarc, int l, int a0, int a1, miArcFacePtr right, - miArcFacePtr left); -static void drawZeroArc(DrawablePtr pDraw, GCPtr pGC, xArc *tarc, int lw, - miArcFacePtr left, miArcFacePtr right); +static void drawArc(xArc * tarc, int l, int a0, int a1, miArcFacePtr right, + miArcFacePtr left); +static void drawZeroArc(DrawablePtr pDraw, GCPtr pGC, xArc * tarc, int lw, + miArcFacePtr left, miArcFacePtr right); static void miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft, - miArcFacePtr pRight, int xOrgLeft, int yOrgLeft, - double xFtransLeft, double yFtransLeft, - int xOrgRight, int yOrgRight, - double xFtransRight, double yFtransRight); + miArcFacePtr pRight, int xOrgLeft, int yOrgLeft, + double xFtransLeft, double yFtransLeft, + int xOrgRight, int yOrgRight, + double xFtransRight, double yFtransRight); static void miArcCap(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pFace, - int end, int xOrg, int yOrg, double xFtrans, - double yFtrans); + int end, int xOrg, int yOrg, double xFtrans, + double yFtrans); static void miRoundCap(DrawablePtr pDraw, GCPtr pGC, SppPointRec pCenter, - SppPointRec pEnd, SppPointRec pCorner, - SppPointRec pOtherCorner, int fLineEnd, - int xOrg, int yOrg, double xFtrans, double yFtrans); + SppPointRec pEnd, SppPointRec pCorner, + SppPointRec pOtherCorner, int fLineEnd, + int xOrg, int yOrg, double xFtrans, double yFtrans); static void miFreeArcs(miPolyArcPtr arcs, GCPtr pGC); -static miPolyArcPtr miComputeArcs(xArc *parcs, int narcs, GCPtr pGC); -static int miGetArcPts(SppArcPtr parc, int cpt, SppPointPtr *ppPts); +static miPolyArcPtr miComputeArcs(xArc * parcs, int narcs, GCPtr pGC); +static int miGetArcPts(SppArcPtr parc, int cpt, SppPointPtr * ppPts); -# define CUBED_ROOT_2 1.2599210498948732038115849718451499938964 -# define CUBED_ROOT_4 1.5874010519681993173435330390930175781250 +#define CUBED_ROOT_2 1.2599210498948732038115849718451499938964 +#define CUBED_ROOT_4 1.5874010519681993173435330390930175781250 /* * draw one segment of the arc using the arc spans generation routines */ static void -miArcSegment( - DrawablePtr pDraw, - GCPtr pGC, - xArc tarc, - miArcFacePtr right, - miArcFacePtr left) +miArcSegment(DrawablePtr pDraw, + GCPtr pGC, xArc tarc, miArcFacePtr right, miArcFacePtr left) { int l = pGC->lineWidth; int a0, a1, startAngle, endAngle; miArcFacePtr temp; if (!l) - l = 1; + l = 1; if (tarc.width == 0 || tarc.height == 0) { - drawZeroArc (pDraw, pGC, &tarc, l, left, right); - return; + drawZeroArc(pDraw, pGC, &tarc, l, left, right); + return; } if (pGC->miTranslate) { - tarc.x += pDraw->x; - tarc.y += pDraw->y; + tarc.x += pDraw->x; + tarc.y += pDraw->y; } a0 = tarc.angle1; a1 = tarc.angle2; if (a1 > FULLCIRCLE) - a1 = FULLCIRCLE; + a1 = FULLCIRCLE; else if (a1 < -FULLCIRCLE) - a1 = -FULLCIRCLE; + a1 = -FULLCIRCLE; if (a1 < 0) { - startAngle = a0 + a1; - endAngle = a0; - temp = right; - right = left; - left = temp; - } else { - startAngle = a0; - endAngle = a0 + a1; + startAngle = a0 + a1; + endAngle = a0; + temp = right; + right = left; + left = temp; + } + else { + startAngle = a0; + endAngle = a0 + a1; } /* * bounds check the two angles */ if (startAngle < 0) - startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; + startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; if (startAngle >= FULLCIRCLE) - startAngle = startAngle % FULLCIRCLE; + startAngle = startAngle % FULLCIRCLE; if (endAngle < 0) - endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; + endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; if (endAngle > FULLCIRCLE) - endAngle = (endAngle-1) % FULLCIRCLE + 1; + endAngle = (endAngle - 1) % FULLCIRCLE + 1; if ((startAngle == endAngle) && a1) { - startAngle = 0; - endAngle = FULLCIRCLE; + startAngle = 0; + endAngle = FULLCIRCLE; } - drawArc (&tarc, l, startAngle, endAngle, right, left); + drawArc(&tarc, l, startAngle, endAngle, right, left); } /* @@ -380,14 +378,11 @@ typedef struct { } miArcSpanData; static void drawQuadrant(struct arc_def *def, struct accelerators *acc, - int a0, int a1, int mask, miArcFacePtr right, - miArcFacePtr left, miArcSpanData *spdata); + int a0, int a1, int mask, miArcFacePtr right, + miArcFacePtr left, miArcSpanData * spdata); static void -miComputeCircleSpans( - int lw, - xArc *parc, - miArcSpanData *spdata) +miComputeCircleSpans(int lw, xArc * parc, miArcSpanData * spdata) { miArcSpan *span; int doinner; @@ -404,58 +399,48 @@ miComputeCircleSpans( dx = 1 - dy; MIWIDEARCSETUP(x, y, dy, slw, e, xk, xm, yk, ym); inslw = parc->width + doinner; - if (inslw > 0) - { - spdata->hole = spdata->top; - MIWIDEARCSETUP(inx, iny, dy, inslw, ine, inxk, inxm, inyk, inym); + if (inslw > 0) { + spdata->hole = spdata->top; + MIWIDEARCSETUP(inx, iny, dy, inslw, ine, inxk, inxm, inyk, inym); } - else - { - spdata->hole = FALSE; - doinner = -y; + else { + spdata->hole = FALSE; + doinner = -y; } spdata->count1 = -doinner - spdata->top; spdata->count2 = y + doinner; span = spdata->spans; - while (y) - { - MIFILLARCSTEP(slw); - span->lx = dy - x; - if (++doinner <= 0) - { - span->lw = slw; - span->rx = 0; - span->rw = span->lx + slw; - } - else - { - MIFILLINARCSTEP(inslw); - span->lw = x - inx; - span->rx = dy - inx + inslw; - span->rw = inx - x + slw - inslw; - } - span++; - } - if (spdata->bot) - { - if (spdata->count2) - spdata->count2--; - else - { - if (lw > (int)parc->height) - span[-1].rx = span[-1].rw = -((lw - (int)parc->height) >> 1); - else - span[-1].rw = 0; - spdata->count1--; - } + while (y) { + MIFILLARCSTEP(slw); + span->lx = dy - x; + if (++doinner <= 0) { + span->lw = slw; + span->rx = 0; + span->rw = span->lx + slw; + } + else { + MIFILLINARCSTEP(inslw); + span->lw = x - inx; + span->rx = dy - inx + inslw; + span->rw = inx - x + slw - inslw; + } + span++; + } + if (spdata->bot) { + if (spdata->count2) + spdata->count2--; + else { + if (lw > (int) parc->height) + span[-1].rx = span[-1].rw = -((lw - (int) parc->height) >> 1); + else + span[-1].rw = 0; + spdata->count1--; + } } } static void -miComputeEllipseSpans( - int lw, - xArc *parc, - miArcSpanData *spdata) +miComputeEllipseSpans(int lw, xArc * parc, miArcSpanData * spdata) { miArcSpan *span; double w, h, r, xorg; @@ -463,8 +448,8 @@ miComputeEllipseSpans( double A, T, b, d, x, y, t, inx, outx = 0.0, hepp, hepm; int flip, solution; - w = (double)parc->width / 2.0; - h = (double)parc->height / 2.0; + w = (double) parc->width / 2.0; + h = (double) parc->height / 2.0; r = lw / 2.0; rs = r * r; Hs = h * h; @@ -479,177 +464,159 @@ miComputeEllipseSpans( K = h + ((lw - 1) >> 1); span = spdata->spans; if (parc->width & 1) - xorg = .5; + xorg = .5; else - xorg = 0.0; - if (spdata->top) - { - span->lx = 0; - span->lw = 1; - span++; + xorg = 0.0; + if (spdata->top) { + span->lx = 0; + span->lw = 1; + span++; } spdata->count1 = 0; spdata->count2 = 0; spdata->hole = (spdata->top && - (int)parc->height * lw <= (int)(parc->width * parc->width) && - lw < (int)parc->height); - for (; K > 0.0; K -= 1.0) - { - N = (K * K + Nk) / 6.0; - Nc = N * N * N; - Vr = Vk * K; - t = Nc + Vr * Vr; - d = Nc + t; - if (d < 0.0) { - d = Nc; - b = N; - if ( (b < 0.0) == (t < 0.0) ) - { - b = -b; - d = -d; - } - Z = N - 2.0 * b * cos(acos(-t / d) / 3.0); - if ( (Z < 0.0) == (Vr < 0.0) ) - flip = 2; - else - flip = 1; - } - else - { - d = Vr * sqrt(d); - Z = N + cbrt(t + d) + cbrt(t - d); - flip = 0; - } - A = sqrt((Z + Z) - Nk); - T = (Fk - Z) * K / A; - inx = 0.0; - solution = FALSE; - b = -A + K; - d = b * b - 4 * (Z + T); - if (d >= 0) - { - d = sqrt(d); - y = (b + d) / 2; - if ((y >= 0.0) && (y < hepp)) - { - solution = TRUE; - if (y > hepm) - y = h; - t = y / h; - x = w * sqrt(1 - (t * t)); - t = K - y; - if (rs - (t * t) >= 0) - t = sqrt(rs - (t * t)); - else - t = 0; - if (flip == 2) - inx = x - t; - else - outx = x + t; - } - } - b = A + K; - d = b * b - 4 * (Z - T); - /* Because of the large magnitudes involved, we lose enough precision - * that sometimes we end up with a negative value near the axis, when - * it should be positive. This is a workaround. - */ - if (d < 0 && !solution) - d = 0.0; - if (d >= 0) { - d = sqrt(d); - y = (b + d) / 2; - if (y < hepp) - { - if (y > hepm) - y = h; - t = y / h; - x = w * sqrt(1 - (t * t)); - t = K - y; - if (rs - (t * t) >= 0) - inx = x - sqrt(rs - (t * t)); - else - inx = x; - } - y = (b - d) / 2; - if (y >= 0.0) - { - if (y > hepm) - y = h; - t = y / h; - x = w * sqrt(1 - (t * t)); - t = K - y; - if (rs - (t * t) >= 0) - t = sqrt(rs - (t * t)); - else - t = 0; - if (flip == 1) - inx = x - t; - else - outx = x + t; - } - } - span->lx = ICEIL(xorg - outx); - if (inx <= 0.0) - { - spdata->count1++; - span->lw = ICEIL(xorg + outx) - span->lx; - span->rx = ICEIL(xorg + inx); - span->rw = -ICEIL(xorg - inx); - } - else - { - spdata->count2++; - span->lw = ICEIL(xorg - inx) - span->lx; - span->rx = ICEIL(xorg + inx); - span->rw = ICEIL(xorg + outx) - span->rx; - } - span++; - } - if (spdata->bot) - { - outx = w + r; - if (r >= h && r <= w) - inx = 0.0; - else if (Nk < 0.0 && -Nk < Hs) - { - inx = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk); - if (inx > w - r) - inx = w - r; - } - else - inx = w - r; - span->lx = ICEIL(xorg - outx); - if (inx <= 0.0) - { - span->lw = ICEIL(xorg + outx) - span->lx; - span->rx = ICEIL(xorg + inx); - span->rw = -ICEIL(xorg - inx); - } - else - { - span->lw = ICEIL(xorg - inx) - span->lx; - span->rx = ICEIL(xorg + inx); - span->rw = ICEIL(xorg + outx) - span->rx; - } - } - if (spdata->hole) - { - span = &spdata->spans[spdata->count1]; - span->lw = -span->lx; - span->rx = 1; - span->rw = span->lw; - spdata->count1--; - spdata->count2++; + (int) parc->height * lw <= (int) (parc->width * parc->width) + && lw < (int) parc->height); + for (; K > 0.0; K -= 1.0) { + N = (K * K + Nk) / 6.0; + Nc = N * N * N; + Vr = Vk * K; + t = Nc + Vr * Vr; + d = Nc + t; + if (d < 0.0) { + d = Nc; + b = N; + if ((b < 0.0) == (t < 0.0)) { + b = -b; + d = -d; + } + Z = N - 2.0 * b * cos(acos(-t / d) / 3.0); + if ((Z < 0.0) == (Vr < 0.0)) + flip = 2; + else + flip = 1; + } + else { + d = Vr * sqrt(d); + Z = N + cbrt(t + d) + cbrt(t - d); + flip = 0; + } + A = sqrt((Z + Z) - Nk); + T = (Fk - Z) * K / A; + inx = 0.0; + solution = FALSE; + b = -A + K; + d = b * b - 4 * (Z + T); + if (d >= 0) { + d = sqrt(d); + y = (b + d) / 2; + if ((y >= 0.0) && (y < hepp)) { + solution = TRUE; + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + if (rs - (t * t) >= 0) + t = sqrt(rs - (t * t)); + else + t = 0; + if (flip == 2) + inx = x - t; + else + outx = x + t; + } + } + b = A + K; + d = b * b - 4 * (Z - T); + /* Because of the large magnitudes involved, we lose enough precision + * that sometimes we end up with a negative value near the axis, when + * it should be positive. This is a workaround. + */ + if (d < 0 && !solution) + d = 0.0; + if (d >= 0) { + d = sqrt(d); + y = (b + d) / 2; + if (y < hepp) { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + if (rs - (t * t) >= 0) + inx = x - sqrt(rs - (t * t)); + else + inx = x; + } + y = (b - d) / 2; + if (y >= 0.0) { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + if (rs - (t * t) >= 0) + t = sqrt(rs - (t * t)); + else + t = 0; + if (flip == 1) + inx = x - t; + else + outx = x + t; + } + } + span->lx = ICEIL(xorg - outx); + if (inx <= 0.0) { + spdata->count1++; + span->lw = ICEIL(xorg + outx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = -ICEIL(xorg - inx); + } + else { + spdata->count2++; + span->lw = ICEIL(xorg - inx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = ICEIL(xorg + outx) - span->rx; + } + span++; + } + if (spdata->bot) { + outx = w + r; + if (r >= h && r <= w) + inx = 0.0; + else if (Nk < 0.0 && -Nk < Hs) { + inx = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk); + if (inx > w - r) + inx = w - r; + } + else + inx = w - r; + span->lx = ICEIL(xorg - outx); + if (inx <= 0.0) { + span->lw = ICEIL(xorg + outx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = -ICEIL(xorg - inx); + } + else { + span->lw = ICEIL(xorg - inx) - span->lx; + span->rx = ICEIL(xorg + inx); + span->rw = ICEIL(xorg + outx) - span->rx; + } + } + if (spdata->hole) { + span = &spdata->spans[spdata->count1]; + span->lw = -span->lx; + span->rx = 1; + span->rw = span->lw; + spdata->count1--; + spdata->count2++; } } static double -tailX( - double K, - struct arc_def *def, - struct arc_bound *bounds, - struct accelerators *acc) +tailX(double K, + struct arc_def *def, struct arc_bound *bounds, struct accelerators *acc) { double w, h, r; double Hs, Hf, WH, Vk, Nk, Fk, Vr, N, Nc, Z, rs; @@ -669,18 +636,18 @@ tailX( Hf = acc->h4; Nk = (Hf - Nk * Nk) / WH; if (K == 0.0) { - if (Nk < 0.0 && -Nk < Hs) { - xs[0] = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk); - xs[1] = w - r; - if (acc->left.valid && boundedLe(K, bounds->left) && - !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0) - return xs[1]; - if (acc->right.valid && boundedLe(K, bounds->right) && - !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0) - return xs[1]; - return xs[0]; - } - return w - r; + if (Nk < 0.0 && -Nk < Hs) { + xs[0] = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk); + xs[1] = w - r; + if (acc->left.valid && boundedLe(K, bounds->left) && + !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0) + return xs[1]; + if (acc->right.valid && boundedLe(K, bounds->right) && + !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0) + return xs[1]; + return xs[0]; + } + return w - r; } Fk = Hf / WH; hepp = h + EPSILON; @@ -693,48 +660,44 @@ tailX( t = Nc + Vr * Vr; d = Nc + t; if (d < 0.0) { - d = Nc; - b = N; - if ( (b < 0.0) == (t < 0.0) ) - { - b = -b; - d = -d; - } - Z = N - 2.0 * b * cos(acos(-t / d) / 3.0); - if ( (Z < 0.0) == (Vr < 0.0) ) - flip = 2; - else - flip = 1; + d = Nc; + b = N; + if ((b < 0.0) == (t < 0.0)) { + b = -b; + d = -d; + } + Z = N - 2.0 * b * cos(acos(-t / d) / 3.0); + if ((Z < 0.0) == (Vr < 0.0)) + flip = 2; + else + flip = 1; } - else - { - d = Vr * sqrt(d); - Z = N + cbrt(t + d) + cbrt(t - d); - flip = 0; + else { + d = Vr * sqrt(d); + Z = N + cbrt(t + d) + cbrt(t - d); + flip = 0; } A = sqrt((Z + Z) - Nk); T = (Fk - Z) * K / A; solution = FALSE; b = -A + K; d = b * b - 4 * (Z + T); - if (d >= 0 && flip == 2) - { - d = sqrt(d); - y = (b + d) / 2; - if ((y >= 0.0) && (y < hepp)) - { - solution = TRUE; - if (y > hepm) - y = h; - t = y / h; - x = w * sqrt(1 - (t * t)); - t = K - y; - if (rs - (t * t) >= 0) - t = sqrt(rs - (t * t)); - else - t = 0; - *xp++ = x - t; - } + if (d >= 0 && flip == 2) { + d = sqrt(d); + y = (b + d) / 2; + if ((y >= 0.0) && (y < hepp)) { + solution = TRUE; + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + if (rs - (t * t) >= 0) + t = sqrt(rs - (t * t)); + else + t = 0; + *xp++ = x - t; + } } b = A + K; d = b * b - 4 * (Z - T); @@ -743,76 +706,71 @@ tailX( * it should be positive. This is a workaround. */ if (d < 0 && !solution) - d = 0.0; + d = 0.0; if (d >= 0) { - d = sqrt(d); - y = (b + d) / 2; - if (y < hepp) - { - if (y > hepm) - y = h; - t = y / h; - x = w * sqrt(1 - (t * t)); - t = K - y; - if (rs - (t * t) >= 0) - *xp++ = x - sqrt(rs - (t * t)); - else - *xp++ = x; - } - y = (b - d) / 2; - if (y >= 0.0 && flip == 1) - { - if (y > hepm) - y = h; - t = y / h; - x = w * sqrt(1 - (t * t)); - t = K - y; - if (rs - (t * t) >= 0) - t = sqrt(rs - (t * t)); - else - t = 0; - *xp++ = x - t; - } + d = sqrt(d); + y = (b + d) / 2; + if (y < hepp) { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + if (rs - (t * t) >= 0) + *xp++ = x - sqrt(rs - (t * t)); + else + *xp++ = x; + } + y = (b - d) / 2; + if (y >= 0.0 && flip == 1) { + if (y > hepm) + y = h; + t = y / h; + x = w * sqrt(1 - (t * t)); + t = K - y; + if (rs - (t * t) >= 0) + t = sqrt(rs - (t * t)); + else + t = 0; + *xp++ = x - t; + } } if (xp > &xs[1]) { - if (acc->left.valid && boundedLe(K, bounds->left) && - !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0) - return xs[1]; - if (acc->right.valid && boundedLe(K, bounds->right) && - !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0) - return xs[1]; + if (acc->left.valid && boundedLe(K, bounds->left) && + !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0) + return xs[1]; + if (acc->right.valid && boundedLe(K, bounds->right) && + !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0) + return xs[1]; } return xs[0]; } static miArcSpanData * -miComputeWideEllipse(int lw, xArc *parc) +miComputeWideEllipse(int lw, xArc * parc) { miArcSpanData *spdata = NULL; int k; if (!lw) - lw = 1; + lw = 1; k = (parc->height >> 1) + ((lw - 1) >> 1); spdata = malloc(sizeof(miArcSpanData) + sizeof(miArcSpan) * (k + 2)); if (!spdata) - return NULL; - spdata->spans = (miArcSpan *)(spdata + 1); + return NULL; + spdata->spans = (miArcSpan *) (spdata + 1); spdata->k = k; spdata->top = !(lw & 1) && !(parc->width & 1); spdata->bot = !(parc->height & 1); if (parc->width == parc->height) - miComputeCircleSpans(lw, parc, spdata); + miComputeCircleSpans(lw, parc, spdata); else - miComputeEllipseSpans(lw, parc, spdata); + miComputeEllipseSpans(lw, parc, spdata); return spdata; } static void -miFillWideEllipse( - DrawablePtr pDraw, - GCPtr pGC, - xArc *parc) +miFillWideEllipse(DrawablePtr pDraw, GCPtr pGC, xArc * parc) { DDXPointPtr points; DDXPointPtr pts; @@ -827,13 +785,12 @@ miFillWideEllipse( n = (sizeof(int) * 2) * yorgu; widths = malloc(n + (sizeof(DDXPointRec) * 2) * yorgu); if (!widths) - return; - points = (DDXPointPtr)((char *)widths + n); - spdata = miComputeWideEllipse((int)pGC->lineWidth, parc); - if (!spdata) - { - free(widths); - return; + return; + points = (DDXPointPtr) ((char *) widths + n); + spdata = miComputeWideEllipse((int) pGC->lineWidth, parc); + if (!spdata) { + free(widths); + return; } pts = points; wids = widths; @@ -841,88 +798,80 @@ miFillWideEllipse( xorg = parc->x + (parc->width >> 1); yorgu = parc->y + (parc->height >> 1); yorgl = yorgu + (parc->height & 1); - if (pGC->miTranslate) - { - xorg += pDraw->x; - yorgu += pDraw->y; - yorgl += pDraw->y; + if (pGC->miTranslate) { + xorg += pDraw->x; + yorgu += pDraw->y; + yorgl += pDraw->y; } yorgu -= spdata->k; yorgl += spdata->k; - if (spdata->top) - { - pts->x = xorg; - pts->y = yorgu - 1; - pts++; - *wids++ = 1; - span++; - } - for (n = spdata->count1; --n >= 0; ) - { - pts[0].x = xorg + span->lx; - pts[0].y = yorgu; - wids[0] = span->lw; - pts[1].x = pts[0].x; - pts[1].y = yorgl; - wids[1] = wids[0]; - yorgu++; - yorgl--; - pts += 2; - wids += 2; - span++; - } - if (spdata->hole) - { - pts[0].x = xorg; - pts[0].y = yorgl; - wids[0] = 1; - pts++; - wids++; - } - for (n = spdata->count2; --n >= 0; ) - { - pts[0].x = xorg + span->lx; - pts[0].y = yorgu; - wids[0] = span->lw; - pts[1].x = xorg + span->rx; - pts[1].y = pts[0].y; - wids[1] = span->rw; - pts[2].x = pts[0].x; - pts[2].y = yorgl; - wids[2] = wids[0]; - pts[3].x = pts[1].x; - pts[3].y = pts[2].y; - wids[3] = wids[1]; - yorgu++; - yorgl--; - pts += 4; - wids += 4; - span++; - } - if (spdata->bot) - { - if (span->rw <= 0) - { - pts[0].x = xorg + span->lx; - pts[0].y = yorgu; - wids[0] = span->lw; - pts++; - wids++; - } - else - { - pts[0].x = xorg + span->lx; - pts[0].y = yorgu; - wids[0] = span->lw; - pts[1].x = xorg + span->rx; - pts[1].y = pts[0].y; - wids[1] = span->rw; - pts += 2; - wids += 2; - } + if (spdata->top) { + pts->x = xorg; + pts->y = yorgu - 1; + pts++; + *wids++ = 1; + span++; + } + for (n = spdata->count1; --n >= 0;) { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts[1].x = pts[0].x; + pts[1].y = yorgl; + wids[1] = wids[0]; + yorgu++; + yorgl--; + pts += 2; + wids += 2; + span++; + } + if (spdata->hole) { + pts[0].x = xorg; + pts[0].y = yorgl; + wids[0] = 1; + pts++; + wids++; + } + for (n = spdata->count2; --n >= 0;) { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts[1].x = xorg + span->rx; + pts[1].y = pts[0].y; + wids[1] = span->rw; + pts[2].x = pts[0].x; + pts[2].y = yorgl; + wids[2] = wids[0]; + pts[3].x = pts[1].x; + pts[3].y = pts[2].y; + wids[3] = wids[1]; + yorgu++; + yorgl--; + pts += 4; + wids += 4; + span++; + } + if (spdata->bot) { + if (span->rw <= 0) { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts++; + wids++; + } + else { + pts[0].x = xorg + span->lx; + pts[0].y = yorgu; + wids[0] = span->lw; + pts[1].x = xorg + span->rx; + pts[1].y = pts[0].y; + wids[1] = span->rw; + pts += 2; + wids += 2; + } } free(spdata); - (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); + (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE); free(widths); } @@ -941,430 +890,406 @@ miFillWideEllipse( */ void -miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) +miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) { - int i; - xArc *parc; - int xMin, xMax, yMin, yMax; - int pixmapWidth = 0, pixmapHeight = 0; - int xOrg = 0, yOrg = 0; - int width; - Bool fTricky; - DrawablePtr pDrawTo; - CARD32 fg, bg; - GCPtr pGCTo; + int i; + xArc *parc; + int xMin, xMax, yMin, yMax; + int pixmapWidth = 0, pixmapHeight = 0; + int xOrg = 0, yOrg = 0; + int width; + Bool fTricky; + DrawablePtr pDrawTo; + CARD32 fg, bg; + GCPtr pGCTo; miPolyArcPtr polyArcs; - int cap[2], join[2]; - int iphase; - int halfWidth; + int cap[2], join[2]; + int iphase; + int halfWidth; width = pGC->lineWidth; - if(width == 0 && pGC->lineStyle == LineSolid) - { - for(i = narcs, parc = parcs; --i >= 0; parc++) - miArcSegment( pDraw, pGC, *parc, - (miArcFacePtr) 0, (miArcFacePtr) 0 ); - fillSpans (pDraw, pGC); - } - else - { - if ((pGC->lineStyle == LineSolid) && narcs) - { - while (parcs->width && parcs->height && - (parcs->angle2 >= FULLCIRCLE || - parcs->angle2 <= -FULLCIRCLE)) - { - miFillWideEllipse(pDraw, pGC, parcs); - if (!--narcs) - return; - parcs++; - } - } - - /* Set up pDrawTo and pGCTo based on the rasterop */ - switch(pGC->alu) - { - case GXclear: /* 0 */ - case GXcopy: /* src */ - case GXcopyInverted: /* NOT src */ - case GXset: /* 1 */ - fTricky = FALSE; - pDrawTo = pDraw; - pGCTo = pGC; - break; - default: - fTricky = TRUE; - - /* find bounding box around arcs */ - xMin = yMin = MAXSHORT; - xMax = yMax = MINSHORT; - - for(i = narcs, parc = parcs; --i >= 0; parc++) - { - xMin = min (xMin, parc->x); - yMin = min (yMin, parc->y); - xMax = max (xMax, (parc->x + (int) parc->width)); - yMax = max (yMax, (parc->y + (int) parc->height)); - } - - /* expand box to deal with line widths */ - halfWidth = (width + 1)/2; - xMin -= halfWidth; - yMin -= halfWidth; - xMax += halfWidth; - yMax += halfWidth; - - /* compute pixmap size; limit it to size of drawable */ - xOrg = max(xMin, 0); - yOrg = max(yMin, 0); - pixmapWidth = min(xMax, pDraw->width) - xOrg; - pixmapHeight = min(yMax, pDraw->height) - yOrg; - - /* if nothing left, return */ - if ( (pixmapWidth <= 0) || (pixmapHeight <= 0) ) return; - - for(i = narcs, parc = parcs; --i >= 0; parc++) - { - parc->x -= xOrg; - parc->y -= yOrg; - } - if (pGC->miTranslate) - { - xOrg += pDraw->x; - yOrg += pDraw->y; - } - - /* set up scratch GC */ - - pGCTo = GetScratchGC(1, pDraw->pScreen); - if (!pGCTo) - return; - { - ChangeGCVal gcvals[6]; - gcvals[0].val = GXcopy; - gcvals[1].val = 1; - gcvals[2].val = 0; - gcvals[3].val = pGC->lineWidth; - gcvals[4].val = pGC->capStyle; - gcvals[5].val = pGC->joinStyle; - ChangeGC(NullClient, pGCTo, GCFunction | - GCForeground | GCBackground | GCLineWidth | - GCCapStyle | GCJoinStyle, gcvals); - } - - /* allocate a 1 bit deep pixmap of the appropriate size, and - * validate it */ - pDrawTo = (DrawablePtr)(*pDraw->pScreen->CreatePixmap) - (pDraw->pScreen, pixmapWidth, pixmapHeight, 1, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pDrawTo) - { - FreeScratchGC(pGCTo); - return; - } - ValidateGC(pDrawTo, pGCTo); - miClearDrawable(pDrawTo, pGCTo); - } - - fg = pGC->fgPixel; - bg = pGC->bgPixel; - if ((pGC->fillStyle == FillTiled) || - (pGC->fillStyle == FillOpaqueStippled)) - bg = fg; /* the protocol sez these don't cause color changes */ - - polyArcs = miComputeArcs (parcs, narcs, pGC); - - if (!polyArcs) - { - if (fTricky) { - (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr)pDrawTo); - FreeScratchGC (pGCTo); - } - return; - } - - cap[0] = cap[1] = 0; - join[0] = join[1] = 0; - for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0); - iphase >= 0; - iphase--) - { - ChangeGCVal gcval; - if (iphase == 1) { - gcval.val = bg; - ChangeGC (NullClient, pGC, GCForeground, &gcval); - ValidateGC (pDraw, pGC); - } else if (pGC->lineStyle == LineDoubleDash) { - gcval.val = fg; - ChangeGC (NullClient, pGC, GCForeground, &gcval); - ValidateGC (pDraw, pGC); - } - for (i = 0; i < polyArcs[iphase].narcs; i++) { - miArcDataPtr arcData; - - arcData = &polyArcs[iphase].arcs[i]; - miArcSegment(pDrawTo, pGCTo, arcData->arc, - &arcData->bounds[RIGHT_END], - &arcData->bounds[LEFT_END]); - if (polyArcs[iphase].arcs[i].render) { - fillSpans (pDrawTo, pGCTo); - /* - * don't cap self-joining arcs - */ - if (polyArcs[iphase].arcs[i].selfJoin && - cap[iphase] < polyArcs[iphase].arcs[i].cap) - cap[iphase]++; - while (cap[iphase] < polyArcs[iphase].arcs[i].cap) { - int arcIndex, end; - miArcDataPtr arcData0; - - arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex; - end = polyArcs[iphase].caps[cap[iphase]].end; - arcData0 = &polyArcs[iphase].arcs[arcIndex]; - miArcCap (pDrawTo, pGCTo, - &arcData0->bounds[end], end, - arcData0->arc.x, arcData0->arc.y, - (double) arcData0->arc.width / 2.0, - (double) arcData0->arc.height / 2.0); - ++cap[iphase]; - } - while (join[iphase] < polyArcs[iphase].arcs[i].join) { - int arcIndex0, arcIndex1, end0, end1; - int phase0, phase1; - miArcDataPtr arcData0, arcData1; - miArcJoinPtr joinp; - - joinp = &polyArcs[iphase].joins[join[iphase]]; - arcIndex0 = joinp->arcIndex0; - end0 = joinp->end0; - arcIndex1 = joinp->arcIndex1; - end1 = joinp->end1; - phase0 = joinp->phase0; - phase1 = joinp->phase1; - arcData0 = &polyArcs[phase0].arcs[arcIndex0]; - arcData1 = &polyArcs[phase1].arcs[arcIndex1]; - miArcJoin (pDrawTo, pGCTo, - &arcData0->bounds[end0], - &arcData1->bounds[end1], - arcData0->arc.x, arcData0->arc.y, - (double) arcData0->arc.width / 2.0, - (double) arcData0->arc.height / 2.0, - arcData1->arc.x, arcData1->arc.y, - (double) arcData1->arc.width / 2.0, - (double) arcData1->arc.height / 2.0); - ++join[iphase]; - } - if (fTricky) { - if (pGC->serialNumber != pDraw->serialNumber) - ValidateGC (pDraw, pGC); - (*pGC->ops->PushPixels) (pGC, (PixmapPtr)pDrawTo, - pDraw, pixmapWidth, pixmapHeight, xOrg, yOrg); - miClearDrawable ((DrawablePtr) pDrawTo, pGCTo); - } - } - } - } - miFreeArcs(polyArcs, pGC); - - if(fTricky) - { - (*pGCTo->pScreen->DestroyPixmap)((PixmapPtr)pDrawTo); - FreeScratchGC(pGCTo); - } + if (width == 0 && pGC->lineStyle == LineSolid) { + for (i = narcs, parc = parcs; --i >= 0; parc++) + miArcSegment(pDraw, pGC, *parc, (miArcFacePtr) 0, (miArcFacePtr) 0); + fillSpans(pDraw, pGC); + } + else { + if ((pGC->lineStyle == LineSolid) && narcs) { + while (parcs->width && parcs->height && + (parcs->angle2 >= FULLCIRCLE || + parcs->angle2 <= -FULLCIRCLE)) { + miFillWideEllipse(pDraw, pGC, parcs); + if (!--narcs) + return; + parcs++; + } + } + + /* Set up pDrawTo and pGCTo based on the rasterop */ + switch (pGC->alu) { + case GXclear: /* 0 */ + case GXcopy: /* src */ + case GXcopyInverted: /* NOT src */ + case GXset: /* 1 */ + fTricky = FALSE; + pDrawTo = pDraw; + pGCTo = pGC; + break; + default: + fTricky = TRUE; + + /* find bounding box around arcs */ + xMin = yMin = MAXSHORT; + xMax = yMax = MINSHORT; + + for (i = narcs, parc = parcs; --i >= 0; parc++) { + xMin = min(xMin, parc->x); + yMin = min(yMin, parc->y); + xMax = max(xMax, (parc->x + (int) parc->width)); + yMax = max(yMax, (parc->y + (int) parc->height)); + } + + /* expand box to deal with line widths */ + halfWidth = (width + 1) / 2; + xMin -= halfWidth; + yMin -= halfWidth; + xMax += halfWidth; + yMax += halfWidth; + + /* compute pixmap size; limit it to size of drawable */ + xOrg = max(xMin, 0); + yOrg = max(yMin, 0); + pixmapWidth = min(xMax, pDraw->width) - xOrg; + pixmapHeight = min(yMax, pDraw->height) - yOrg; + + /* if nothing left, return */ + if ((pixmapWidth <= 0) || (pixmapHeight <= 0)) + return; + + for (i = narcs, parc = parcs; --i >= 0; parc++) { + parc->x -= xOrg; + parc->y -= yOrg; + } + if (pGC->miTranslate) { + xOrg += pDraw->x; + yOrg += pDraw->y; + } + + /* set up scratch GC */ + + pGCTo = GetScratchGC(1, pDraw->pScreen); + if (!pGCTo) + return; + { + ChangeGCVal gcvals[6]; + + gcvals[0].val = GXcopy; + gcvals[1].val = 1; + gcvals[2].val = 0; + gcvals[3].val = pGC->lineWidth; + gcvals[4].val = pGC->capStyle; + gcvals[5].val = pGC->joinStyle; + ChangeGC(NullClient, pGCTo, GCFunction | + GCForeground | GCBackground | GCLineWidth | + GCCapStyle | GCJoinStyle, gcvals); + } + + /* allocate a 1 bit deep pixmap of the appropriate size, and + * validate it */ + pDrawTo = (DrawablePtr) (*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, pixmapWidth, pixmapHeight, 1, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pDrawTo) { + FreeScratchGC(pGCTo); + return; + } + ValidateGC(pDrawTo, pGCTo); + miClearDrawable(pDrawTo, pGCTo); + } + + fg = pGC->fgPixel; + bg = pGC->bgPixel; + if ((pGC->fillStyle == FillTiled) || + (pGC->fillStyle == FillOpaqueStippled)) + bg = fg; /* the protocol sez these don't cause color changes */ + + polyArcs = miComputeArcs(parcs, narcs, pGC); + + if (!polyArcs) { + if (fTricky) { + (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo); + FreeScratchGC(pGCTo); + } + return; + } + + cap[0] = cap[1] = 0; + join[0] = join[1] = 0; + for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0); + iphase >= 0; iphase--) { + ChangeGCVal gcval; + + if (iphase == 1) { + gcval.val = bg; + ChangeGC(NullClient, pGC, GCForeground, &gcval); + ValidateGC(pDraw, pGC); + } + else if (pGC->lineStyle == LineDoubleDash) { + gcval.val = fg; + ChangeGC(NullClient, pGC, GCForeground, &gcval); + ValidateGC(pDraw, pGC); + } + for (i = 0; i < polyArcs[iphase].narcs; i++) { + miArcDataPtr arcData; + + arcData = &polyArcs[iphase].arcs[i]; + miArcSegment(pDrawTo, pGCTo, arcData->arc, + &arcData->bounds[RIGHT_END], + &arcData->bounds[LEFT_END]); + if (polyArcs[iphase].arcs[i].render) { + fillSpans(pDrawTo, pGCTo); + /* + * don't cap self-joining arcs + */ + if (polyArcs[iphase].arcs[i].selfJoin && + cap[iphase] < polyArcs[iphase].arcs[i].cap) + cap[iphase]++; + while (cap[iphase] < polyArcs[iphase].arcs[i].cap) { + int arcIndex, end; + miArcDataPtr arcData0; + + arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex; + end = polyArcs[iphase].caps[cap[iphase]].end; + arcData0 = &polyArcs[iphase].arcs[arcIndex]; + miArcCap(pDrawTo, pGCTo, + &arcData0->bounds[end], end, + arcData0->arc.x, arcData0->arc.y, + (double) arcData0->arc.width / 2.0, + (double) arcData0->arc.height / 2.0); + ++cap[iphase]; + } + while (join[iphase] < polyArcs[iphase].arcs[i].join) { + int arcIndex0, arcIndex1, end0, end1; + int phase0, phase1; + miArcDataPtr arcData0, arcData1; + miArcJoinPtr joinp; + + joinp = &polyArcs[iphase].joins[join[iphase]]; + arcIndex0 = joinp->arcIndex0; + end0 = joinp->end0; + arcIndex1 = joinp->arcIndex1; + end1 = joinp->end1; + phase0 = joinp->phase0; + phase1 = joinp->phase1; + arcData0 = &polyArcs[phase0].arcs[arcIndex0]; + arcData1 = &polyArcs[phase1].arcs[arcIndex1]; + miArcJoin(pDrawTo, pGCTo, + &arcData0->bounds[end0], + &arcData1->bounds[end1], + arcData0->arc.x, arcData0->arc.y, + (double) arcData0->arc.width / 2.0, + (double) arcData0->arc.height / 2.0, + arcData1->arc.x, arcData1->arc.y, + (double) arcData1->arc.width / 2.0, + (double) arcData1->arc.height / 2.0); + ++join[iphase]; + } + if (fTricky) { + if (pGC->serialNumber != pDraw->serialNumber) + ValidateGC(pDraw, pGC); + (*pGC->ops->PushPixels) (pGC, (PixmapPtr) pDrawTo, + pDraw, pixmapWidth, + pixmapHeight, xOrg, yOrg); + miClearDrawable((DrawablePtr) pDrawTo, pGCTo); + } + } + } + } + miFreeArcs(polyArcs, pGC); + + if (fTricky) { + (*pGCTo->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo); + FreeScratchGC(pGCTo); + } } } static double -angleBetween (SppPointRec center, SppPointRec point1, SppPointRec point2) +angleBetween(SppPointRec center, SppPointRec point1, SppPointRec point2) { - double a1, a2, a; - - /* - * reflect from X coordinates back to ellipse - * coordinates -- y increasing upwards - */ - a1 = miDatan2 (- (point1.y - center.y), point1.x - center.x); - a2 = miDatan2 (- (point2.y - center.y), point2.x - center.x); - a = a2 - a1; - if (a <= -180.0) - a += 360.0; - else if (a > 180.0) - a -= 360.0; - return a; + double a1, a2, a; + + /* + * reflect from X coordinates back to ellipse + * coordinates -- y increasing upwards + */ + a1 = miDatan2(-(point1.y - center.y), point1.x - center.x); + a2 = miDatan2(-(point2.y - center.y), point2.x - center.x); + a = a2 - a1; + if (a <= -180.0) + a += 360.0; + else if (a > 180.0) + a -= 360.0; + return a; } static void -translateBounds ( - miArcFacePtr b, - int x, - int y, - double fx, - double fy) +translateBounds(miArcFacePtr b, int x, int y, double fx, double fy) { - fx += x; - fy += y; - b->clock.x -= fx; - b->clock.y -= fy; - b->center.x -= fx; - b->center.y -= fy; - b->counterClock.x -= fx; - b->counterClock.y -= fy; + fx += x; + fy += y; + b->clock.x -= fx; + b->clock.y -= fy; + b->center.x -= fx; + b->center.y -= fy; + b->counterClock.x -= fx; + b->counterClock.y -= fy; } static void miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft, - miArcFacePtr pRight, int xOrgLeft, int yOrgLeft, - double xFtransLeft, double yFtransLeft, - int xOrgRight, int yOrgRight, - double xFtransRight, double yFtransRight) + miArcFacePtr pRight, int xOrgLeft, int yOrgLeft, + double xFtransLeft, double yFtransLeft, + int xOrgRight, int yOrgRight, + double xFtransRight, double yFtransRight) { - SppPointRec center, corner, otherCorner; - SppPointRec poly[5], e; - SppPointPtr pArcPts; - int cpt; - SppArcRec arc; - miArcFaceRec Right, Left; - int polyLen = 0; - int xOrg, yOrg; - double xFtrans, yFtrans; - double a; - double ae, ac2, ec2, bc2, de; - double width; - - xOrg = (xOrgRight + xOrgLeft) / 2; - yOrg = (yOrgRight + yOrgLeft) / 2; - xFtrans = (xFtransLeft + xFtransRight) / 2; - yFtrans = (yFtransLeft + yFtransRight) / 2; - Right = *pRight; - translateBounds (&Right, xOrg - xOrgRight, yOrg - yOrgRight, - xFtrans - xFtransRight, yFtrans - yFtransRight); - Left = *pLeft; - translateBounds (&Left, xOrg - xOrgLeft, yOrg - yOrgLeft, - xFtrans - xFtransLeft, yFtrans - yFtransLeft); - pRight = &Right; - pLeft = &Left; - - if (pRight->clock.x == pLeft->counterClock.x && - pRight->clock.y == pLeft->counterClock.y) - return; - center = pRight->center; - if (0 <= (a = angleBetween (center, pRight->clock, pLeft->counterClock)) - && a <= 180.0) - { - corner = pRight->clock; - otherCorner = pLeft->counterClock; - } else { - a = angleBetween (center, pLeft->clock, pRight->counterClock); - corner = pLeft->clock; - otherCorner = pRight->counterClock; - } - switch (pGC->joinStyle) { - case JoinRound: - width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1); - - arc.x = center.x - width/2; - arc.y = center.y - width/2; - arc.width = width; - arc.height = width; - arc.angle1 = -miDatan2 (corner.y - center.y, corner.x - center.x); - arc.angle2 = a; - pArcPts = malloc(3 * sizeof (SppPointRec)); - if (!pArcPts) - return; - pArcPts[0].x = otherCorner.x; - pArcPts[0].y = otherCorner.y; - pArcPts[1].x = center.x; - pArcPts[1].y = center.y; - pArcPts[2].x = corner.x; - pArcPts[2].y = corner.y; - if( (cpt = miGetArcPts(&arc, 3, &pArcPts)) ) - { - /* by drawing with miFillSppPoly and setting the endpoints of the arc - * to be the corners, we assure that the cap will meet up with the - * rest of the line */ - miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans); - } - free(pArcPts); - return; - case JoinMiter: - /* - * don't miter arcs with less than 11 degrees between them - */ - if (a < 169.0) { - poly[0] = corner; - poly[1] = center; - poly[2] = otherCorner; - bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) + - (corner.y - otherCorner.y) * (corner.y - otherCorner.y); - ec2 = bc2 / 4; - ac2 = (corner.x - center.x) * (corner.x - center.x) + - (corner.y - center.y) * (corner.y - center.y); - ae = sqrt (ac2 - ec2); - de = ec2 / ae; - e.x = (corner.x + otherCorner.x) / 2; - e.y = (corner.y + otherCorner.y) / 2; - poly[3].x = e.x + de * (e.x - center.x) / ae; - poly[3].y = e.y + de * (e.y - center.y) / ae; - poly[4] = corner; - polyLen = 5; - break; - } - case JoinBevel: - poly[0] = corner; - poly[1] = center; - poly[2] = otherCorner; - poly[3] = corner; - polyLen = 4; - break; - } - miFillSppPoly (pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans); + SppPointRec center, corner, otherCorner; + SppPointRec poly[5], e; + SppPointPtr pArcPts; + int cpt; + SppArcRec arc; + miArcFaceRec Right, Left; + int polyLen = 0; + int xOrg, yOrg; + double xFtrans, yFtrans; + double a; + double ae, ac2, ec2, bc2, de; + double width; + + xOrg = (xOrgRight + xOrgLeft) / 2; + yOrg = (yOrgRight + yOrgLeft) / 2; + xFtrans = (xFtransLeft + xFtransRight) / 2; + yFtrans = (yFtransLeft + yFtransRight) / 2; + Right = *pRight; + translateBounds(&Right, xOrg - xOrgRight, yOrg - yOrgRight, + xFtrans - xFtransRight, yFtrans - yFtransRight); + Left = *pLeft; + translateBounds(&Left, xOrg - xOrgLeft, yOrg - yOrgLeft, + xFtrans - xFtransLeft, yFtrans - yFtransLeft); + pRight = &Right; + pLeft = &Left; + + if (pRight->clock.x == pLeft->counterClock.x && + pRight->clock.y == pLeft->counterClock.y) + return; + center = pRight->center; + if (0 <= (a = angleBetween(center, pRight->clock, pLeft->counterClock)) + && a <= 180.0) { + corner = pRight->clock; + otherCorner = pLeft->counterClock; + } + else { + a = angleBetween(center, pLeft->clock, pRight->counterClock); + corner = pLeft->clock; + otherCorner = pRight->counterClock; + } + switch (pGC->joinStyle) { + case JoinRound: + width = (pGC->lineWidth ? (double) pGC->lineWidth : (double) 1); + + arc.x = center.x - width / 2; + arc.y = center.y - width / 2; + arc.width = width; + arc.height = width; + arc.angle1 = -miDatan2(corner.y - center.y, corner.x - center.x); + arc.angle2 = a; + pArcPts = malloc(3 * sizeof(SppPointRec)); + if (!pArcPts) + return; + pArcPts[0].x = otherCorner.x; + pArcPts[0].y = otherCorner.y; + pArcPts[1].x = center.x; + pArcPts[1].y = center.y; + pArcPts[2].x = corner.x; + pArcPts[2].y = corner.y; + if ((cpt = miGetArcPts(&arc, 3, &pArcPts))) { + /* by drawing with miFillSppPoly and setting the endpoints of the arc + * to be the corners, we assure that the cap will meet up with the + * rest of the line */ + miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, + yFtrans); + } + free(pArcPts); + return; + case JoinMiter: + /* + * don't miter arcs with less than 11 degrees between them + */ + if (a < 169.0) { + poly[0] = corner; + poly[1] = center; + poly[2] = otherCorner; + bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) + + (corner.y - otherCorner.y) * (corner.y - otherCorner.y); + ec2 = bc2 / 4; + ac2 = (corner.x - center.x) * (corner.x - center.x) + + (corner.y - center.y) * (corner.y - center.y); + ae = sqrt(ac2 - ec2); + de = ec2 / ae; + e.x = (corner.x + otherCorner.x) / 2; + e.y = (corner.y + otherCorner.y) / 2; + poly[3].x = e.x + de * (e.x - center.x) / ae; + poly[3].y = e.y + de * (e.y - center.y) / ae; + poly[4] = corner; + polyLen = 5; + break; + } + case JoinBevel: + poly[0] = corner; + poly[1] = center; + poly[2] = otherCorner; + poly[3] = corner; + polyLen = 4; + break; + } + miFillSppPoly(pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans); } -/*ARGSUSED*/ -static void -miArcCap ( - DrawablePtr pDraw, - GCPtr pGC, - miArcFacePtr pFace, - int end, - int xOrg, - int yOrg, - double xFtrans, - double yFtrans) + /*ARGSUSED*/ static void +miArcCap(DrawablePtr pDraw, + GCPtr pGC, + miArcFacePtr pFace, + int end, int xOrg, int yOrg, double xFtrans, double yFtrans) { - SppPointRec corner, otherCorner, center, endPoint, poly[5]; - - corner = pFace->clock; - otherCorner = pFace->counterClock; - center = pFace->center; - switch (pGC->capStyle) { - case CapProjecting: - poly[0].x = otherCorner.x; - poly[0].y = otherCorner.y; - poly[1].x = corner.x; - poly[1].y = corner.y; - poly[2].x = corner.x - - (center.y - corner.y); - poly[2].y = corner.y + - (center.x - corner.x); - poly[3].x = otherCorner.x - - (otherCorner.y - center.y); - poly[3].y = otherCorner.y + - (otherCorner.x - center.x); - poly[4].x = otherCorner.x; - poly[4].y = otherCorner.y; - miFillSppPoly (pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans); - break; - case CapRound: - /* - * miRoundCap just needs these to be unequal. - */ - endPoint = center; - endPoint.x = endPoint.x + 100; - miRoundCap (pDraw, pGC, center, endPoint, corner, otherCorner, 0, - -xOrg, -yOrg, xFtrans, yFtrans); - break; - } + SppPointRec corner, otherCorner, center, endPoint, poly[5]; + + corner = pFace->clock; + otherCorner = pFace->counterClock; + center = pFace->center; + switch (pGC->capStyle) { + case CapProjecting: + poly[0].x = otherCorner.x; + poly[0].y = otherCorner.y; + poly[1].x = corner.x; + poly[1].y = corner.y; + poly[2].x = corner.x - (center.y - corner.y); + poly[2].y = corner.y + (center.x - corner.x); + poly[3].x = otherCorner.x - (otherCorner.y - center.y); + poly[3].y = otherCorner.y + (otherCorner.x - center.x); + poly[4].x = otherCorner.x; + poly[4].y = otherCorner.y; + miFillSppPoly(pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans); + break; + case CapRound: + /* + * miRoundCap just needs these to be unequal. + */ + endPoint = center; + endPoint.x = endPoint.x + 100; + miRoundCap(pDraw, pGC, center, endPoint, corner, otherCorner, 0, + -xOrg, -yOrg, xFtrans, yFtrans); + break; + } } /* MIROUNDCAP -- a private helper function @@ -1373,47 +1298,42 @@ miArcCap ( * two corners at this end of the line. * NOTE: pOtherCorner must be counter-clockwise from pCorner. */ -/*ARGSUSED*/ -static void -miRoundCap( - DrawablePtr pDraw, - GCPtr pGC, - SppPointRec pCenter, - SppPointRec pEnd, - SppPointRec pCorner, - SppPointRec pOtherCorner, - int fLineEnd, - int xOrg, - int yOrg, - double xFtrans, - double yFtrans) + /*ARGSUSED*/ static void +miRoundCap(DrawablePtr pDraw, + GCPtr pGC, + SppPointRec pCenter, + SppPointRec pEnd, + SppPointRec pCorner, + SppPointRec pOtherCorner, + int fLineEnd, int xOrg, int yOrg, double xFtrans, double yFtrans) { - int cpt; - double width; - SppArcRec arc; - SppPointPtr pArcPts; + int cpt; + double width; + SppArcRec arc; + SppPointPtr pArcPts; - width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1); + width = (pGC->lineWidth ? (double) pGC->lineWidth : (double) 1); - arc.x = pCenter.x - width/2; - arc.y = pCenter.y - width/2; + arc.x = pCenter.x - width / 2; + arc.y = pCenter.y - width / 2; arc.width = width; arc.height = width; - arc.angle1 = -miDatan2 (pCorner.y - pCenter.y, pCorner.x - pCenter.x); - if(PTISEQUAL(pCenter, pEnd)) - arc.angle2 = - 180.0; + arc.angle1 = -miDatan2(pCorner.y - pCenter.y, pCorner.x - pCenter.x); + if (PTISEQUAL(pCenter, pEnd)) + arc.angle2 = -180.0; else { - arc.angle2 = -miDatan2 (pOtherCorner.y - pCenter.y, pOtherCorner.x - pCenter.x) - arc.angle1; - if (arc.angle2 < 0) - arc.angle2 += 360.0; + arc.angle2 = + -miDatan2(pOtherCorner.y - pCenter.y, + pOtherCorner.x - pCenter.x) - arc.angle1; + if (arc.angle2 < 0) + arc.angle2 += 360.0; } pArcPts = (SppPointPtr) NULL; - if( (cpt = miGetArcPts(&arc, 0, &pArcPts)) ) - { - /* by drawing with miFillSppPoly and setting the endpoints of the arc - * to be the corners, we assure that the cap will meet up with the - * rest of the line */ - miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans); + if ((cpt = miGetArcPts(&arc, 0, &pArcPts))) { + /* by drawing with miFillSppPoly and setting the endpoints of the arc + * to be the corners, we assure that the cap will meet up with the + * rest of the line */ + miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans); } free(pArcPts); } @@ -1430,79 +1350,91 @@ miRoundCap( #define M_PI_2 1.57079632679489661923 #endif -# define Dsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0))) -# define Dcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0))) -# define mod(a,b) ((a) >= 0 ? (a) % (b) : (b) - (-(a)) % (b)) +#define Dsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0))) +#define Dcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0))) +#define mod(a,b) ((a) >= 0 ? (a) % (b) : (b) - (-(a)) % (b)) static double -miDcos (double a) +miDcos(double a) { - int i; - - if (floor (a/90) == a/90) { - i = (int) (a/90.0); - switch (mod (i, 4)) { - case 0: return 1; - case 1: return 0; - case 2: return -1; - case 3: return 0; - } - } - return cos (a * M_PI / 180.0); + int i; + + if (floor(a / 90) == a / 90) { + i = (int) (a / 90.0); + switch (mod(i, 4)) { + case 0: + return 1; + case 1: + return 0; + case 2: + return -1; + case 3: + return 0; + } + } + return cos(a * M_PI / 180.0); } static double -miDsin (double a) +miDsin(double a) { - int i; - - if (floor (a/90) == a/90) { - i = (int) (a/90.0); - switch (mod (i, 4)) { - case 0: return 0; - case 1: return 1; - case 2: return 0; - case 3: return -1; - } - } - return sin (a * M_PI / 180.0); + int i; + + if (floor(a / 90) == a / 90) { + i = (int) (a / 90.0); + switch (mod(i, 4)) { + case 0: + return 0; + case 1: + return 1; + case 2: + return 0; + case 3: + return -1; + } + } + return sin(a * M_PI / 180.0); } static double -miDasin (double v) +miDasin(double v) { if (v == 0) - return 0.0; + return 0.0; if (v == 1.0) - return 90.0; + return 90.0; if (v == -1.0) - return -90.0; + return -90.0; return asin(v) * (180.0 / M_PI); } static double -miDatan2 (double dy, double dx) +miDatan2(double dy, double dx) { if (dy == 0) { - if (dx >= 0) - return 0.0; - return 180.0; - } else if (dx == 0) { - if (dy > 0) - return 90.0; - return -90.0; - } else if (fabs (dy) == fabs (dx)) { - if (dy > 0) { - if (dx > 0) - return 45.0; - return 135.0; - } else { - if (dx > 0) - return 315.0; - return 225.0; - } - } else { - return atan2 (dy, dx) * (180.0 / M_PI); + if (dx >= 0) + return 0.0; + return 180.0; + } + else if (dx == 0) { + if (dy > 0) + return 90.0; + return -90.0; + } + else if (fabs(dy) == fabs(dx)) { + if (dy > 0) { + if (dx > 0) + return 45.0; + return 135.0; + } + else { + if (dx > 0) + return 315.0; + return 225.0; + } + } + else { + return atan2(dy, dx) * (180.0 / M_PI); } } @@ -1519,30 +1451,28 @@ miDatan2 (double dy, double dx) * count on realloc() to handle the null pointer correctly. */ static int -miGetArcPts( - SppArcPtr parc, /* points to an arc */ - int cpt, /* number of points already in arc list */ - SppPointPtr *ppPts) /* pointer to pointer to arc-list -- modified */ -{ - double st, /* Start Theta, start angle */ - et, /* End Theta, offset from start theta */ - dt, /* Delta Theta, angle to sweep ellipse */ - cdt, /* Cos Delta Theta, actually 2 cos(dt) */ - x0, y0, /* the recurrence formula needs two points to start */ - x1, y1, - x2, y2, /* this will be the new point generated */ - xc, yc; /* the center point */ - int count, i; - SppPointPtr poly; +miGetArcPts(SppArcPtr parc, /* points to an arc */ + int cpt, /* number of points already in arc list */ + SppPointPtr * ppPts) +{ /* pointer to pointer to arc-list -- modified */ + double st, /* Start Theta, start angle */ + et, /* End Theta, offset from start theta */ + dt, /* Delta Theta, angle to sweep ellipse */ + cdt, /* Cos Delta Theta, actually 2 cos(dt) */ + x0, y0, /* the recurrence formula needs two points to start */ + x1, y1, x2, y2, /* this will be the new point generated */ + xc, yc; /* the center point */ + int count, i; + SppPointPtr poly; /* The spec says that positive angles indicate counterclockwise motion. * Given our coordinate system (with 0,0 in the upper left corner), * the screen appears flipped in Y. The easiest fix is to negate the * angles given */ - - st = - parc->angle1; - et = - parc->angle2; + st = -parc->angle1; + + et = -parc->angle2; /* Try to get a delta theta that is within 1/2 pixel. Then adjust it * so that it divides evenly into the total. @@ -1550,175 +1480,151 @@ miGetArcPts( */ cdt = parc->width; if (parc->height > cdt) - cdt = parc->height; + cdt = parc->height; cdt /= 2.0; - if(cdt <= 0) - return 0; + if (cdt <= 0) + return 0; if (cdt < 1.0) - cdt = 1.0; - dt = miDasin ( 1.0 / cdt ); /* minimum step necessary */ - count = et/dt; + cdt = 1.0; + dt = miDasin(1.0 / cdt); /* minimum step necessary */ + count = et / dt; count = abs(count) + 1; - dt = et/count; + dt = et / count; count++; cdt = 2 * miDcos(dt); - if (!(poly = (SppPointPtr) realloc((pointer)*ppPts, - (cpt + count) * sizeof(SppPointRec)))) - return 0; + if (!(poly = (SppPointPtr) realloc((pointer) *ppPts, + (cpt + count) * sizeof(SppPointRec)))) + return 0; *ppPts = poly; - xc = parc->width/2.0; /* store half width and half height */ - yc = parc->height/2.0; - + xc = parc->width / 2.0; /* store half width and half height */ + yc = parc->height / 2.0; + x0 = xc * miDcos(st); y0 = yc * miDsin(st); x1 = xc * miDcos(st + dt); y1 = yc * miDsin(st + dt); - xc += parc->x; /* by adding initial point, these become */ - yc += parc->y; /* the center point */ + xc += parc->x; /* by adding initial point, these become */ + yc += parc->y; /* the center point */ poly[cpt].x = (xc + x0); poly[cpt].y = (yc + y0); poly[cpt + 1].x = (xc + x1); poly[cpt + 1].y = (yc + y1); - for(i = 2; i < count; i++) - { - x2 = cdt * x1 - x0; - y2 = cdt * y1 - y0; + for (i = 2; i < count; i++) { + x2 = cdt * x1 - x0; + y2 = cdt * y1 - y0; - poly[cpt + i].x = (xc + x2); - poly[cpt + i].y = (yc + y2); + poly[cpt + i].x = (xc + x2); + poly[cpt + i].y = (yc + y2); - x0 = x1; y0 = y1; - x1 = x2; y1 = y2; + x0 = x1; + y0 = y1; + x1 = x2; + y1 = y2; } /* adjust the last point */ if (abs(parc->angle2) >= 360.0) - poly[cpt +i -1] = poly[0]; + poly[cpt + i - 1] = poly[0]; else { - poly[cpt +i -1].x = (miDcos(st + et) * parc->width/2.0 + xc); - poly[cpt +i -1].y = (miDsin(st + et) * parc->height/2.0 + yc); + poly[cpt + i - 1].x = (miDcos(st + et) * parc->width / 2.0 + xc); + poly[cpt + i - 1].y = (miDsin(st + et) * parc->height / 2.0 + yc); } return count; } struct arcData { - double x0, y0, x1, y1; - int selfJoin; + double x0, y0, x1, y1; + int selfJoin; }; -# define ADD_REALLOC_STEP 20 +#define ADD_REALLOC_STEP 20 static void -addCap ( - miArcCapPtr *capsp, - int *ncapsp, - int *sizep, - int end, - int arcIndex) +addCap(miArcCapPtr * capsp, int *ncapsp, int *sizep, int end, int arcIndex) { - int newsize; - miArcCapPtr cap; - - if (*ncapsp == *sizep) - { - newsize = *sizep + ADD_REALLOC_STEP; - cap = (miArcCapPtr) realloc(*capsp, - newsize * sizeof (**capsp)); - if (!cap) - return; - *sizep = newsize; - *capsp = cap; - } - cap = &(*capsp)[*ncapsp]; - cap->end = end; - cap->arcIndex = arcIndex; - ++*ncapsp; + int newsize; + miArcCapPtr cap; + + if (*ncapsp == *sizep) { + newsize = *sizep + ADD_REALLOC_STEP; + cap = (miArcCapPtr) realloc(*capsp, newsize * sizeof(**capsp)); + if (!cap) + return; + *sizep = newsize; + *capsp = cap; + } + cap = &(*capsp)[*ncapsp]; + cap->end = end; + cap->arcIndex = arcIndex; + ++*ncapsp; } static void -addJoin ( - miArcJoinPtr *joinsp, - int *njoinsp, - int *sizep, - int end0, - int index0, - int phase0, - int end1, - int index1, - int phase1) +addJoin(miArcJoinPtr * joinsp, + int *njoinsp, + int *sizep, + int end0, int index0, int phase0, int end1, int index1, int phase1) { - int newsize; - miArcJoinPtr join; - - if (*njoinsp == *sizep) - { - newsize = *sizep + ADD_REALLOC_STEP; - join = (miArcJoinPtr) realloc(*joinsp, - newsize * sizeof (**joinsp)); - if (!join) - return; - *sizep = newsize; - *joinsp = join; - } - join = &(*joinsp)[*njoinsp]; - join->end0 = end0; - join->arcIndex0 = index0; - join->phase0 = phase0; - join->end1 = end1; - join->arcIndex1 = index1; - join->phase1 = phase1; - ++*njoinsp; + int newsize; + miArcJoinPtr join; + + if (*njoinsp == *sizep) { + newsize = *sizep + ADD_REALLOC_STEP; + join = (miArcJoinPtr) realloc(*joinsp, newsize * sizeof(**joinsp)); + if (!join) + return; + *sizep = newsize; + *joinsp = join; + } + join = &(*joinsp)[*njoinsp]; + join->end0 = end0; + join->arcIndex0 = index0; + join->phase0 = phase0; + join->end1 = end1; + join->arcIndex1 = index1; + join->phase1 = phase1; + ++*njoinsp; } static miArcDataPtr -addArc ( - miArcDataPtr *arcsp, - int *narcsp, - int *sizep, - xArc *xarc) +addArc(miArcDataPtr * arcsp, int *narcsp, int *sizep, xArc * xarc) { - int newsize; - miArcDataPtr arc; - - if (*narcsp == *sizep) - { - newsize = *sizep + ADD_REALLOC_STEP; - arc = (miArcDataPtr) realloc(*arcsp, - newsize * sizeof (**arcsp)); - if (!arc) - return NULL; - *sizep = newsize; - *arcsp = arc; - } - arc = &(*arcsp)[*narcsp]; - arc->arc = *xarc; - ++*narcsp; - return arc; + int newsize; + miArcDataPtr arc; + + if (*narcsp == *sizep) { + newsize = *sizep + ADD_REALLOC_STEP; + arc = (miArcDataPtr) realloc(*arcsp, newsize * sizeof(**arcsp)); + if (!arc) + return NULL; + *sizep = newsize; + *arcsp = arc; + } + arc = &(*arcsp)[*narcsp]; + arc->arc = *xarc; + ++*narcsp; + return arc; } static void -miFreeArcs( - miPolyArcPtr arcs, - GCPtr pGC) +miFreeArcs(miPolyArcPtr arcs, GCPtr pGC) { - int iphase; - - for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0); - iphase >= 0; - iphase--) - { - if (arcs[iphase].narcs > 0) - free(arcs[iphase].arcs); - if (arcs[iphase].njoins > 0) - free(arcs[iphase].joins); - if (arcs[iphase].ncaps > 0) - free(arcs[iphase].caps); - } - free(arcs); + int iphase; + + for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0); + iphase >= 0; iphase--) { + if (arcs[iphase].narcs > 0) + free(arcs[iphase].arcs); + if (arcs[iphase].njoins > 0) + free(arcs[iphase].joins); + if (arcs[iphase].ncaps > 0) + free(arcs[iphase].caps); + } + free(arcs); } /* @@ -1729,486 +1635,484 @@ miFreeArcs( * a polygonal approximation to the arc for computing arc lengths */ -# define DASH_MAP_SIZE 91 +#define DASH_MAP_SIZE 91 -# define dashIndexToAngle(di) ((((double) (di)) * 90.0) / ((double) DASH_MAP_SIZE - 1)) -# define xAngleToDashIndex(xa) ((((long) (xa)) * (DASH_MAP_SIZE - 1)) / (90 * 64)) -# define dashIndexToXAngle(di) ((((long) (di)) * (90 * 64)) / (DASH_MAP_SIZE - 1)) -# define dashXAngleStep (((double) (90 * 64)) / ((double) (DASH_MAP_SIZE - 1))) +#define dashIndexToAngle(di) ((((double) (di)) * 90.0) / ((double) DASH_MAP_SIZE - 1)) +#define xAngleToDashIndex(xa) ((((long) (xa)) * (DASH_MAP_SIZE - 1)) / (90 * 64)) +#define dashIndexToXAngle(di) ((((long) (di)) * (90 * 64)) / (DASH_MAP_SIZE - 1)) +#define dashXAngleStep (((double) (90 * 64)) / ((double) (DASH_MAP_SIZE - 1))) typedef struct { - double map[DASH_MAP_SIZE]; + double map[DASH_MAP_SIZE]; } dashMap; -static int computeAngleFromPath(int startAngle, int endAngle, dashMap *map, - int *lenp, int backwards); +static int computeAngleFromPath(int startAngle, int endAngle, dashMap * map, + int *lenp, int backwards); static void -computeDashMap ( - xArc *arcp, - dashMap *map) +computeDashMap(xArc * arcp, dashMap * map) { - int di; - double a, x, y, prevx = 0.0, prevy = 0.0, dist; - - for (di = 0; di < DASH_MAP_SIZE; di++) { - a = dashIndexToAngle (di); - x = ((double) arcp->width / 2.0) * miDcos (a); - y = ((double) arcp->height / 2.0) * miDsin (a); - if (di == 0) { - map->map[di] = 0.0; - } else { - dist = hypot (x - prevx, y - prevy); - map->map[di] = map->map[di - 1] + dist; - } - prevx = x; - prevy = y; - } + int di; + double a, x, y, prevx = 0.0, prevy = 0.0, dist; + + for (di = 0; di < DASH_MAP_SIZE; di++) { + a = dashIndexToAngle(di); + x = ((double) arcp->width / 2.0) * miDcos(a); + y = ((double) arcp->height / 2.0) * miDsin(a); + if (di == 0) { + map->map[di] = 0.0; + } + else { + dist = hypot(x - prevx, y - prevy); + map->map[di] = map->map[di - 1] + dist; + } + prevx = x; + prevy = y; + } } -typedef enum {HORIZONTAL, VERTICAL, OTHER} arcTypes; +typedef enum { HORIZONTAL, VERTICAL, OTHER } arcTypes; /* this routine is a bit gory */ static miPolyArcPtr -miComputeArcs ( - xArc *parcs, - int narcs, - GCPtr pGC) +miComputeArcs(xArc * parcs, int narcs, GCPtr pGC) { - int isDashed, isDoubleDash; - int dashOffset; - miPolyArcPtr arcs; - int start, i, j, k = 0, nexti, nextk = 0; - int joinSize[2]; - int capSize[2]; - int arcSize[2]; - int angle2; - double a0, a1; - struct arcData *data; - miArcDataPtr arc; - xArc xarc; - int iphase, prevphase = 0, joinphase; - int arcsJoin; - int selfJoin; - - int iDash = 0, dashRemaining = 0; - int iDashStart = 0, dashRemainingStart = 0, iphaseStart; - int startAngle, spanAngle, endAngle, backwards = 0; - int prevDashAngle, dashAngle; - dashMap map; - - isDashed = !(pGC->lineStyle == LineSolid); - isDoubleDash = (pGC->lineStyle == LineDoubleDash); - dashOffset = pGC->dashOffset; - - data = malloc(narcs * sizeof (struct arcData)); - if (!data) - return NULL; - arcs = malloc(sizeof (*arcs) * (isDoubleDash ? 2 : 1)); - if (!arcs) - { - free(data); - return NULL; - } - for (i = 0; i < narcs; i++) { - a0 = todeg (parcs[i].angle1); - angle2 = parcs[i].angle2; - if (angle2 > FULLCIRCLE) - angle2 = FULLCIRCLE; - else if (angle2 < -FULLCIRCLE) - angle2 = -FULLCIRCLE; - data[i].selfJoin = angle2 == FULLCIRCLE || angle2 == -FULLCIRCLE; - a1 = todeg (parcs[i].angle1 + angle2); - data[i].x0 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a0)); - data[i].y0 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a0)); - data[i].x1 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a1)); - data[i].y1 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a1)); - } - - for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) { - arcs[iphase].njoins = 0; - arcs[iphase].joins = 0; - joinSize[iphase] = 0; - - arcs[iphase].ncaps = 0; - arcs[iphase].caps = 0; - capSize[iphase] = 0; - - arcs[iphase].narcs = 0; - arcs[iphase].arcs = 0; - arcSize[iphase] = 0; - } - - iphase = 0; - if (isDashed) { - iDash = 0; - dashRemaining = pGC->dash[0]; - while (dashOffset > 0) { - if (dashOffset >= dashRemaining) { - dashOffset -= dashRemaining; - iphase = iphase ? 0 : 1; - iDash++; - if (iDash == pGC->numInDashList) - iDash = 0; - dashRemaining = pGC->dash[iDash]; - } else { - dashRemaining -= dashOffset; - dashOffset = 0; - } - } - iDashStart = iDash; - dashRemainingStart = dashRemaining; - } - iphaseStart = iphase; - - for (i = narcs - 1; i >= 0; i--) { - j = i + 1; - if (j == narcs) - j = 0; - if (data[i].selfJoin || i == j || - (UNEQUAL (data[i].x1, data[j].x0) || - UNEQUAL (data[i].y1, data[j].y0))) - { - if (iphase == 0 || isDoubleDash) - addCap (&arcs[iphase].caps, &arcs[iphase].ncaps, - &capSize[iphase], RIGHT_END, 0); - break; - } - } - start = i + 1; - if (start == narcs) - start = 0; - i = start; - for (;;) { - j = i + 1; - if (j == narcs) - j = 0; - nexti = i+1; - if (nexti == narcs) - nexti = 0; - if (isDashed) { - /* - ** deal with dashed arcs. Use special rules for certain 0 area arcs. - ** Presumably, the other 0 area arcs still aren't done right. - */ - arcTypes arcType = OTHER; - CARD16 thisLength; - - if (parcs[i].height == 0 - && (parcs[i].angle1 % FULLCIRCLE) == 0x2d00 - && parcs[i].angle2 == 0x2d00) - arcType = HORIZONTAL; - else if (parcs[i].width == 0 - && (parcs[i].angle1 % FULLCIRCLE) == 0x1680 - && parcs[i].angle2 == 0x2d00) - arcType = VERTICAL; - if (arcType == OTHER) { - /* - * precompute an approximation map - */ - computeDashMap (&parcs[i], &map); - /* - * compute each individual dash segment using the path - * length function - */ - startAngle = parcs[i].angle1; - spanAngle = parcs[i].angle2; - if (spanAngle > FULLCIRCLE) - spanAngle = FULLCIRCLE; - else if (spanAngle < -FULLCIRCLE) - spanAngle = -FULLCIRCLE; - if (startAngle < 0) - startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; - if (startAngle >= FULLCIRCLE) - startAngle = startAngle % FULLCIRCLE; - endAngle = startAngle + spanAngle; - backwards = spanAngle < 0; - } else { - xarc = parcs[i]; - if (arcType == VERTICAL) { - xarc.angle1 = 0x1680; - startAngle = parcs[i].y; - endAngle = startAngle + parcs[i].height; - } else { - xarc.angle1 = 0x2d00; - startAngle = parcs[i].x; - endAngle = startAngle + parcs[i].width; - } - } - dashAngle = startAngle; - selfJoin = data[i].selfJoin && - (iphase == 0 || isDoubleDash); - /* - * add dashed arcs to each bucket - */ - arc = 0; - while (dashAngle != endAngle) { - prevDashAngle = dashAngle; - if (arcType == OTHER) { - dashAngle = computeAngleFromPath (prevDashAngle, endAngle, - &map, &dashRemaining, backwards); - /* avoid troubles with huge arcs and small dashes */ - if (dashAngle == prevDashAngle) { - if (backwards) - dashAngle--; - else - dashAngle++; - } - } else { - thisLength = (dashAngle + dashRemaining <= endAngle) ? - dashRemaining : endAngle - dashAngle; - if (arcType == VERTICAL) { - xarc.y = dashAngle; - xarc.height = thisLength; - } else { - xarc.x = dashAngle; - xarc.width = thisLength; - } - dashAngle += thisLength; - dashRemaining -= thisLength; - } - if (iphase == 0 || isDoubleDash) { - if (arcType == OTHER) { - xarc = parcs[i]; - spanAngle = prevDashAngle; - if (spanAngle < 0) - spanAngle = FULLCIRCLE - (-spanAngle) % FULLCIRCLE; - if (spanAngle >= FULLCIRCLE) - spanAngle = spanAngle % FULLCIRCLE; - xarc.angle1 = spanAngle; - spanAngle = dashAngle - prevDashAngle; - if (backwards) { - if (dashAngle > prevDashAngle) - spanAngle = - FULLCIRCLE + spanAngle; - } else { - if (dashAngle < prevDashAngle) - spanAngle = FULLCIRCLE + spanAngle; - } - if (spanAngle > FULLCIRCLE) - spanAngle = FULLCIRCLE; - if (spanAngle < -FULLCIRCLE) - spanAngle = -FULLCIRCLE; - xarc.angle2 = spanAngle; - } - arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs, - &arcSize[iphase], &xarc); - if (!arc) - goto arcfail; - /* - * cap each end of an on/off dash - */ - if (!isDoubleDash) { - if (prevDashAngle != startAngle) { - addCap (&arcs[iphase].caps, - &arcs[iphase].ncaps, - &capSize[iphase], RIGHT_END, - arc - arcs[iphase].arcs); - - } - if (dashAngle != endAngle) { - addCap (&arcs[iphase].caps, - &arcs[iphase].ncaps, - &capSize[iphase], LEFT_END, - arc - arcs[iphase].arcs); - } - } - arc->cap = arcs[iphase].ncaps; - arc->join = arcs[iphase].njoins; - arc->render = 0; - arc->selfJoin = 0; - if (dashAngle == endAngle) - arc->selfJoin = selfJoin; - } - prevphase = iphase; - if (dashRemaining <= 0) { - ++iDash; - if (iDash == pGC->numInDashList) - iDash = 0; - iphase = iphase ? 0:1; - dashRemaining = pGC->dash[iDash]; - } - } - /* - * make sure a place exists for the position data when - * drawing a zero-length arc - */ - if (startAngle == endAngle) { - prevphase = iphase; - if (!isDoubleDash && iphase == 1) - prevphase = 0; - arc = addArc (&arcs[prevphase].arcs, &arcs[prevphase].narcs, - &arcSize[prevphase], &parcs[i]); - if (!arc) - goto arcfail; - arc->join = arcs[prevphase].njoins; - arc->cap = arcs[prevphase].ncaps; - arc->selfJoin = data[i].selfJoin; - } - } else { - arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs, - &arcSize[iphase], &parcs[i]); - if (!arc) - goto arcfail; - arc->join = arcs[iphase].njoins; - arc->cap = arcs[iphase].ncaps; - arc->selfJoin = data[i].selfJoin; - prevphase = iphase; - } - if (prevphase == 0 || isDoubleDash) - k = arcs[prevphase].narcs - 1; - if (iphase == 0 || isDoubleDash) - nextk = arcs[iphase].narcs; - if (nexti == start) { - nextk = 0; - if (isDashed) { - iDash = iDashStart; - iphase = iphaseStart; - dashRemaining = dashRemainingStart; - } - } - arcsJoin = narcs > 1 && i != j && - ISEQUAL (data[i].x1, data[j].x0) && - ISEQUAL (data[i].y1, data[j].y0) && - !data[i].selfJoin && !data[j].selfJoin; - if (arc) - { - if (arcsJoin) - arc->render = 0; - else - arc->render = 1; - } - if (arcsJoin && - (prevphase == 0 || isDoubleDash) && - (iphase == 0 || isDoubleDash)) - { - joinphase = iphase; - if (isDoubleDash) { - if (nexti == start) - joinphase = iphaseStart; - /* - * if the join is right at the dash, - * draw the join in foreground - * This is because the foreground - * arcs are computed second, the results - * of which are needed to draw the join - */ - if (joinphase != prevphase) - joinphase = 0; - } - if (joinphase == 0 || isDoubleDash) { - addJoin (&arcs[joinphase].joins, - &arcs[joinphase].njoins, - &joinSize[joinphase], - LEFT_END, k, prevphase, - RIGHT_END, nextk, iphase); - arc->join = arcs[prevphase].njoins; - } - } else { - /* - * cap the left end of this arc - * unless it joins itself - */ - if ((prevphase == 0 || isDoubleDash) && - !arc->selfJoin) - { - addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps, - &capSize[prevphase], LEFT_END, k); - arc->cap = arcs[prevphase].ncaps; - } - if (isDashed && !arcsJoin) { - iDash = iDashStart; - iphase = iphaseStart; - dashRemaining = dashRemainingStart; - } - nextk = arcs[iphase].narcs; - if (nexti == start) { - nextk = 0; - iDash = iDashStart; - iphase = iphaseStart; - dashRemaining = dashRemainingStart; - } - /* - * cap the right end of the next arc. If the - * next arc is actually the first arc, only - * cap it if it joins with this arc. This - * case will occur when the final dash segment - * of an on/off dash is off. Of course, this - * cap will be drawn at a strange time, but that - * hardly matters... - */ - if ((iphase == 0 || isDoubleDash) && - (nexti != start || (arcsJoin && isDashed))) - addCap (&arcs[iphase].caps, &arcs[iphase].ncaps, - &capSize[iphase], RIGHT_END, nextk); - } - i = nexti; - if (i == start) - break; - } - /* - * make sure the last section is rendered - */ - for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) - if (arcs[iphase].narcs > 0) { - arcs[iphase].arcs[arcs[iphase].narcs-1].render = 1; - arcs[iphase].arcs[arcs[iphase].narcs-1].join = - arcs[iphase].njoins; - arcs[iphase].arcs[arcs[iphase].narcs-1].cap = - arcs[iphase].ncaps; - } - free(data); - return arcs; -arcfail: - miFreeArcs(arcs, pGC); - free(data); - return NULL; + int isDashed, isDoubleDash; + int dashOffset; + miPolyArcPtr arcs; + int start, i, j, k = 0, nexti, nextk = 0; + int joinSize[2]; + int capSize[2]; + int arcSize[2]; + int angle2; + double a0, a1; + struct arcData *data; + miArcDataPtr arc; + xArc xarc; + int iphase, prevphase = 0, joinphase; + int arcsJoin; + int selfJoin; + + int iDash = 0, dashRemaining = 0; + int iDashStart = 0, dashRemainingStart = 0, iphaseStart; + int startAngle, spanAngle, endAngle, backwards = 0; + int prevDashAngle, dashAngle; + dashMap map; + + isDashed = !(pGC->lineStyle == LineSolid); + isDoubleDash = (pGC->lineStyle == LineDoubleDash); + dashOffset = pGC->dashOffset; + + data = malloc(narcs * sizeof(struct arcData)); + if (!data) + return NULL; + arcs = malloc(sizeof(*arcs) * (isDoubleDash ? 2 : 1)); + if (!arcs) { + free(data); + return NULL; + } + for (i = 0; i < narcs; i++) { + a0 = todeg(parcs[i].angle1); + angle2 = parcs[i].angle2; + if (angle2 > FULLCIRCLE) + angle2 = FULLCIRCLE; + else if (angle2 < -FULLCIRCLE) + angle2 = -FULLCIRCLE; + data[i].selfJoin = angle2 == FULLCIRCLE || angle2 == -FULLCIRCLE; + a1 = todeg(parcs[i].angle1 + angle2); + data[i].x0 = + parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos(a0)); + data[i].y0 = + parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin(a0)); + data[i].x1 = + parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos(a1)); + data[i].y1 = + parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin(a1)); + } + + for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) { + arcs[iphase].njoins = 0; + arcs[iphase].joins = 0; + joinSize[iphase] = 0; + + arcs[iphase].ncaps = 0; + arcs[iphase].caps = 0; + capSize[iphase] = 0; + + arcs[iphase].narcs = 0; + arcs[iphase].arcs = 0; + arcSize[iphase] = 0; + } + + iphase = 0; + if (isDashed) { + iDash = 0; + dashRemaining = pGC->dash[0]; + while (dashOffset > 0) { + if (dashOffset >= dashRemaining) { + dashOffset -= dashRemaining; + iphase = iphase ? 0 : 1; + iDash++; + if (iDash == pGC->numInDashList) + iDash = 0; + dashRemaining = pGC->dash[iDash]; + } + else { + dashRemaining -= dashOffset; + dashOffset = 0; + } + } + iDashStart = iDash; + dashRemainingStart = dashRemaining; + } + iphaseStart = iphase; + + for (i = narcs - 1; i >= 0; i--) { + j = i + 1; + if (j == narcs) + j = 0; + if (data[i].selfJoin || i == j || + (UNEQUAL(data[i].x1, data[j].x0) || + UNEQUAL(data[i].y1, data[j].y0))) { + if (iphase == 0 || isDoubleDash) + addCap(&arcs[iphase].caps, &arcs[iphase].ncaps, + &capSize[iphase], RIGHT_END, 0); + break; + } + } + start = i + 1; + if (start == narcs) + start = 0; + i = start; + for (;;) { + j = i + 1; + if (j == narcs) + j = 0; + nexti = i + 1; + if (nexti == narcs) + nexti = 0; + if (isDashed) { + /* + ** deal with dashed arcs. Use special rules for certain 0 area arcs. + ** Presumably, the other 0 area arcs still aren't done right. + */ + arcTypes arcType = OTHER; + CARD16 thisLength; + + if (parcs[i].height == 0 + && (parcs[i].angle1 % FULLCIRCLE) == 0x2d00 + && parcs[i].angle2 == 0x2d00) + arcType = HORIZONTAL; + else if (parcs[i].width == 0 + && (parcs[i].angle1 % FULLCIRCLE) == 0x1680 + && parcs[i].angle2 == 0x2d00) + arcType = VERTICAL; + if (arcType == OTHER) { + /* + * precompute an approximation map + */ + computeDashMap(&parcs[i], &map); + /* + * compute each individual dash segment using the path + * length function + */ + startAngle = parcs[i].angle1; + spanAngle = parcs[i].angle2; + if (spanAngle > FULLCIRCLE) + spanAngle = FULLCIRCLE; + else if (spanAngle < -FULLCIRCLE) + spanAngle = -FULLCIRCLE; + if (startAngle < 0) + startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; + if (startAngle >= FULLCIRCLE) + startAngle = startAngle % FULLCIRCLE; + endAngle = startAngle + spanAngle; + backwards = spanAngle < 0; + } + else { + xarc = parcs[i]; + if (arcType == VERTICAL) { + xarc.angle1 = 0x1680; + startAngle = parcs[i].y; + endAngle = startAngle + parcs[i].height; + } + else { + xarc.angle1 = 0x2d00; + startAngle = parcs[i].x; + endAngle = startAngle + parcs[i].width; + } + } + dashAngle = startAngle; + selfJoin = data[i].selfJoin && (iphase == 0 || isDoubleDash); + /* + * add dashed arcs to each bucket + */ + arc = 0; + while (dashAngle != endAngle) { + prevDashAngle = dashAngle; + if (arcType == OTHER) { + dashAngle = computeAngleFromPath(prevDashAngle, endAngle, + &map, &dashRemaining, + backwards); + /* avoid troubles with huge arcs and small dashes */ + if (dashAngle == prevDashAngle) { + if (backwards) + dashAngle--; + else + dashAngle++; + } + } + else { + thisLength = (dashAngle + dashRemaining <= endAngle) ? + dashRemaining : endAngle - dashAngle; + if (arcType == VERTICAL) { + xarc.y = dashAngle; + xarc.height = thisLength; + } + else { + xarc.x = dashAngle; + xarc.width = thisLength; + } + dashAngle += thisLength; + dashRemaining -= thisLength; + } + if (iphase == 0 || isDoubleDash) { + if (arcType == OTHER) { + xarc = parcs[i]; + spanAngle = prevDashAngle; + if (spanAngle < 0) + spanAngle = FULLCIRCLE - (-spanAngle) % FULLCIRCLE; + if (spanAngle >= FULLCIRCLE) + spanAngle = spanAngle % FULLCIRCLE; + xarc.angle1 = spanAngle; + spanAngle = dashAngle - prevDashAngle; + if (backwards) { + if (dashAngle > prevDashAngle) + spanAngle = -FULLCIRCLE + spanAngle; + } + else { + if (dashAngle < prevDashAngle) + spanAngle = FULLCIRCLE + spanAngle; + } + if (spanAngle > FULLCIRCLE) + spanAngle = FULLCIRCLE; + if (spanAngle < -FULLCIRCLE) + spanAngle = -FULLCIRCLE; + xarc.angle2 = spanAngle; + } + arc = addArc(&arcs[iphase].arcs, &arcs[iphase].narcs, + &arcSize[iphase], &xarc); + if (!arc) + goto arcfail; + /* + * cap each end of an on/off dash + */ + if (!isDoubleDash) { + if (prevDashAngle != startAngle) { + addCap(&arcs[iphase].caps, + &arcs[iphase].ncaps, + &capSize[iphase], RIGHT_END, + arc - arcs[iphase].arcs); + + } + if (dashAngle != endAngle) { + addCap(&arcs[iphase].caps, + &arcs[iphase].ncaps, + &capSize[iphase], LEFT_END, + arc - arcs[iphase].arcs); + } + } + arc->cap = arcs[iphase].ncaps; + arc->join = arcs[iphase].njoins; + arc->render = 0; + arc->selfJoin = 0; + if (dashAngle == endAngle) + arc->selfJoin = selfJoin; + } + prevphase = iphase; + if (dashRemaining <= 0) { + ++iDash; + if (iDash == pGC->numInDashList) + iDash = 0; + iphase = iphase ? 0 : 1; + dashRemaining = pGC->dash[iDash]; + } + } + /* + * make sure a place exists for the position data when + * drawing a zero-length arc + */ + if (startAngle == endAngle) { + prevphase = iphase; + if (!isDoubleDash && iphase == 1) + prevphase = 0; + arc = addArc(&arcs[prevphase].arcs, &arcs[prevphase].narcs, + &arcSize[prevphase], &parcs[i]); + if (!arc) + goto arcfail; + arc->join = arcs[prevphase].njoins; + arc->cap = arcs[prevphase].ncaps; + arc->selfJoin = data[i].selfJoin; + } + } + else { + arc = addArc(&arcs[iphase].arcs, &arcs[iphase].narcs, + &arcSize[iphase], &parcs[i]); + if (!arc) + goto arcfail; + arc->join = arcs[iphase].njoins; + arc->cap = arcs[iphase].ncaps; + arc->selfJoin = data[i].selfJoin; + prevphase = iphase; + } + if (prevphase == 0 || isDoubleDash) + k = arcs[prevphase].narcs - 1; + if (iphase == 0 || isDoubleDash) + nextk = arcs[iphase].narcs; + if (nexti == start) { + nextk = 0; + if (isDashed) { + iDash = iDashStart; + iphase = iphaseStart; + dashRemaining = dashRemainingStart; + } + } + arcsJoin = narcs > 1 && i != j && + ISEQUAL(data[i].x1, data[j].x0) && + ISEQUAL(data[i].y1, data[j].y0) && + !data[i].selfJoin && !data[j].selfJoin; + if (arc) { + if (arcsJoin) + arc->render = 0; + else + arc->render = 1; + } + if (arcsJoin && + (prevphase == 0 || isDoubleDash) && (iphase == 0 || isDoubleDash)) { + joinphase = iphase; + if (isDoubleDash) { + if (nexti == start) + joinphase = iphaseStart; + /* + * if the join is right at the dash, + * draw the join in foreground + * This is because the foreground + * arcs are computed second, the results + * of which are needed to draw the join + */ + if (joinphase != prevphase) + joinphase = 0; + } + if (joinphase == 0 || isDoubleDash) { + addJoin(&arcs[joinphase].joins, + &arcs[joinphase].njoins, + &joinSize[joinphase], + LEFT_END, k, prevphase, RIGHT_END, nextk, iphase); + arc->join = arcs[prevphase].njoins; + } + } + else { + /* + * cap the left end of this arc + * unless it joins itself + */ + if ((prevphase == 0 || isDoubleDash) && !arc->selfJoin) { + addCap(&arcs[prevphase].caps, &arcs[prevphase].ncaps, + &capSize[prevphase], LEFT_END, k); + arc->cap = arcs[prevphase].ncaps; + } + if (isDashed && !arcsJoin) { + iDash = iDashStart; + iphase = iphaseStart; + dashRemaining = dashRemainingStart; + } + nextk = arcs[iphase].narcs; + if (nexti == start) { + nextk = 0; + iDash = iDashStart; + iphase = iphaseStart; + dashRemaining = dashRemainingStart; + } + /* + * cap the right end of the next arc. If the + * next arc is actually the first arc, only + * cap it if it joins with this arc. This + * case will occur when the final dash segment + * of an on/off dash is off. Of course, this + * cap will be drawn at a strange time, but that + * hardly matters... + */ + if ((iphase == 0 || isDoubleDash) && + (nexti != start || (arcsJoin && isDashed))) + addCap(&arcs[iphase].caps, &arcs[iphase].ncaps, + &capSize[iphase], RIGHT_END, nextk); + } + i = nexti; + if (i == start) + break; + } + /* + * make sure the last section is rendered + */ + for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) + if (arcs[iphase].narcs > 0) { + arcs[iphase].arcs[arcs[iphase].narcs - 1].render = 1; + arcs[iphase].arcs[arcs[iphase].narcs - 1].join = + arcs[iphase].njoins; + arcs[iphase].arcs[arcs[iphase].narcs - 1].cap = arcs[iphase].ncaps; + } + free(data); + return arcs; + arcfail: + miFreeArcs(arcs, pGC); + free(data); + return NULL; } static double -angleToLength ( - int angle, - dashMap *map) +angleToLength(int angle, dashMap * map) { - double len, excesslen, sidelen = map->map[DASH_MAP_SIZE - 1], totallen; - int di; - int excess; - Bool oddSide = FALSE; - - totallen = 0; - if (angle >= 0) { - while (angle >= 90 * 64) { - angle -= 90 * 64; - totallen += sidelen; - oddSide = !oddSide; - } - } else { - while (angle < 0) { - angle += 90 * 64; - totallen -= sidelen; - oddSide = !oddSide; - } - } - if (oddSide) - angle = 90 * 64 - angle; - - di = xAngleToDashIndex (angle); - excess = angle - dashIndexToXAngle (di); - - len = map->map[di]; - /* - * linearly interpolate between this point and the next - */ - if (excess > 0) { - excesslen = (map->map[di + 1] - map->map[di]) * - ((double) excess) / dashXAngleStep; - len += excesslen; - } - if (oddSide) - totallen += (sidelen - len); - else - totallen += len; - return totallen; + double len, excesslen, sidelen = map->map[DASH_MAP_SIZE - 1], totallen; + int di; + int excess; + Bool oddSide = FALSE; + + totallen = 0; + if (angle >= 0) { + while (angle >= 90 * 64) { + angle -= 90 * 64; + totallen += sidelen; + oddSide = !oddSide; + } + } + else { + while (angle < 0) { + angle += 90 * 64; + totallen -= sidelen; + oddSide = !oddSide; + } + } + if (oddSide) + angle = 90 * 64 - angle; + + di = xAngleToDashIndex(angle); + excess = angle - dashIndexToXAngle(di); + + len = map->map[di]; + /* + * linearly interpolate between this point and the next + */ + if (excess > 0) { + excesslen = (map->map[di + 1] - map->map[di]) * + ((double) excess) / dashXAngleStep; + len += excesslen; + } + if (oddSide) + totallen += (sidelen - len); + else + totallen += len; + return totallen; } /* @@ -2216,63 +2120,62 @@ angleToLength ( */ static int -lengthToAngle ( - double len, - dashMap *map) +lengthToAngle(double len, dashMap * map) { - double sidelen = map->map[DASH_MAP_SIZE - 1]; - int angle, angleexcess; - Bool oddSide = FALSE; - int a0, a1, a; - - angle = 0; - /* - * step around the ellipse, subtracting sidelens and - * adding 90 degrees. oddSide will tell if the - * map should be interpolated in reverse - */ - if (len >= 0) { - if (sidelen == 0) - return 2 * FULLCIRCLE; /* infinity */ - while (len >= sidelen) { - angle += 90 * 64; - len -= sidelen; - oddSide = !oddSide; - } - } else { - if (sidelen == 0) - return -2 * FULLCIRCLE; /* infinity */ - while (len < 0) { - angle -= 90 * 64; - len += sidelen; - oddSide = !oddSide; - } - } - if (oddSide) - len = sidelen - len; - a0 = 0; - a1 = DASH_MAP_SIZE - 1; - /* - * binary search for the closest pre-computed length - */ - while (a1 - a0 > 1) { - a = (a0 + a1) / 2; - if (len > map->map[a]) - a0 = a; - else - a1 = a; - } - angleexcess = dashIndexToXAngle (a0); - /* - * linearly interpolate to the next point - */ - angleexcess += (len - map->map[a0]) / - (map->map[a0+1] - map->map[a0]) * dashXAngleStep; - if (oddSide) - angle += (90 * 64) - angleexcess; - else - angle += angleexcess; - return angle; + double sidelen = map->map[DASH_MAP_SIZE - 1]; + int angle, angleexcess; + Bool oddSide = FALSE; + int a0, a1, a; + + angle = 0; + /* + * step around the ellipse, subtracting sidelens and + * adding 90 degrees. oddSide will tell if the + * map should be interpolated in reverse + */ + if (len >= 0) { + if (sidelen == 0) + return 2 * FULLCIRCLE; /* infinity */ + while (len >= sidelen) { + angle += 90 * 64; + len -= sidelen; + oddSide = !oddSide; + } + } + else { + if (sidelen == 0) + return -2 * FULLCIRCLE; /* infinity */ + while (len < 0) { + angle -= 90 * 64; + len += sidelen; + oddSide = !oddSide; + } + } + if (oddSide) + len = sidelen - len; + a0 = 0; + a1 = DASH_MAP_SIZE - 1; + /* + * binary search for the closest pre-computed length + */ + while (a1 - a0 > 1) { + a = (a0 + a1) / 2; + if (len > map->map[a]) + a0 = a; + else + a1 = a; + } + angleexcess = dashIndexToXAngle(a0); + /* + * linearly interpolate to the next point + */ + angleexcess += (len - map->map[a0]) / + (map->map[a0 + 1] - map->map[a0]) * dashXAngleStep; + if (oddSide) + angle += (90 * 64) - angleexcess; + else + angle += angleexcess; + return angle; } /* @@ -2288,41 +2191,38 @@ lengthToAngle ( */ static int -computeAngleFromPath ( - int startAngle, - int endAngle, /* normalized absolute angles in *64 degrees */ - dashMap *map, - int *lenp, - int backwards) +computeAngleFromPath(int startAngle, int endAngle, /* normalized absolute angles in *64 degrees */ + dashMap * map, int *lenp, int backwards) { - int a0, a1, a; - double len0; - int len; - - a0 = startAngle; - a1 = endAngle; - len = *lenp; - if (backwards) { - /* - * flip the problem around to always be - * forwards - */ - a0 = FULLCIRCLE - a0; - a1 = FULLCIRCLE - a1; - } - if (a1 < a0) - a1 += FULLCIRCLE; - len0 = angleToLength (a0, map); - a = lengthToAngle (len0 + len, map); - if (a > a1) { - a = a1; - len -= angleToLength (a1, map) - len0; - } else - len = 0; - if (backwards) - a = FULLCIRCLE - a; - *lenp = len; - return a; + int a0, a1, a; + double len0; + int len; + + a0 = startAngle; + a1 = endAngle; + len = *lenp; + if (backwards) { + /* + * flip the problem around to always be + * forwards + */ + a0 = FULLCIRCLE - a0; + a1 = FULLCIRCLE - a1; + } + if (a1 < a0) + a1 += FULLCIRCLE; + len0 = angleToLength(a0, map); + a = lengthToAngle(len0 + len, map); + if (a > a1) { + a = a1; + len -= angleToLength(a1, map) - len0; + } + else + len = 0; + if (backwards) + a = FULLCIRCLE - a; + *lenp = len; + return a; } /* @@ -2334,133 +2234,122 @@ computeAngleFromPath ( */ static void -drawZeroArc ( - DrawablePtr pDraw, - GCPtr pGC, - xArc *tarc, - int lw, - miArcFacePtr left, - miArcFacePtr right) +drawZeroArc(DrawablePtr pDraw, + GCPtr pGC, + xArc * tarc, int lw, miArcFacePtr left, miArcFacePtr right) { - double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0, w, h, x, y; - double xmax, ymax, xmin, ymin; - int a0, a1; - double a, startAngle, endAngle; - double l, lx, ly; - - l = lw / 2.0; - a0 = tarc->angle1; - a1 = tarc->angle2; - if (a1 > FULLCIRCLE) - a1 = FULLCIRCLE; - else if (a1 < -FULLCIRCLE) - a1 = -FULLCIRCLE; - w = (double)tarc->width / 2.0; - h = (double)tarc->height / 2.0; - /* - * play in X coordinates right away - */ - startAngle = - ((double) a0 / 64.0); - endAngle = - ((double) (a0 + a1) / 64.0); - - xmax = -w; - xmin = w; - ymax = -h; - ymin = h; - a = startAngle; - for (;;) - { - x = w * miDcos(a); - y = h * miDsin(a); - if (a == startAngle) - { - x0 = x; - y0 = y; - } - if (a == endAngle) - { - x1 = x; - y1 = y; - } - if (x > xmax) - xmax = x; - if (x < xmin) - xmin = x; - if (y > ymax) - ymax = y; - if (y < ymin) - ymin = y; - if (a == endAngle) - break; - if (a1 < 0) /* clockwise */ - { - if (floor (a / 90.0) == floor (endAngle / 90.0)) - a = endAngle; - else - a = 90 * (floor (a/90.0) + 1); - } - else - { - if (ceil (a / 90.0) == ceil (endAngle / 90.0)) - a = endAngle; - else - a = 90 * (ceil (a/90.0) - 1); - } - } - lx = ly = l; - if ((x1 - x0) + (y1 - y0) < 0) - lx = ly = -l; - if (h) - { - ly = 0.0; - lx = -lx; - } - else - lx = 0.0; - if (right) - { - right->center.x = x0; - right->center.y = y0; - right->clock.x = x0 - lx; - right->clock.y = y0 - ly; - right->counterClock.x = x0 + lx; - right->counterClock.y = y0 + ly; - } - if (left) - { - left->center.x = x1; - left->center.y = y1; - left->clock.x = x1 + lx; - left->clock.y = y1 + ly; - left->counterClock.x = x1 - lx; - left->counterClock.y = y1 - ly; - } - - x0 = xmin; - x1 = xmax; - y0 = ymin; - y1 = ymax; - if (ymin != y1) { - xmin = -l; - xmax = l; - } else { - ymin = -l; - ymax = l; - } - if (xmax != xmin && ymax != ymin) { - int minx, maxx, miny, maxy; - xRectangle rect; - - minx = ICEIL (xmin + w) + tarc->x; - maxx = ICEIL (xmax + w) + tarc->x; - miny = ICEIL (ymin + h) + tarc->y; - maxy = ICEIL (ymax + h) + tarc->y; - rect.x = minx; - rect.y = miny; - rect.width = maxx - minx; - rect.height = maxy - miny; - (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect); - } + double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0, w, h, x, y; + double xmax, ymax, xmin, ymin; + int a0, a1; + double a, startAngle, endAngle; + double l, lx, ly; + + l = lw / 2.0; + a0 = tarc->angle1; + a1 = tarc->angle2; + if (a1 > FULLCIRCLE) + a1 = FULLCIRCLE; + else if (a1 < -FULLCIRCLE) + a1 = -FULLCIRCLE; + w = (double) tarc->width / 2.0; + h = (double) tarc->height / 2.0; + /* + * play in X coordinates right away + */ + startAngle = -((double) a0 / 64.0); + endAngle = -((double) (a0 + a1) / 64.0); + + xmax = -w; + xmin = w; + ymax = -h; + ymin = h; + a = startAngle; + for (;;) { + x = w * miDcos(a); + y = h * miDsin(a); + if (a == startAngle) { + x0 = x; + y0 = y; + } + if (a == endAngle) { + x1 = x; + y1 = y; + } + if (x > xmax) + xmax = x; + if (x < xmin) + xmin = x; + if (y > ymax) + ymax = y; + if (y < ymin) + ymin = y; + if (a == endAngle) + break; + if (a1 < 0) { /* clockwise */ + if (floor(a / 90.0) == floor(endAngle / 90.0)) + a = endAngle; + else + a = 90 * (floor(a / 90.0) + 1); + } + else { + if (ceil(a / 90.0) == ceil(endAngle / 90.0)) + a = endAngle; + else + a = 90 * (ceil(a / 90.0) - 1); + } + } + lx = ly = l; + if ((x1 - x0) + (y1 - y0) < 0) + lx = ly = -l; + if (h) { + ly = 0.0; + lx = -lx; + } + else + lx = 0.0; + if (right) { + right->center.x = x0; + right->center.y = y0; + right->clock.x = x0 - lx; + right->clock.y = y0 - ly; + right->counterClock.x = x0 + lx; + right->counterClock.y = y0 + ly; + } + if (left) { + left->center.x = x1; + left->center.y = y1; + left->clock.x = x1 + lx; + left->clock.y = y1 + ly; + left->counterClock.x = x1 - lx; + left->counterClock.y = y1 - ly; + } + + x0 = xmin; + x1 = xmax; + y0 = ymin; + y1 = ymax; + if (ymin != y1) { + xmin = -l; + xmax = l; + } + else { + ymin = -l; + ymax = l; + } + if (xmax != xmin && ymax != ymin) { + int minx, maxx, miny, maxy; + xRectangle rect; + + minx = ICEIL(xmin + w) + tarc->x; + maxx = ICEIL(xmax + w) + tarc->x; + miny = ICEIL(ymin + h) + tarc->y; + maxy = ICEIL(ymax + h) + tarc->y; + rect.x = minx; + rect.y = miny; + rect.width = maxx - minx; + rect.height = maxy - miny; + (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect); + } } /* @@ -2469,27 +2358,26 @@ drawZeroArc ( */ static void -tailEllipseY ( - struct arc_def *def, - struct accelerators *acc) +tailEllipseY(struct arc_def *def, struct accelerators *acc) { - double t; - - acc->tail_y = 0.0; - if (def->w == def->h) - return; - t = def->l * def->w; - if (def->w > def->h) { - if (t < acc->h2) - return; - } else { - if (t > acc->h2) - return; - } - t = 2.0 * def->h * t; - t = (CUBED_ROOT_4 * acc->h2 - cbrt(t * t)) / acc->h2mw2; - if (t > 0.0) - acc->tail_y = def->h / CUBED_ROOT_2 * sqrt(t); + double t; + + acc->tail_y = 0.0; + if (def->w == def->h) + return; + t = def->l * def->w; + if (def->w > def->h) { + if (t < acc->h2) + return; + } + else { + if (t > acc->h2) + return; + } + t = 2.0 * def->h * t; + t = (CUBED_ROOT_4 * acc->h2 - cbrt(t * t)) / acc->h2mw2; + if (t > 0.0) + acc->tail_y = def->h / CUBED_ROOT_2 * sqrt(t); } /* @@ -2498,73 +2386,49 @@ tailEllipseY ( */ static double -outerXfromXY ( - double x, - double y, - struct arc_def *def, - struct accelerators *acc) +outerXfromXY(double x, double y, struct arc_def *def, struct accelerators *acc) { - return x + (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); + return x + (x * acc->h2l) / sqrt(x * x * acc->h4 + y * y * acc->w4); } static double -outerYfromXY ( - double x, - double y, - struct arc_def *def, - struct accelerators *acc) +outerYfromXY(double x, double y, struct arc_def *def, struct accelerators *acc) { - return y + (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); + return y + (y * acc->w2l) / sqrt(x * x * acc->h4 + y * y * acc->w4); } static double -innerXfromXY ( - double x, - double y, - struct arc_def *def, - struct accelerators *acc) +innerXfromXY(double x, double y, struct arc_def *def, struct accelerators *acc) { - return x - (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); + return x - (x * acc->h2l) / sqrt(x * x * acc->h4 + y * y * acc->w4); } static double -innerYfromXY ( - double x, - double y, - struct arc_def *def, - struct accelerators *acc) +innerYfromXY(double x, double y, struct arc_def *def, struct accelerators *acc) { - return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); + return y - (y * acc->w2l) / sqrt(x * x * acc->h4 + y * y * acc->w4); } static double -innerYfromY ( - double y, - struct arc_def *def, - struct accelerators *acc) +innerYfromY(double y, struct arc_def *def, struct accelerators *acc) { - double x; + double x; - x = (def->w / def->h) * sqrt (acc->h2 - y*y); + x = (def->w / def->h) * sqrt(acc->h2 - y * y); - return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4); + return y - (y * acc->w2l) / sqrt(x * x * acc->h4 + y * y * acc->w4); } static void -computeLine ( - double x1, - double y1, - double x2, - double y2, - struct line *line) +computeLine(double x1, double y1, double x2, double y2, struct line *line) { - if (y1 == y2) - line->valid = 0; - else { - line->m = (x1 - x2) / (y1 - y2); - line->b = x1 - y1 * line->m; - line->valid = 1; - } + if (y1 == y2) + line->valid = 0; + else { + line->m = (x1 - x2) / (y1 - y2); + line->b = x1 - y1 * line->m; + line->valid = 1; + } } /* @@ -2574,124 +2438,117 @@ computeLine ( */ static void -computeAcc ( - xArc *tarc, - int lw, - struct arc_def *def, - struct accelerators *acc) +computeAcc(xArc * tarc, int lw, struct arc_def *def, struct accelerators *acc) { - def->w = ((double) tarc->width) / 2.0; - def->h = ((double) tarc->height) / 2.0; - def->l = ((double) lw) / 2.0; - acc->h2 = def->h * def->h; - acc->w2 = def->w * def->w; - acc->h4 = acc->h2 * acc->h2; - acc->w4 = acc->w2 * acc->w2; - acc->h2l = acc->h2 * def->l; - acc->w2l = acc->w2 * def->l; - acc->h2mw2 = acc->h2 - acc->w2; - acc->fromIntX = (tarc->width & 1) ? 0.5 : 0.0; - acc->fromIntY = (tarc->height & 1) ? 0.5 : 0.0; - acc->xorg = tarc->x + (tarc->width >> 1); - acc->yorgu = tarc->y + (tarc->height >> 1); - acc->yorgl = acc->yorgu + (tarc->height & 1); - tailEllipseY (def, acc); + def->w = ((double) tarc->width) / 2.0; + def->h = ((double) tarc->height) / 2.0; + def->l = ((double) lw) / 2.0; + acc->h2 = def->h * def->h; + acc->w2 = def->w * def->w; + acc->h4 = acc->h2 * acc->h2; + acc->w4 = acc->w2 * acc->w2; + acc->h2l = acc->h2 * def->l; + acc->w2l = acc->w2 * def->l; + acc->h2mw2 = acc->h2 - acc->w2; + acc->fromIntX = (tarc->width & 1) ? 0.5 : 0.0; + acc->fromIntY = (tarc->height & 1) ? 0.5 : 0.0; + acc->xorg = tarc->x + (tarc->width >> 1); + acc->yorgu = tarc->y + (tarc->height >> 1); + acc->yorgl = acc->yorgu + (tarc->height & 1); + tailEllipseY(def, acc); } - + /* * compute y value bounds of various portions of the arc, * the outer edge, the ellipse and the inner edge. */ static void -computeBound ( - struct arc_def *def, - struct arc_bound *bound, - struct accelerators *acc, - miArcFacePtr right, - miArcFacePtr left) +computeBound(struct arc_def *def, + struct arc_bound *bound, + struct accelerators *acc, miArcFacePtr right, miArcFacePtr left) { - double t; - double innerTaily; - double tail_y; - struct bound innerx, outerx; - struct bound ellipsex; - - bound->ellipse.min = Dsin (def->a0) * def->h; - bound->ellipse.max = Dsin (def->a1) * def->h; - if (def->a0 == 45 && def->w == def->h) - ellipsex.min = bound->ellipse.min; - else - ellipsex.min = Dcos (def->a0) * def->w; - if (def->a1 == 45 && def->w == def->h) - ellipsex.max = bound->ellipse.max; - else - ellipsex.max = Dcos (def->a1) * def->w; - bound->outer.min = outerYfromXY (ellipsex.min, bound->ellipse.min, def, acc); - bound->outer.max = outerYfromXY (ellipsex.max, bound->ellipse.max, def, acc); - bound->inner.min = innerYfromXY (ellipsex.min, bound->ellipse.min, def, acc); - bound->inner.max = innerYfromXY (ellipsex.max, bound->ellipse.max, def, acc); - - outerx.min = outerXfromXY (ellipsex.min, bound->ellipse.min, def, acc); - outerx.max = outerXfromXY (ellipsex.max, bound->ellipse.max, def, acc); - innerx.min = innerXfromXY (ellipsex.min, bound->ellipse.min, def, acc); - innerx.max = innerXfromXY (ellipsex.max, bound->ellipse.max, def, acc); - - /* - * save the line end points for the - * cap code to use. Careful here, these are - * in cartesean coordinates (y increasing upwards) - * while the cap code uses inverted coordinates - * (y increasing downwards) - */ - - if (right) { - right->counterClock.y = bound->outer.min; - right->counterClock.x = outerx.min; - right->center.y = bound->ellipse.min; - right->center.x = ellipsex.min; - right->clock.y = bound->inner.min; - right->clock.x = innerx.min; - } - - if (left) { - left->clock.y = bound->outer.max; - left->clock.x = outerx.max; - left->center.y = bound->ellipse.max; - left->center.x = ellipsex.max; - left->counterClock.y = bound->inner.max; - left->counterClock.x = innerx.max; - } - - bound->left.min = bound->inner.max; - bound->left.max = bound->outer.max; - bound->right.min = bound->inner.min; - bound->right.max = bound->outer.min; - - computeLine (innerx.min, bound->inner.min, outerx.min, bound->outer.min, - &acc->right); - computeLine (innerx.max, bound->inner.max, outerx.max, bound->outer.max, - &acc->left); - - if (bound->inner.min > bound->inner.max) { - t = bound->inner.min; - bound->inner.min = bound->inner.max; - bound->inner.max = t; - } - tail_y = acc->tail_y; - if (tail_y > bound->ellipse.max) - tail_y = bound->ellipse.max; - else if (tail_y < bound->ellipse.min) - tail_y = bound->ellipse.min; - innerTaily = innerYfromY (tail_y, def, acc); - if (bound->inner.min > innerTaily) - bound->inner.min = innerTaily; - if (bound->inner.max < innerTaily) - bound->inner.max = innerTaily; - bound->inneri.min = ICEIL(bound->inner.min - acc->fromIntY); - bound->inneri.max = floor(bound->inner.max - acc->fromIntY); - bound->outeri.min = ICEIL(bound->outer.min - acc->fromIntY); - bound->outeri.max = floor(bound->outer.max - acc->fromIntY); + double t; + double innerTaily; + double tail_y; + struct bound innerx, outerx; + struct bound ellipsex; + + bound->ellipse.min = Dsin(def->a0) * def->h; + bound->ellipse.max = Dsin(def->a1) * def->h; + if (def->a0 == 45 && def->w == def->h) + ellipsex.min = bound->ellipse.min; + else + ellipsex.min = Dcos(def->a0) * def->w; + if (def->a1 == 45 && def->w == def->h) + ellipsex.max = bound->ellipse.max; + else + ellipsex.max = Dcos(def->a1) * def->w; + bound->outer.min = outerYfromXY(ellipsex.min, bound->ellipse.min, def, acc); + bound->outer.max = outerYfromXY(ellipsex.max, bound->ellipse.max, def, acc); + bound->inner.min = innerYfromXY(ellipsex.min, bound->ellipse.min, def, acc); + bound->inner.max = innerYfromXY(ellipsex.max, bound->ellipse.max, def, acc); + + outerx.min = outerXfromXY(ellipsex.min, bound->ellipse.min, def, acc); + outerx.max = outerXfromXY(ellipsex.max, bound->ellipse.max, def, acc); + innerx.min = innerXfromXY(ellipsex.min, bound->ellipse.min, def, acc); + innerx.max = innerXfromXY(ellipsex.max, bound->ellipse.max, def, acc); + + /* + * save the line end points for the + * cap code to use. Careful here, these are + * in cartesean coordinates (y increasing upwards) + * while the cap code uses inverted coordinates + * (y increasing downwards) + */ + + if (right) { + right->counterClock.y = bound->outer.min; + right->counterClock.x = outerx.min; + right->center.y = bound->ellipse.min; + right->center.x = ellipsex.min; + right->clock.y = bound->inner.min; + right->clock.x = innerx.min; + } + + if (left) { + left->clock.y = bound->outer.max; + left->clock.x = outerx.max; + left->center.y = bound->ellipse.max; + left->center.x = ellipsex.max; + left->counterClock.y = bound->inner.max; + left->counterClock.x = innerx.max; + } + + bound->left.min = bound->inner.max; + bound->left.max = bound->outer.max; + bound->right.min = bound->inner.min; + bound->right.max = bound->outer.min; + + computeLine(innerx.min, bound->inner.min, outerx.min, bound->outer.min, + &acc->right); + computeLine(innerx.max, bound->inner.max, outerx.max, bound->outer.max, + &acc->left); + + if (bound->inner.min > bound->inner.max) { + t = bound->inner.min; + bound->inner.min = bound->inner.max; + bound->inner.max = t; + } + tail_y = acc->tail_y; + if (tail_y > bound->ellipse.max) + tail_y = bound->ellipse.max; + else if (tail_y < bound->ellipse.min) + tail_y = bound->ellipse.min; + innerTaily = innerYfromY(tail_y, def, acc); + if (bound->inner.min > innerTaily) + bound->inner.min = innerTaily; + if (bound->inner.max < innerTaily) + bound->inner.max = innerTaily; + bound->inneri.min = ICEIL(bound->inner.min - acc->fromIntY); + bound->inneri.max = floor(bound->inner.max - acc->fromIntY); + bound->outeri.min = ICEIL(bound->outer.min - acc->fromIntY); + bound->outeri.max = floor(bound->outer.max - acc->fromIntY); } /* @@ -2745,24 +2602,21 @@ computeBound ( */ static double -hookEllipseY ( - double scan_y, - struct arc_bound *bound, - struct accelerators *acc, - int left) +hookEllipseY(double scan_y, + struct arc_bound *bound, struct accelerators *acc, int left) { - double ret; - - if (acc->h2mw2 == 0) { - if ( (scan_y > 0 && !left) || (scan_y < 0 && left) ) - return bound->ellipse.min; - return bound->ellipse.max; - } - ret = (acc->h4 * scan_y) / (acc->h2mw2); - if (ret >= 0) - return cbrt (ret); - else - return -cbrt (-ret); + double ret; + + if (acc->h2mw2 == 0) { + if ((scan_y > 0 && !left) || (scan_y < 0 && left)) + return bound->ellipse.min; + return bound->ellipse.max; + } + ret = (acc->h4 * scan_y) / (acc->h2mw2); + if (ret >= 0) + return cbrt(ret); + else + return -cbrt(-ret); } /* @@ -2771,55 +2625,55 @@ hookEllipseY ( */ static double -hookX ( - double scan_y, - struct arc_def *def, - struct arc_bound *bound, - struct accelerators *acc, - int left) +hookX(double scan_y, + struct arc_def *def, + struct arc_bound *bound, struct accelerators *acc, int left) { - double ellipse_y, x; - double maxMin; - - if (def->w != def->h) { - ellipse_y = hookEllipseY (scan_y, bound, acc, left); - if (boundedLe (ellipse_y, bound->ellipse)) { - /* - * compute the value of the second - * derivative - */ - maxMin = ellipse_y*ellipse_y*ellipse_y * acc->h2mw2 - - acc->h2 * scan_y * (3 * ellipse_y*ellipse_y - 2*acc->h2); - if ((left && maxMin > 0) || (!left && maxMin < 0)) { - if (ellipse_y == 0) - return def->w + left ? -def->l : def->l; - x = (acc->h2 * scan_y - ellipse_y * acc->h2mw2) * - sqrt (acc->h2 - ellipse_y * ellipse_y) / - (def->h * def->w * ellipse_y); - return x; - } - } - } - if (left) { - if (acc->left.valid && boundedLe (scan_y, bound->left)) { - x = intersectLine (scan_y, acc->left); - } else { - if (acc->right.valid) - x = intersectLine (scan_y, acc->right); - else - x = def->w - def->l; - } - } else { - if (acc->right.valid && boundedLe (scan_y, bound->right)) { - x = intersectLine (scan_y, acc->right); - } else { - if (acc->left.valid) - x = intersectLine (scan_y, acc->left); - else - x = def->w - def->l; - } - } - return x; + double ellipse_y, x; + double maxMin; + + if (def->w != def->h) { + ellipse_y = hookEllipseY(scan_y, bound, acc, left); + if (boundedLe(ellipse_y, bound->ellipse)) { + /* + * compute the value of the second + * derivative + */ + maxMin = ellipse_y * ellipse_y * ellipse_y * acc->h2mw2 - + acc->h2 * scan_y * (3 * ellipse_y * ellipse_y - 2 * acc->h2); + if ((left && maxMin > 0) || (!left && maxMin < 0)) { + if (ellipse_y == 0) + return def->w + left ? -def->l : def->l; + x = (acc->h2 * scan_y - ellipse_y * acc->h2mw2) * + sqrt(acc->h2 - ellipse_y * ellipse_y) / + (def->h * def->w * ellipse_y); + return x; + } + } + } + if (left) { + if (acc->left.valid && boundedLe(scan_y, bound->left)) { + x = intersectLine(scan_y, acc->left); + } + else { + if (acc->right.valid) + x = intersectLine(scan_y, acc->right); + else + x = def->w - def->l; + } + } + else { + if (acc->right.valid && boundedLe(scan_y, bound->right)) { + x = intersectLine(scan_y, acc->right); + } + else { + if (acc->left.valid) + x = intersectLine(scan_y, acc->left); + else + x = def->w - def->l; + } + } + return x; } /* @@ -2828,152 +2682,130 @@ hookX ( */ static void -arcSpan ( - int y, - int lx, - int lw, - int rx, - int rw, - struct arc_def *def, - struct arc_bound *bounds, - struct accelerators *acc, - int mask) +arcSpan(int y, + int lx, + int lw, + int rx, + int rw, + struct arc_def *def, + struct arc_bound *bounds, struct accelerators *acc, int mask) { - int linx, loutx, rinx, routx; - double x, altx; - - if (boundedLe (y, bounds->inneri)) { - linx = -(lx + lw); - rinx = rx; - } else { - /* - * intersection with left face - */ - x = hookX (y + acc->fromIntY, def, bounds, acc, 1); - if (acc->right.valid && - boundedLe (y + acc->fromIntY, bounds->right)) - { - altx = intersectLine (y + acc->fromIntY, acc->right); - if (altx < x) - x = altx; - } - linx = -ICEIL(acc->fromIntX - x); - rinx = ICEIL(acc->fromIntX + x); - } - if (boundedLe (y, bounds->outeri)) { - loutx = -lx; - routx = rx + rw; - } else { - /* - * intersection with right face - */ - x = hookX (y + acc->fromIntY, def, bounds, acc, 0); - if (acc->left.valid && - boundedLe (y + acc->fromIntY, bounds->left)) - { - altx = x; - x = intersectLine (y + acc->fromIntY, acc->left); - if (x < altx) - x = altx; - } - loutx = -ICEIL(acc->fromIntX - x); - routx = ICEIL(acc->fromIntX + x); - } - if (routx > rinx) { - if (mask & 1) - newFinalSpan (acc->yorgu - y, - acc->xorg + rinx, acc->xorg + routx); - if (mask & 8) - newFinalSpan (acc->yorgl + y, - acc->xorg + rinx, acc->xorg + routx); - } - if (loutx > linx) { - if (mask & 2) - newFinalSpan (acc->yorgu - y, - acc->xorg - loutx, acc->xorg - linx); - if (mask & 4) - newFinalSpan (acc->yorgl + y, - acc->xorg - loutx, acc->xorg - linx); - } + int linx, loutx, rinx, routx; + double x, altx; + + if (boundedLe(y, bounds->inneri)) { + linx = -(lx + lw); + rinx = rx; + } + else { + /* + * intersection with left face + */ + x = hookX(y + acc->fromIntY, def, bounds, acc, 1); + if (acc->right.valid && boundedLe(y + acc->fromIntY, bounds->right)) { + altx = intersectLine(y + acc->fromIntY, acc->right); + if (altx < x) + x = altx; + } + linx = -ICEIL(acc->fromIntX - x); + rinx = ICEIL(acc->fromIntX + x); + } + if (boundedLe(y, bounds->outeri)) { + loutx = -lx; + routx = rx + rw; + } + else { + /* + * intersection with right face + */ + x = hookX(y + acc->fromIntY, def, bounds, acc, 0); + if (acc->left.valid && boundedLe(y + acc->fromIntY, bounds->left)) { + altx = x; + x = intersectLine(y + acc->fromIntY, acc->left); + if (x < altx) + x = altx; + } + loutx = -ICEIL(acc->fromIntX - x); + routx = ICEIL(acc->fromIntX + x); + } + if (routx > rinx) { + if (mask & 1) + newFinalSpan(acc->yorgu - y, acc->xorg + rinx, acc->xorg + routx); + if (mask & 8) + newFinalSpan(acc->yorgl + y, acc->xorg + rinx, acc->xorg + routx); + } + if (loutx > linx) { + if (mask & 2) + newFinalSpan(acc->yorgu - y, acc->xorg - loutx, acc->xorg - linx); + if (mask & 4) + newFinalSpan(acc->yorgl + y, acc->xorg - loutx, acc->xorg - linx); + } } static void -arcSpan0 ( - int lx, - int lw, - int rx, - int rw, - struct arc_def *def, - struct arc_bound *bounds, - struct accelerators *acc, - int mask) +arcSpan0(int lx, + int lw, + int rx, + int rw, + struct arc_def *def, + struct arc_bound *bounds, struct accelerators *acc, int mask) { double x; - if (boundedLe (0, bounds->inneri) && - acc->left.valid && boundedLe (0, bounds->left) && - acc->left.b > 0) - { - x = def->w - def->l; - if (acc->left.b < x) - x = acc->left.b; - lw = ICEIL(acc->fromIntX - x) - lx; - rw += rx; - rx = ICEIL(acc->fromIntX + x); - rw -= rx; - } - arcSpan (0, lx, lw, rx, rw, def, bounds, acc, mask); + if (boundedLe(0, bounds->inneri) && + acc->left.valid && boundedLe(0, bounds->left) && acc->left.b > 0) { + x = def->w - def->l; + if (acc->left.b < x) + x = acc->left.b; + lw = ICEIL(acc->fromIntX - x) - lx; + rw += rx; + rx = ICEIL(acc->fromIntX + x); + rw -= rx; + } + arcSpan(0, lx, lw, rx, rw, def, bounds, acc, mask); } static void -tailSpan ( - int y, - int lw, - int rw, - struct arc_def *def, - struct arc_bound *bounds, - struct accelerators *acc, - int mask) +tailSpan(int y, + int lw, + int rw, + struct arc_def *def, + struct arc_bound *bounds, struct accelerators *acc, int mask) { double yy, xalt, x, lx, rx; int n; if (boundedLe(y, bounds->outeri)) - arcSpan (y, 0, lw, -rw, rw, def, bounds, acc, mask); + arcSpan(y, 0, lw, -rw, rw, def, bounds, acc, mask); else if (def->w != def->h) { - yy = y + acc->fromIntY; - x = tailX(yy, def, bounds, acc); - if (yy == 0.0 && x == -rw - acc->fromIntX) - return; - if (acc->right.valid && boundedLe (yy, bounds->right)) { - rx = x; - lx = -x; - xalt = intersectLine (yy, acc->right); - if (xalt >= -rw - acc->fromIntX && xalt <= rx) - rx = xalt; - n = ICEIL(acc->fromIntX + lx); - if (lw > n) { - if (mask & 2) - newFinalSpan (acc->yorgu - y, - acc->xorg + n, acc->xorg + lw); - if (mask & 4) - newFinalSpan (acc->yorgl + y, - acc->xorg + n, acc->xorg + lw); - } - n = ICEIL(acc->fromIntX + rx); - if (n > -rw) { - if (mask & 1) - newFinalSpan (acc->yorgu - y, - acc->xorg - rw, acc->xorg + n); - if (mask & 8) - newFinalSpan (acc->yorgl + y, - acc->xorg - rw, acc->xorg + n); - } - } - arcSpan (y, - ICEIL(acc->fromIntX - x), 0, - ICEIL(acc->fromIntX + x), 0, - def, bounds, acc, mask); + yy = y + acc->fromIntY; + x = tailX(yy, def, bounds, acc); + if (yy == 0.0 && x == -rw - acc->fromIntX) + return; + if (acc->right.valid && boundedLe(yy, bounds->right)) { + rx = x; + lx = -x; + xalt = intersectLine(yy, acc->right); + if (xalt >= -rw - acc->fromIntX && xalt <= rx) + rx = xalt; + n = ICEIL(acc->fromIntX + lx); + if (lw > n) { + if (mask & 2) + newFinalSpan(acc->yorgu - y, acc->xorg + n, acc->xorg + lw); + if (mask & 4) + newFinalSpan(acc->yorgl + y, acc->xorg + n, acc->xorg + lw); + } + n = ICEIL(acc->fromIntX + rx); + if (n > -rw) { + if (mask & 1) + newFinalSpan(acc->yorgu - y, acc->xorg - rw, acc->xorg + n); + if (mask & 8) + newFinalSpan(acc->yorgl + y, acc->xorg - rw, acc->xorg + n); + } + } + arcSpan(y, + ICEIL(acc->fromIntX - x), 0, + ICEIL(acc->fromIntX + x), 0, def, bounds, acc, mask); } } @@ -2982,254 +2814,247 @@ tailSpan ( * very bad. */ -static struct finalSpan **finalSpans = NULL; -static int finalMiny = 0, finalMaxy = -1; -static int finalSize = 0; +static struct finalSpan **finalSpans = NULL; +static int finalMiny = 0, finalMaxy = -1; +static int finalSize = 0; -static int nspans = 0; /* total spans, not just y coords */ +static int nspans = 0; /* total spans, not just y coords */ struct finalSpan { - struct finalSpan *next; - int min, max; /* x values */ + struct finalSpan *next; + int min, max; /* x values */ }; -static struct finalSpan *freeFinalSpans, *tmpFinalSpan; +static struct finalSpan *freeFinalSpans, *tmpFinalSpan; -# define allocFinalSpan() (freeFinalSpans ?\ +#define allocFinalSpan() (freeFinalSpans ?\ ((tmpFinalSpan = freeFinalSpans), \ (freeFinalSpans = freeFinalSpans->next), \ (tmpFinalSpan->next = 0), \ tmpFinalSpan) : \ realAllocSpan ()) -# define SPAN_CHUNK_SIZE 128 +#define SPAN_CHUNK_SIZE 128 struct finalSpanChunk { - struct finalSpan data[SPAN_CHUNK_SIZE]; - struct finalSpanChunk *next; + struct finalSpan data[SPAN_CHUNK_SIZE]; + struct finalSpanChunk *next; }; -static struct finalSpanChunk *chunks; +static struct finalSpanChunk *chunks; static struct finalSpan * -realAllocSpan (void) +realAllocSpan(void) { - struct finalSpanChunk *newChunk; - struct finalSpan *span; - int i; - - newChunk = malloc(sizeof (struct finalSpanChunk)); - if (!newChunk) - return (struct finalSpan *) NULL; - newChunk->next = chunks; - chunks = newChunk; - freeFinalSpans = span = newChunk->data + 1; - for (i = 1; i < SPAN_CHUNK_SIZE-1; i++) { - span->next = span+1; - span++; - } - span->next = 0; - span = newChunk->data; - span->next = 0; - return span; + struct finalSpanChunk *newChunk; + struct finalSpan *span; + int i; + + newChunk = malloc(sizeof(struct finalSpanChunk)); + if (!newChunk) + return (struct finalSpan *) NULL; + newChunk->next = chunks; + chunks = newChunk; + freeFinalSpans = span = newChunk->data + 1; + for (i = 1; i < SPAN_CHUNK_SIZE - 1; i++) { + span->next = span + 1; + span++; + } + span->next = 0; + span = newChunk->data; + span->next = 0; + return span; } static void -disposeFinalSpans (void) +disposeFinalSpans(void) { - struct finalSpanChunk *chunk, *next; - - for (chunk = chunks; chunk; chunk = next) { - next = chunk->next; - free(chunk); - } - chunks = 0; - freeFinalSpans = 0; - free(finalSpans); - finalSpans = 0; + struct finalSpanChunk *chunk, *next; + + for (chunk = chunks; chunk; chunk = next) { + next = chunk->next; + free(chunk); + } + chunks = 0; + freeFinalSpans = 0; + free(finalSpans); + finalSpans = 0; } static void -fillSpans ( - DrawablePtr pDrawable, - GCPtr pGC) +fillSpans(DrawablePtr pDrawable, GCPtr pGC) { - struct finalSpan *span; - DDXPointPtr xSpan; - int *xWidth; - int i; - struct finalSpan **f; - int spany; - DDXPointPtr xSpans; - int *xWidths; - - if (nspans == 0) - return; - xSpan = xSpans = malloc(nspans * sizeof (DDXPointRec)); - xWidth = xWidths = malloc(nspans * sizeof (int)); - if (xSpans && xWidths) - { - i = 0; - f = finalSpans; - for (spany = finalMiny; spany <= finalMaxy; spany++, f++) { - for (span = *f; span; span=span->next) { - if (span->max <= span->min) - continue; - xSpan->x = span->min; - xSpan->y = spany; - ++xSpan; - *xWidth++ = span->max - span->min; - ++i; - } - } - (*pGC->ops->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE); - } - disposeFinalSpans (); - free(xSpans); - free(xWidths); - finalMiny = 0; - finalMaxy = -1; - finalSize = 0; - nspans = 0; + struct finalSpan *span; + DDXPointPtr xSpan; + int *xWidth; + int i; + struct finalSpan **f; + int spany; + DDXPointPtr xSpans; + int *xWidths; + + if (nspans == 0) + return; + xSpan = xSpans = malloc(nspans * sizeof(DDXPointRec)); + xWidth = xWidths = malloc(nspans * sizeof(int)); + if (xSpans && xWidths) { + i = 0; + f = finalSpans; + for (spany = finalMiny; spany <= finalMaxy; spany++, f++) { + for (span = *f; span; span = span->next) { + if (span->max <= span->min) + continue; + xSpan->x = span->min; + xSpan->y = spany; + ++xSpan; + *xWidth++ = span->max - span->min; + ++i; + } + } + (*pGC->ops->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE); + } + disposeFinalSpans(); + free(xSpans); + free(xWidths); + finalMiny = 0; + finalMaxy = -1; + finalSize = 0; + nspans = 0; } -# define SPAN_REALLOC 100 +#define SPAN_REALLOC 100 -# define findSpan(y) ((finalMiny <= (y) && (y) <= finalMaxy) ? \ +#define findSpan(y) ((finalMiny <= (y) && (y) <= finalMaxy) ? \ &finalSpans[(y) - finalMiny] : \ realFindSpan (y)) static struct finalSpan ** -realFindSpan (int y) +realFindSpan(int y) { - struct finalSpan **newSpans; - int newSize, newMiny, newMaxy; - int change; - int i; - - if (y < finalMiny || y > finalMaxy) { - if (!finalSize) { - finalMiny = y; - finalMaxy = y - 1; - } - if (y < finalMiny) - change = finalMiny - y; - else - change = y - finalMaxy; - if (change >= SPAN_REALLOC) - change += SPAN_REALLOC; - else - change = SPAN_REALLOC; - newSize = finalSize + change; - newSpans = malloc(newSize * sizeof (struct finalSpan *)); - if (!newSpans) - return NULL; - newMiny = finalMiny; - newMaxy = finalMaxy; - if (y < finalMiny) - newMiny = finalMiny - change; - else - newMaxy = finalMaxy + change; - if (finalSpans) { - memmove(((char *) newSpans) + (finalMiny-newMiny) * sizeof (struct finalSpan *), - (char *) finalSpans, - finalSize * sizeof (struct finalSpan *)); - free(finalSpans); - } - if ((i = finalMiny - newMiny) > 0) - memset((char *)newSpans, 0, i * sizeof (struct finalSpan *)); - if ((i = newMaxy - finalMaxy) > 0) - memset((char *)(newSpans + newSize - i), 0, - i * sizeof (struct finalSpan *)); - finalSpans = newSpans; - finalMaxy = newMaxy; - finalMiny = newMiny; - finalSize = newSize; - } - return &finalSpans[y - finalMiny]; + struct finalSpan **newSpans; + int newSize, newMiny, newMaxy; + int change; + int i; + + if (y < finalMiny || y > finalMaxy) { + if (!finalSize) { + finalMiny = y; + finalMaxy = y - 1; + } + if (y < finalMiny) + change = finalMiny - y; + else + change = y - finalMaxy; + if (change >= SPAN_REALLOC) + change += SPAN_REALLOC; + else + change = SPAN_REALLOC; + newSize = finalSize + change; + newSpans = malloc(newSize * sizeof(struct finalSpan *)); + if (!newSpans) + return NULL; + newMiny = finalMiny; + newMaxy = finalMaxy; + if (y < finalMiny) + newMiny = finalMiny - change; + else + newMaxy = finalMaxy + change; + if (finalSpans) { + memmove(((char *) newSpans) + + (finalMiny - newMiny) * sizeof(struct finalSpan *), + (char *) finalSpans, + finalSize * sizeof(struct finalSpan *)); + free(finalSpans); + } + if ((i = finalMiny - newMiny) > 0) + memset((char *) newSpans, 0, i * sizeof(struct finalSpan *)); + if ((i = newMaxy - finalMaxy) > 0) + memset((char *) (newSpans + newSize - i), 0, + i * sizeof(struct finalSpan *)); + finalSpans = newSpans; + finalMaxy = newMaxy; + finalMiny = newMiny; + finalSize = newSize; + } + return &finalSpans[y - finalMiny]; } static void -newFinalSpan ( - int y, - int xmin, - int xmax) +newFinalSpan(int y, int xmin, int xmax) { - struct finalSpan *x; - struct finalSpan **f; - struct finalSpan *oldx; - struct finalSpan *prev; - - f = findSpan (y); - if (!f) - return; - oldx = 0; - for (;;) { - prev = 0; - for (x = *f; x; x=x->next) { - if (x == oldx) { - prev = x; - continue; - } - if (x->min <= xmax && xmin <= x->max) { - if (oldx) { - oldx->min = min (x->min, xmin); - oldx->max = max (x->max, xmax); - if (prev) - prev->next = x->next; - else - *f = x->next; - --nspans; - } else { - x->min = min (x->min, xmin); - x->max = max (x->max, xmax); - oldx = x; - } - xmin = oldx->min; - xmax = oldx->max; - break; - } - prev = x; - } - if (!x) - break; - } - if (!oldx) { - x = allocFinalSpan (); - if (x) - { - x->min = xmin; - x->max = xmax; - x->next = *f; - *f = x; - ++nspans; - } - } + struct finalSpan *x; + struct finalSpan **f; + struct finalSpan *oldx; + struct finalSpan *prev; + + f = findSpan(y); + if (!f) + return; + oldx = 0; + for (;;) { + prev = 0; + for (x = *f; x; x = x->next) { + if (x == oldx) { + prev = x; + continue; + } + if (x->min <= xmax && xmin <= x->max) { + if (oldx) { + oldx->min = min(x->min, xmin); + oldx->max = max(x->max, xmax); + if (prev) + prev->next = x->next; + else + *f = x->next; + --nspans; + } + else { + x->min = min(x->min, xmin); + x->max = max(x->max, xmax); + oldx = x; + } + xmin = oldx->min; + xmax = oldx->max; + break; + } + prev = x; + } + if (!x) + break; + } + if (!oldx) { + x = allocFinalSpan(); + if (x) { + x->min = xmin; + x->max = xmax; + x->next = *f; + *f = x; + ++nspans; + } + } } static void -mirrorSppPoint ( - int quadrant, - SppPointPtr sppPoint) +mirrorSppPoint(int quadrant, SppPointPtr sppPoint) { - switch (quadrant) { - case 0: - break; - case 1: - sppPoint->x = -sppPoint->x; - break; - case 2: - sppPoint->x = -sppPoint->x; - sppPoint->y = -sppPoint->y; - break; - case 3: - sppPoint->y = -sppPoint->y; - break; - } - /* - * and translate to X coordinate system - */ - sppPoint->y = -sppPoint->y; + switch (quadrant) { + case 0: + break; + case 1: + sppPoint->x = -sppPoint->x; + break; + case 2: + sppPoint->x = -sppPoint->x; + sppPoint->y = -sppPoint->y; + break; + case 3: + sppPoint->y = -sppPoint->y; + break; + } + /* + * and translate to X coordinate system + */ + sppPoint->y = -sppPoint->y; } /* @@ -3241,350 +3066,337 @@ mirrorSppPoint ( */ static void -drawArc ( - xArc *tarc, - int l, - int a0, - int a1, - miArcFacePtr right, - miArcFacePtr left) /* save end line points */ -{ - struct arc_def def; - struct accelerators acc; - int startq, endq, curq; - int rightq, leftq = 0, righta = 0, lefta = 0; - miArcFacePtr passRight, passLeft; - int q0 = 0, q1 = 0, mask; - struct band { - int a0, a1; - int mask; - } band[5], sweep[20]; - int bandno, sweepno; - int i, j; - int flipRight = 0, flipLeft = 0; - int copyEnd = 0; - miArcSpanData *spdata; - - spdata = miComputeWideEllipse(l, tarc); - if (!spdata) - return; - - if (a1 < a0) - a1 += 360 * 64; - startq = a0 / (90 * 64); - if (a0 == a1) - endq = startq; - else - endq = (a1-1) / (90 * 64); - bandno = 0; - curq = startq; - rightq = -1; - for (;;) { - switch (curq) { - case 0: - if (a0 > 90 * 64) - q0 = 0; - else - q0 = a0; - if (a1 < 360 * 64) - q1 = min (a1, 90 * 64); - else - q1 = 90 * 64; - if (curq == startq && a0 == q0 && rightq < 0) { - righta = q0; - rightq = curq; - } - if (curq == endq && a1 == q1) { - lefta = q1; - leftq = curq; - } - break; - case 1: - if (a1 < 90 * 64) - q0 = 0; - else - q0 = 180 * 64 - min (a1, 180 * 64); - if (a0 > 180 * 64) - q1 = 90 * 64; - else - q1 = 180 * 64 - max (a0, 90 * 64); - if (curq == startq && 180 * 64 - a0 == q1) { - righta = q1; - rightq = curq; - } - if (curq == endq && 180 * 64 - a1 == q0) { - lefta = q0; - leftq = curq; - } - break; - case 2: - if (a0 > 270 * 64) - q0 = 0; - else - q0 = max (a0, 180 * 64) - 180 * 64; - if (a1 < 180 * 64) - q1 = 90 * 64; - else - q1 = min (a1, 270 * 64) - 180 * 64; - if (curq == startq && a0 - 180*64 == q0) { - righta = q0; - rightq = curq; - } - if (curq == endq && a1 - 180 * 64 == q1) { - lefta = q1; - leftq = curq; - } - break; - case 3: - if (a1 < 270 * 64) - q0 = 0; - else - q0 = 360 * 64 - min (a1, 360 * 64); - q1 = 360 * 64 - max (a0, 270 * 64); - if (curq == startq && 360 * 64 - a0 == q1) { - righta = q1; - rightq = curq; - } - if (curq == endq && 360 * 64 - a1 == q0) { - lefta = q0; - leftq = curq; - } - break; - } - band[bandno].a0 = q0; - band[bandno].a1 = q1; - band[bandno].mask = 1 << curq; - bandno++; - if (curq == endq) - break; - curq++; - if (curq == 4) { - a0 = 0; - a1 -= 360 * 64; - curq = 0; - endq -= 4; - } - } - sweepno = 0; - for (;;) { - q0 = 90 * 64; - mask = 0; - /* - * find left-most point - */ - for (i = 0; i < bandno; i++) - if (band[i].a0 <= q0) { - q0 = band[i].a0; - q1 = band[i].a1; - mask = band[i].mask; - } - if (!mask) - break; - /* - * locate next point of change - */ - for (i = 0; i < bandno; i++) - if (!(mask & band[i].mask)) { - if (band[i].a0 == q0) { - if (band[i].a1 < q1) - q1 = band[i].a1; - mask |= band[i].mask; - } else if (band[i].a0 < q1) - q1 = band[i].a0; - } - /* - * create a new sweep - */ - sweep[sweepno].a0 = q0; - sweep[sweepno].a1 = q1; - sweep[sweepno].mask = mask; - sweepno++; - /* - * subtract the sweep from the affected bands - */ - for (i = 0; i < bandno; i++) - if (band[i].a0 == q0) { - band[i].a0 = q1; - /* - * check if this band is empty - */ - if (band[i].a0 == band[i].a1) - band[i].a1 = band[i].a0 = 90 * 64 + 1; - } - } - computeAcc (tarc, l, &def, &acc); - for (j = 0; j < sweepno; j++) { - mask = sweep[j].mask; - passRight = passLeft = 0; - if (mask & (1 << rightq)) { - if (sweep[j].a0 == righta) - passRight = right; - else if (sweep[j].a1 == righta) { - passLeft = right; - flipRight = 1; - } - } - if (mask & (1 << leftq)) { - if (sweep[j].a1 == lefta) - { - if (passLeft) - copyEnd = 1; - passLeft = left; - } - else if (sweep[j].a0 == lefta) { - if (passRight) - copyEnd = 1; - passRight = left; - flipLeft = 1; - } - } - drawQuadrant (&def, &acc, sweep[j].a0, sweep[j].a1, mask, - passRight, passLeft, spdata); - } - /* - * when copyEnd is set, both ends of the arc were computed - * at the same time; drawQuadrant only takes one end though, - * so the left end will be the only one holding the data. Copy - * it from there. - */ - if (copyEnd) - *right = *left; - /* - * mirror the coordinates generated for the - * faces of the arc - */ - if (right) { - mirrorSppPoint (rightq, &right->clock); - mirrorSppPoint (rightq, &right->center); - mirrorSppPoint (rightq, &right->counterClock); - if (flipRight) { - SppPointRec temp; - - temp = right->clock; - right->clock = right->counterClock; - right->counterClock = temp; - } - } - if (left) { - mirrorSppPoint (leftq, &left->counterClock); - mirrorSppPoint (leftq, &left->center); - mirrorSppPoint (leftq, &left->clock); - if (flipLeft) { - SppPointRec temp; - - temp = left->clock; - left->clock = left->counterClock; - left->counterClock = temp; - } - } - free(spdata); +drawArc(xArc * tarc, + int l, int a0, int a1, miArcFacePtr right, miArcFacePtr left) +{ /* save end line points */ + struct arc_def def; + struct accelerators acc; + int startq, endq, curq; + int rightq, leftq = 0, righta = 0, lefta = 0; + miArcFacePtr passRight, passLeft; + int q0 = 0, q1 = 0, mask; + struct band { + int a0, a1; + int mask; + } band[5], sweep[20]; + int bandno, sweepno; + int i, j; + int flipRight = 0, flipLeft = 0; + int copyEnd = 0; + miArcSpanData *spdata; + + spdata = miComputeWideEllipse(l, tarc); + if (!spdata) + return; + + if (a1 < a0) + a1 += 360 * 64; + startq = a0 / (90 * 64); + if (a0 == a1) + endq = startq; + else + endq = (a1 - 1) / (90 * 64); + bandno = 0; + curq = startq; + rightq = -1; + for (;;) { + switch (curq) { + case 0: + if (a0 > 90 * 64) + q0 = 0; + else + q0 = a0; + if (a1 < 360 * 64) + q1 = min(a1, 90 * 64); + else + q1 = 90 * 64; + if (curq == startq && a0 == q0 && rightq < 0) { + righta = q0; + rightq = curq; + } + if (curq == endq && a1 == q1) { + lefta = q1; + leftq = curq; + } + break; + case 1: + if (a1 < 90 * 64) + q0 = 0; + else + q0 = 180 * 64 - min(a1, 180 * 64); + if (a0 > 180 * 64) + q1 = 90 * 64; + else + q1 = 180 * 64 - max(a0, 90 * 64); + if (curq == startq && 180 * 64 - a0 == q1) { + righta = q1; + rightq = curq; + } + if (curq == endq && 180 * 64 - a1 == q0) { + lefta = q0; + leftq = curq; + } + break; + case 2: + if (a0 > 270 * 64) + q0 = 0; + else + q0 = max(a0, 180 * 64) - 180 * 64; + if (a1 < 180 * 64) + q1 = 90 * 64; + else + q1 = min(a1, 270 * 64) - 180 * 64; + if (curq == startq && a0 - 180 * 64 == q0) { + righta = q0; + rightq = curq; + } + if (curq == endq && a1 - 180 * 64 == q1) { + lefta = q1; + leftq = curq; + } + break; + case 3: + if (a1 < 270 * 64) + q0 = 0; + else + q0 = 360 * 64 - min(a1, 360 * 64); + q1 = 360 * 64 - max(a0, 270 * 64); + if (curq == startq && 360 * 64 - a0 == q1) { + righta = q1; + rightq = curq; + } + if (curq == endq && 360 * 64 - a1 == q0) { + lefta = q0; + leftq = curq; + } + break; + } + band[bandno].a0 = q0; + band[bandno].a1 = q1; + band[bandno].mask = 1 << curq; + bandno++; + if (curq == endq) + break; + curq++; + if (curq == 4) { + a0 = 0; + a1 -= 360 * 64; + curq = 0; + endq -= 4; + } + } + sweepno = 0; + for (;;) { + q0 = 90 * 64; + mask = 0; + /* + * find left-most point + */ + for (i = 0; i < bandno; i++) + if (band[i].a0 <= q0) { + q0 = band[i].a0; + q1 = band[i].a1; + mask = band[i].mask; + } + if (!mask) + break; + /* + * locate next point of change + */ + for (i = 0; i < bandno; i++) + if (!(mask & band[i].mask)) { + if (band[i].a0 == q0) { + if (band[i].a1 < q1) + q1 = band[i].a1; + mask |= band[i].mask; + } + else if (band[i].a0 < q1) + q1 = band[i].a0; + } + /* + * create a new sweep + */ + sweep[sweepno].a0 = q0; + sweep[sweepno].a1 = q1; + sweep[sweepno].mask = mask; + sweepno++; + /* + * subtract the sweep from the affected bands + */ + for (i = 0; i < bandno; i++) + if (band[i].a0 == q0) { + band[i].a0 = q1; + /* + * check if this band is empty + */ + if (band[i].a0 == band[i].a1) + band[i].a1 = band[i].a0 = 90 * 64 + 1; + } + } + computeAcc(tarc, l, &def, &acc); + for (j = 0; j < sweepno; j++) { + mask = sweep[j].mask; + passRight = passLeft = 0; + if (mask & (1 << rightq)) { + if (sweep[j].a0 == righta) + passRight = right; + else if (sweep[j].a1 == righta) { + passLeft = right; + flipRight = 1; + } + } + if (mask & (1 << leftq)) { + if (sweep[j].a1 == lefta) { + if (passLeft) + copyEnd = 1; + passLeft = left; + } + else if (sweep[j].a0 == lefta) { + if (passRight) + copyEnd = 1; + passRight = left; + flipLeft = 1; + } + } + drawQuadrant(&def, &acc, sweep[j].a0, sweep[j].a1, mask, + passRight, passLeft, spdata); + } + /* + * when copyEnd is set, both ends of the arc were computed + * at the same time; drawQuadrant only takes one end though, + * so the left end will be the only one holding the data. Copy + * it from there. + */ + if (copyEnd) + *right = *left; + /* + * mirror the coordinates generated for the + * faces of the arc + */ + if (right) { + mirrorSppPoint(rightq, &right->clock); + mirrorSppPoint(rightq, &right->center); + mirrorSppPoint(rightq, &right->counterClock); + if (flipRight) { + SppPointRec temp; + + temp = right->clock; + right->clock = right->counterClock; + right->counterClock = temp; + } + } + if (left) { + mirrorSppPoint(leftq, &left->counterClock); + mirrorSppPoint(leftq, &left->center); + mirrorSppPoint(leftq, &left->clock); + if (flipLeft) { + SppPointRec temp; + + temp = left->clock; + left->clock = left->counterClock; + left->counterClock = temp; + } + } + free(spdata); } static void -drawQuadrant ( - struct arc_def *def, - struct accelerators *acc, - int a0, - int a1, - int mask, - miArcFacePtr right, - miArcFacePtr left, - miArcSpanData *spdata) +drawQuadrant(struct arc_def *def, + struct accelerators *acc, + int a0, + int a1, + int mask, + miArcFacePtr right, miArcFacePtr left, miArcSpanData * spdata) { - struct arc_bound bound; - double yy, x, xalt; - int y, miny, maxy; - int n; - miArcSpan *span; - - def->a0 = ((double) a0) / 64.0; - def->a1 = ((double) a1) / 64.0; - computeBound (def, &bound, acc, right, left); - yy = bound.inner.min; - if (bound.outer.min < yy) - yy = bound.outer.min; - miny = ICEIL(yy - acc->fromIntY); - yy = bound.inner.max; - if (bound.outer.max > yy) - yy = bound.outer.max; - maxy = floor(yy - acc->fromIntY); - y = spdata->k; - span = spdata->spans; - if (spdata->top) - { - if (a1 == 90 * 64 && (mask & 1)) - newFinalSpan (acc->yorgu - y - 1, acc->xorg, acc->xorg + 1); - span++; - } - for (n = spdata->count1; --n >= 0; ) - { - if (y < miny) - return; - if (y <= maxy) { - arcSpan (y, - span->lx, -span->lx, 0, span->lx + span->lw, - def, &bound, acc, mask); - if (span->rw + span->rx) - tailSpan (y, -span->rw, -span->rx, def, &bound, acc, mask); - } - y--; - span++; - } - if (y < miny) - return; - if (spdata->hole) - { - if (y <= maxy) - arcSpan (y, 0, 0, 0, 1, def, &bound, acc, mask & 0xc); - } - for (n = spdata->count2; --n >= 0; ) - { - if (y < miny) - return; - if (y <= maxy) - arcSpan (y, span->lx, span->lw, span->rx, span->rw, - def, &bound, acc, mask); - y--; - span++; - } - if (spdata->bot && miny <= y && y <= maxy) - { - n = mask; - if (y == miny) - n &= 0xc; - if (span->rw <= 0) { - arcSpan0 (span->lx, -span->lx, 0, span->lx + span->lw, - def, &bound, acc, n); - if (span->rw + span->rx) - tailSpan (y, -span->rw, -span->rx, def, &bound, acc, n); - } - else - arcSpan0 (span->lx, span->lw, span->rx, span->rw, - def, &bound, acc, n); - y--; - } - while (y >= miny) { - yy = y + acc->fromIntY; - if (def->w == def->h) { - xalt = def->w - def->l; - x = -sqrt(xalt * xalt - yy * yy); - } else { - x = tailX(yy, def, &bound, acc); - if (acc->left.valid && boundedLe (yy, bound.left)) { - xalt = intersectLine (yy, acc->left); - if (xalt < x) - x = xalt; - } - if (acc->right.valid && boundedLe (yy, bound.right)) { - xalt = intersectLine (yy, acc->right); - if (xalt < x) - x = xalt; - } - } - arcSpan (y, - ICEIL(acc->fromIntX - x), 0, - ICEIL(acc->fromIntX + x), 0, - def, &bound, acc, mask); - y--; - } + struct arc_bound bound; + double yy, x, xalt; + int y, miny, maxy; + int n; + miArcSpan *span; + + def->a0 = ((double) a0) / 64.0; + def->a1 = ((double) a1) / 64.0; + computeBound(def, &bound, acc, right, left); + yy = bound.inner.min; + if (bound.outer.min < yy) + yy = bound.outer.min; + miny = ICEIL(yy - acc->fromIntY); + yy = bound.inner.max; + if (bound.outer.max > yy) + yy = bound.outer.max; + maxy = floor(yy - acc->fromIntY); + y = spdata->k; + span = spdata->spans; + if (spdata->top) { + if (a1 == 90 * 64 && (mask & 1)) + newFinalSpan(acc->yorgu - y - 1, acc->xorg, acc->xorg + 1); + span++; + } + for (n = spdata->count1; --n >= 0;) { + if (y < miny) + return; + if (y <= maxy) { + arcSpan(y, + span->lx, -span->lx, 0, span->lx + span->lw, + def, &bound, acc, mask); + if (span->rw + span->rx) + tailSpan(y, -span->rw, -span->rx, def, &bound, acc, mask); + } + y--; + span++; + } + if (y < miny) + return; + if (spdata->hole) { + if (y <= maxy) + arcSpan(y, 0, 0, 0, 1, def, &bound, acc, mask & 0xc); + } + for (n = spdata->count2; --n >= 0;) { + if (y < miny) + return; + if (y <= maxy) + arcSpan(y, span->lx, span->lw, span->rx, span->rw, + def, &bound, acc, mask); + y--; + span++; + } + if (spdata->bot && miny <= y && y <= maxy) { + n = mask; + if (y == miny) + n &= 0xc; + if (span->rw <= 0) { + arcSpan0(span->lx, -span->lx, 0, span->lx + span->lw, + def, &bound, acc, n); + if (span->rw + span->rx) + tailSpan(y, -span->rw, -span->rx, def, &bound, acc, n); + } + else + arcSpan0(span->lx, span->lw, span->rx, span->rw, + def, &bound, acc, n); + y--; + } + while (y >= miny) { + yy = y + acc->fromIntY; + if (def->w == def->h) { + xalt = def->w - def->l; + x = -sqrt(xalt * xalt - yy * yy); + } + else { + x = tailX(yy, def, &bound, acc); + if (acc->left.valid && boundedLe(yy, bound.left)) { + xalt = intersectLine(yy, acc->left); + if (xalt < x) + x = xalt; + } + if (acc->right.valid && boundedLe(yy, bound.right)) { + xalt = intersectLine(yy, acc->right); + if (xalt < x) + x = xalt; + } + } + arcSpan(y, + ICEIL(acc->fromIntX - x), 0, + ICEIL(acc->fromIntX + x), 0, def, &bound, acc, mask); + y--; + } } |