diff options
Diffstat (limited to 'xserver/mi/miarc.c')
-rw-r--r-- | xserver/mi/miarc.c | 426 |
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 |