gfx.cc
来自「source code: Covert TXT to PDF」· CC 代码 · 共 2,586 行 · 第 1/5 页
CC
2,586 行
} if (k == nComps) { break; } k = (i + j) / 2; ta[k] = 0.5 * (ta[i] + ta[j]); next[i] = k; next[k] = j; j = k; } // use the average of the colors of the two sides of the region for (k = 0; k < nComps; ++k) { color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]); } // compute the coordinates of the point on the t axis; then // compute the intersection of the perpendicular line with the // bounding box tx = x0 + ta[j] * dx; ty = y0 + ta[j] * dy; if (dx == 0 && dy == 0) { sMin = sMax = 0; } if (dx == 0) { sMin = (xMin - tx) / -dy; sMax = (xMax - tx) / -dy; if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } } else if (dy == 0) { sMin = (yMin - ty) / dx; sMax = (yMax - ty) / dx; if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } } else { s[0] = (yMin - ty) / dx; s[1] = (yMax - ty) / dx; s[2] = (xMin - tx) / -dy; s[3] = (xMax - tx) / -dy; for (j = 0; j < 3; ++j) { kk = j; for (k = j + 1; k < 4; ++k) { if (s[k] < s[kk]) { kk = k; } } tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; } sMin = s[1]; sMax = s[2]; } ux1 = tx - sMin * dy; uy1 = ty + sMin * dx; vx1 = tx - sMax * dy; vy1 = ty + sMax * dx; // set the color state->setFillColor(&color0); out->updateFillColor(state); // fill the region state->moveTo(ux0, uy0); state->lineTo(vx0, vy0); state->lineTo(vx1, vy1); state->lineTo(ux1, uy1); state->closePath(); out->fill(state); state->clearPath(); // set up for next region ux0 = ux1; uy0 = uy1; vx0 = vx1; vy0 = vy1; color0 = color1; i = next[i]; }}void Gfx::doRadialShFill(GfxRadialShading *shading) { double sMin, sMax, xMin, yMin, xMax, yMax; double x0, y0, r0, x1, y1, r1, t0, t1; int nComps; GfxColor colorA, colorB; double xa, ya, xb, yb, ra, rb; double ta, tb, sa, sb; int ia, ib, k, n; double *ctm; double angle, t; // get the shading info shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); t0 = shading->getDomain0(); t1 = shading->getDomain1(); nComps = shading->getColorSpace()->getNComps(); // compute the (possibly extended) s range sMin = 0; sMax = 1; if (shading->getExtend0()) { if (r0 < r1) { // extend the smaller end sMin = -r0 / (r1 - r0); } else { // extend the larger end //~ this computes the diagonal of the bounding box -- we should //~ really compute the intersection of the moving/expanding //~ circles with each of the four corners and look for the max //~ radius state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); sMin = (sqrt((xMax - xMin) * (xMax - xMin) + (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0); if (sMin > 0) { sMin = 0; } else if (sMin < -20) { // sanity check sMin = -20; } } } if (shading->getExtend1()) { if (r1 < r0) { // extend the smaller end sMax = -r0 / (r1 - r0); } else if (r1 > r0) { // extend the larger end state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); sMax = (sqrt((xMax - xMin) * (xMax - xMin) + (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0); if (sMax < 1) { sMin = 1; } else if (sMax > 20) { // sanity check sMax = 20; } } } // compute the number of steps into which circles must be divided to // achieve a curve flatness of 0.1 pixel in device space for the // largest circle (note that "device space" is 72 dpi when generating // PostScript, hence the relatively small 0.1 pixel accuracy) ctm = state->getCTM(); t = fabs(ctm[0]); if (fabs(ctm[1]) > t) { t = fabs(ctm[1]); } if (fabs(ctm[2]) > t) { t = fabs(ctm[2]); } if (fabs(ctm[3]) > t) { t = fabs(ctm[3]); } if (r0 > r1) { t *= r0; } else { t *= r1; } if (t < 1) { n = 3; } else { n = (int)(M_PI / acos(1 - 0.1 / t)); if (n < 3) { n = 3; } else if (n > 200) { n = 200; } } // Traverse the t axis and do the shading. // // This generates and fills a series of rings. Each ring is defined // by two circles: // sa, ta, xa, ya, ra, colorA // sb, tb, xb, yb, rb, colorB // // The s/t axis is divided into radialMaxSplits parts; these parts // are combined as much as possible while respecting the // radialColorDelta parameter. // setup for the start circle ia = 0; sa = sMin; ta = t0 + sa * (t1 - t0); xa = x0 + sa * (x1 - x0); ya = y0 + sa * (y1 - y0); ra = r0 + sa * (r1 - r0); if (ta < t0) { shading->getColor(t0, &colorA); } else if (ta > t1) { shading->getColor(t1, &colorA); } else { shading->getColor(ta, &colorA); } while (ia < radialMaxSplits) { // go as far along the t axis (toward t1) as we can, such that the // color difference is within the tolerance (radialColorDelta) -- // this uses bisection (between the current value, t, and t1), // limited to radialMaxSplits points along the t axis ib = radialMaxSplits; sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin); tb = t0 + sb * (t1 - t0); if (tb < t0) { shading->getColor(t0, &colorB); } else if (tb > t1) { shading->getColor(t1, &colorB); } else { shading->getColor(tb, &colorB); } while (ib - ia > 1) { for (k = 0; k < nComps; ++k) { if (fabs(colorB.c[k] - colorA.c[k]) > radialColorDelta) { break; } } if (k == nComps) { break; } ib = (ia + ib) / 2; sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin); tb = t0 + sb * (t1 - t0); if (tb < t0) { shading->getColor(t0, &colorB); } else if (tb > t1) { shading->getColor(t1, &colorB); } else { shading->getColor(tb, &colorB); } } // compute center and radius of the circle xb = x0 + sb * (x1 - x0); yb = y0 + sb * (y1 - y0); rb = r0 + sb * (r1 - r0); // use the average of the colors at the two circles for (k = 0; k < nComps; ++k) { colorA.c[k] = 0.5 * (colorA.c[k] + colorB.c[k]); } state->setFillColor(&colorA); out->updateFillColor(state); // construct path for first circle state->moveTo(xa + ra, ya); for (k = 1; k < n; ++k) { angle = ((double)k / (double)n) * 2 * M_PI; state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); } state->closePath(); // construct and append path for second circle state->moveTo(xb + rb, yb); for (k = 1; k < n; ++k) { angle = ((double)k / (double)n) * 2 * M_PI; state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); } state->closePath(); // fill the ring out->eoFill(state); state->clearPath(); // step to the next value of t ia = ib; sa = sb; ta = tb; xa = xb; ya = yb; ra = rb; colorA = colorB; }}void Gfx::doEndPath() { if (state->isCurPt() && clip != clipNone) { state->clip(); if (clip == clipNormal) { out->clip(state); } else { out->eoClip(state); } } clip = clipNone; state->clearPath();}//------------------------------------------------------------------------// path clipping operators//------------------------------------------------------------------------void Gfx::opClip(Object args[], int numArgs) { clip = clipNormal;}void Gfx::opEOClip(Object args[], int numArgs) { clip = clipEO;}//------------------------------------------------------------------------// text object operators//------------------------------------------------------------------------void Gfx::opBeginText(Object args[], int numArgs) { state->setTextMat(1, 0, 0, 1, 0, 0); state->textMoveTo(0, 0); out->updateTextMat(state); out->updateTextPos(state); fontChanged = gTrue;}void Gfx::opEndText(Object args[], int numArgs) {}//------------------------------------------------------------------------// text state operators//------------------------------------------------------------------------void Gfx::opSetCharSpacing(Object args[], int numArgs) { state->setCharSpace(args[0].getNum()); out->updateCharSpace(state);}void Gfx::opSetFont(Object args[], int numArgs) { GfxFont *font; if (!(font = res->lookupFont(args[0].getName()))) { return; } if (printCommands) { printf(" font: tag=%s name='%s' %g\n", font->getTag()->getCString(), font->getName() ? font->getName()->getCString() : "???", args[1].getNum()); fflush(stdout); } state->setFont(font, args[1].getNum()); fontChanged = gTrue;}void Gfx::opSetTextLeading(Object args[], int numArgs) { state->setLeading(args[0].getNum());}void Gfx::opSetTextRender(Object args[], int numArgs) { state->setRender(args[0].getInt()); out->updateRender(state);}void Gfx::opSetTextRise(Object args[], int numArgs) { state->setRise(args[0].getNum()); out->updateRise(state);}void Gfx::opSetWordSpacing(Object args[], int numArgs) { state->setWordSpace(args[0].getNum()); out->updateWordSpace(state);}void Gfx::opSetHorizScaling(Object args[], int numArgs) { state->setHorizScaling(args[0].getNum()); out->updateHorizScaling(state); fontChanged = gTrue;}//------------------------------------------------------------------------// text positioning operators//------------------------------------------------------------------------void Gfx::opTextMove(Object args[], int numArgs) { double tx, ty; tx = state->getLineX() + args[0].getNum(); ty = state->getLineY() + args[1].getNum(); state->textMoveTo(tx, ty); out->updateTextPos(state);}void Gfx::opTextMoveSet(Object args[], int numArgs) { double tx, ty; tx = state->getLineX() + args[0].getNum(); ty = args[1].getNum(); state->setLeading(-ty); ty += state->getLineY(); state->textMoveTo(tx, ty); out->updateTextPos(state);}void Gfx::opSetTextMatrix(Object args[], int numArgs) { state->setTextMat(args[0].getNum(), args[1].getNum(), args[2].getNum(), args[3].getNum(), args[4].getNum(), args[5].getNum()); state->textMoveTo(0, 0); out->updateTextMat(state); out->updateTextPos(state); fontChanged = gTrue;}void Gfx::opTextNextLine(Object args[], int numArgs) { double tx, ty; tx = state->getLineX(); ty = state->getLineY() - state->getLeading(); state->textMoveTo(tx, ty); out->updateTextPos(state);}//------------------------------------------------------------------------// text string operators//------------------------------------------------------------------------void Gfx::opShowText(Object args[], int numArgs) { if (!state->getFont()) { error(getPos(), "No font in show"); return; } doShowText(args[0].getString());}void Gfx::opMoveShowText(Object args[], int numArgs) { double tx, ty; if (!state->getFont()) { error(getPos(), "No font in move/show"); return; } tx = state->getLineX(); ty = state->getLineY() - state->getLeading(); state->textMoveTo(tx, ty); out->updateTextPos(state); doShowText(args[0].getString());}void Gfx::opMoveSetShowText(Object args[], int numArgs) { double tx, ty; if (!state->getFont()) { error(getPos(), "No font in move/set/show"); return; } state->setWordSpace(args[0].getNum()); state->setCharSpace(args[1].getNum()); tx = state->getLineX(); ty = state->getLineY() - state->getLeading(); state->textMoveTo(tx, ty); out->updateWordSpace(state); out->updateCharSpace(state); out->updateTextPos(state); doShowText(args[2].getString());}void Gfx::opShowSpaceText(Object args[], int numArgs) { Array *a; Object obj; int wMode; int i; if (!state->getFont()) { error(getPos(), "No font in show/space"); return; } wMode = state->getFont()->getWMode(); a = args[0].getArray(); for (i = 0; i < a->getLength(); ++i) { a->get(i, &obj); if (obj.isNum()) { if (wMode) { state->textShift(0, -obj.getNum() * 0.001 * state->getFontSize()); } else { state->textShift(-obj.getNum() * 0.001 * state->getFontSize(), 0); } out->updateTextShift(state, obj.getNum()); } else if (obj.isString()) { doShowText(obj.getString()); } else { error(getPos(), "Element of show/space array must be number or string"); } obj.free(); }}void Gfx::doShowText(GString *s) { GfxFont *font; int wMode; double riseX, riseY; CharCode code; Unicode u[8]; double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY; double originX, originY, tOriginX, tOriginY; double oldCTM[6], newCTM[6]; double *mat; Object charProc; Dict *resDict; Parser *oldParser; char *p; int len, n, uLen, nChars, nSpaces, i; if (fontChanged) { out->updateFont(state); fontChanged = gFalse; } font = state->getFont(); wMode = font->getWMode(); if (out->useDrawChar()) { out->beginString(state, s); } // handle a Type 3 char if (font->getType() == fontType3 && out->interpretType3Chars()) { mat = state->getCTM(); for (i = 0; i < 6; ++i) { oldCTM[i] = mat[i]; } mat = state->getTextMat(); newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?