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 + -
显示快捷键?