📄 miarc.c
字号:
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 doubletailX(K, def, bounds, acc) 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; double A, T, b, d, x, y, t, hepp, hepm; int flip, solution; double xs[2]; double *xp; w = def->w; h = def->h; r = def->l; rs = r * r; Hs = acc->h2; WH = -acc->h2mw2; Nk = def->w * r; Vk = (Nk * Hs) / (WH + WH); 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; } Fk = Hf / WH; hepp = h + EPSILON; hepm = h - EPSILON; N = (K * K + Nk) / 6.0; Nc = N * N * N; Vr = Vk * K; xp = xs; xs[0] = 0.0; 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; 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; } } 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) *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]; } return xs[0];}static miArcSpanData *miComputeWideEllipse(lw, parc, mustFree) int lw; register xArc *parc; Bool *mustFree;{ register miArcSpanData *spdata; register arcCacheRec *cent, *lruent; register int k; arcCacheRec fakeent; if (!lw) lw = 1; if (parc->height <= 1500) { *mustFree = FALSE; cent = lastCacheHit; if (cent->lw == lw && cent->width == parc->width && cent->height == parc->height) { cent->lrustamp = ++lrustamp; return cent->spdata; } lruent = &arcCache[0]; for (k = CACHESIZE, cent = lruent; --k >= 0; cent++) { if (cent->lw == lw && cent->width == parc->width && cent->height == parc->height) { cent->lrustamp = ++lrustamp; lastCacheHit = cent; return cent->spdata; } if (cent->lrustamp < lruent->lrustamp) lruent = cent; } if (!cacheType) { cacheType = CreateNewResourceType(miFreeArcCache); (void) AddResource(FakeClientID(0), cacheType, NULL); } } else { lruent = &fakeent; lruent->spdata = NULL; *mustFree = TRUE; } k = (parc->height >> 1) + ((lw - 1) >> 1); spdata = lruent->spdata; if (!spdata || spdata->k != k) { if (spdata) xfree(spdata); spdata = (miArcSpanData *)xalloc(sizeof(miArcSpanData) + sizeof(miArcSpan) * (k + 2)); lruent->spdata = spdata; if (!spdata) { lruent->lrustamp = 0; lruent->lw = 0; return spdata; } spdata->spans = (miArcSpan *)(spdata + 1); spdata->k = k; } spdata->top = !(lw & 1) && !(parc->width & 1); spdata->bot = !(parc->height & 1); lruent->lrustamp = ++lrustamp; lruent->lw = lw; lruent->width = parc->width; lruent->height = parc->height; if (lruent != &fakeent) lastCacheHit = lruent; if (parc->width == parc->height) miComputeCircleSpans(lw, parc, spdata); else miComputeEllipseSpans(lw, parc, spdata); return spdata;}static voidmiFillWideEllipse(pDraw, pGC, parc) DrawablePtr pDraw; GCPtr pGC; xArc *parc;{ DDXPointPtr points; register DDXPointPtr pts; int *widths; register int *wids; miArcSpanData *spdata; Bool mustFree; register miArcSpan *span; register int xorg, yorgu, yorgl; register int n; yorgu = parc->height + pGC->lineWidth; n = (sizeof(int) * 2) * yorgu; widths = (int *)ALLOCATE_LOCAL(n + (sizeof(DDXPointRec) * 2) * yorgu); if (!widths) return; points = (DDXPointPtr)((char *)widths + n); spdata = miComputeWideEllipse((int)pGC->lineWidth, parc, &mustFree); if (!spdata) { DEALLOCATE_LOCAL(widths); return; } pts = points; wids = widths; span = spdata->spans; 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; } 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 (mustFree) xfree(spdata); (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); DEALLOCATE_LOCAL(widths);}/* * miPolyArc strategy: * * If arc is zero width and solid, we don't have to worry about the rasterop * or join styles. For wide solid circles, we use a fast integer algorithm. * For wide solid ellipses, we use special case floating point code. * Otherwise, we set up pDrawTo and pGCTo according to the rasterop, then * draw using pGCTo and pDrawTo. If the raster-op was "tricky," that is, * if it involves the destination, then we use PushPixels to move the bits * from the scratch drawable to pDraw. (See the wide line code for a * fuller explanation of this.) */voidmiPolyArc(pDraw, pGC, narcs, parcs) DrawablePtr pDraw; GCPtr pGC; int narcs; xArc *parcs;{ register int i; xArc *parc; int xMin, xMax, yMin, yMax; int pixmapWidth, pixmapHeight; int xOrg, yOrg; int width; Bool fTricky; DrawablePtr pDrawTo; CARD32 fg, bg; GCPtr pGCTo; miPolyArcPtr polyArcs; 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -