summaryrefslogtreecommitdiff
path: root/xserver/mi/miarc.c
diff options
context:
space:
mode:
Diffstat (limited to 'xserver/mi/miarc.c')
-rw-r--r--xserver/mi/miarc.c426
1 files changed, 216 insertions, 210 deletions
diff --git a/xserver/mi/miarc.c b/xserver/mi/miarc.c
index 2588ee48a..71df4ab64 100644
--- a/xserver/mi/miarc.c
+++ b/xserver/mi/miarc.c
@@ -215,10 +215,21 @@ typedef struct _miPolyArc {
miArcJoinPtr joins;
} miPolyArcRec, *miPolyArcPtr;
+typedef struct {
+ short lx, lw, rx, rw;
+} miArcSpan;
+
+typedef struct {
+ miArcSpan *spans;
+ int count1, count2, k;
+ char top, bot, hole;
+} miArcSpanData;
+
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 miArcSpanData *drawArc(xArc * tarc, int l, int a0, int a1,
+ miArcFacePtr right, miArcFacePtr left,
+ miArcSpanData *spdata);
static void drawZeroArc(DrawablePtr pDraw, GCPtr pGC, xArc * tarc, int lw,
miArcFacePtr left, miArcFacePtr right);
static void miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft,
@@ -244,9 +255,9 @@ static int miGetArcPts(SppArcPtr parc, int cpt, SppPointPtr * ppPts);
* 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)
+static miArcSpanData *
+miArcSegment(DrawablePtr pDraw, GCPtr pGC, xArc tarc, miArcFacePtr right,
+ miArcFacePtr left, miArcSpanData *spdata)
{
int l = pGC->lineWidth;
int a0, a1, startAngle, endAngle;
@@ -257,7 +268,7 @@ miArcSegment(DrawablePtr pDraw,
if (tarc.width == 0 || tarc.height == 0) {
drawZeroArc(pDraw, pGC, &tarc, l, left, right);
- return;
+ return spdata;
}
if (pGC->miTranslate) {
@@ -298,7 +309,7 @@ miArcSegment(DrawablePtr pDraw,
endAngle = FULLCIRCLE;
}
- drawArc(&tarc, l, startAngle, endAngle, right, left);
+ return drawArc(&tarc, l, startAngle, endAngle, right, left, spdata);
}
/*
@@ -364,16 +375,6 @@ correspond to the inner and outer boundaries.
*/
-typedef struct {
- short lx, lw, rx, rw;
-} miArcSpan;
-
-typedef struct {
- miArcSpan *spans;
- int count1, count2, k;
- char top, bot, hole;
-} miArcSpanData;
-
static void drawQuadrant(struct arc_def *def, struct accelerators *acc,
int a0, int a1, int mask, miArcFacePtr right,
miArcFacePtr left, miArcSpanData * spdata);
@@ -894,7 +895,7 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
int xMin, xMax, yMin, yMax;
int pixmapWidth = 0, pixmapHeight = 0;
int xOrg = 0, yOrg = 0;
- int width;
+ int width = pGC->lineWidth;
Bool fTricky;
DrawablePtr pDrawTo;
CARD32 fg, bg;
@@ -904,210 +905,215 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
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);
+ for (i = narcs, parc = parcs; --i >= 0; parc++) {
+ miArcSpanData *spdata;
+ spdata = miArcSegment(pDraw, pGC, *parc, NULL, NULL, NULL);
+ free(spdata);
+ }
fillSpans(pDraw, pGC);
+ return;
}
- 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))
+ if ((pGC->lineStyle == LineSolid) && narcs) {
+ while (parcs->width && parcs->height &&
+ (parcs->angle2 >= FULLCIRCLE || parcs->angle2 <= -FULLCIRCLE)) {
+ miFillWideEllipse(pDraw, pGC, parcs);
+ if (!--narcs)
return;
+ parcs++;
+ }
+ }
- 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 */
+ /* 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;
- 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);
- }
+ for (i = narcs, parc = parcs; --i >= 0; parc++) {
+ parc->x -= xOrg;
+ parc->y -= yOrg;
+ }
+ if (pGC->miTranslate) {
+ xOrg += pDraw->x;
+ yOrg += pDraw->y;
+ }
- /* 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);
+ /* 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 bitmap 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 */
+ fg = pGC->fgPixel;
+ bg = pGC->bgPixel;
- polyArcs = miComputeArcs(parcs, narcs, pGC);
+ /* the protocol sez these don't cause color changes */
+ if ((pGC->fillStyle == FillTiled) ||
+ (pGC->fillStyle == FillOpaqueStippled))
+ bg = fg;
- if (!polyArcs) {
- if (fTricky) {
- (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo);
- FreeScratchGC(pGCTo);
- }
- return;
- }
+ polyArcs = miComputeArcs(parcs, narcs, pGC);
+ if (!polyArcs)
+ goto out;
- cap[0] = cap[1] = 0;
- join[0] = join[1] = 0;
- for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0);
- iphase >= 0; iphase--) {
- ChangeGCVal gcval;
+ cap[0] = cap[1] = 0;
+ join[0] = join[1] = 0;
+ for (iphase = (pGC->lineStyle == LineDoubleDash); iphase >= 0; iphase--) {
+ miArcSpanData *spdata = NULL;
+ xArc lastArc;
+ 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);
+ 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];
+ if (spdata) {
+ if (lastArc.width != arcData->arc.width ||
+ lastArc.height != arcData->arc.height) {
+ free(spdata);
+ spdata = NULL;
+ }
}
- 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);
- }
+ memcpy(&lastArc, &arcData->arc, sizeof(xArc));
+ spdata = miArcSegment(pDrawTo, pGCTo, arcData->arc,
+ &arcData->bounds[RIGHT_END],
+ &arcData->bounds[LEFT_END], spdata);
+ 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);
+ free(spdata);
+ spdata = NULL;
+ }
+ miFreeArcs(polyArcs, pGC);
- if (fTricky) {
- (*pGCTo->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo);
- FreeScratchGC(pGCTo);
- }
+out:
+ if (fTricky) {
+ (*pGCTo->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo);
+ FreeScratchGC(pGCTo);
}
}
@@ -3250,9 +3256,9 @@ mirrorSppPoint(int quadrant, SppPointPtr sppPoint)
* first quadrant.
*/
-static void
-drawArc(xArc * tarc,
- int l, int a0, int a1, miArcFacePtr right, miArcFacePtr left)
+static miArcSpanData *
+drawArc(xArc * tarc, int l, int a0, int a1, miArcFacePtr right,
+ miArcFacePtr left, miArcSpanData *spdata)
{ /* save end line points */
struct arc_def def;
struct accelerators acc;
@@ -3268,11 +3274,11 @@ drawArc(xArc * tarc,
int i, j;
int flipRight = 0, flipLeft = 0;
int copyEnd = 0;
- miArcSpanData *spdata;
- spdata = miComputeWideEllipse(l, tarc);
if (!spdata)
- return;
+ spdata = miComputeWideEllipse(l, tarc);
+ if (!spdata)
+ return NULL;
if (a1 < a0)
a1 += 360 * 64;
@@ -3482,7 +3488,7 @@ drawArc(xArc * tarc,
left->counterClock = temp;
}
}
- free(spdata);
+ return spdata;
}
static void