gfx.cc

来自「source code: Covert TXT to PDF」· CC 代码 · 共 2,586 行 · 第 1/5 页

CC
2,586 行
字号
    return;  }  x1 = args[0].getNum();  y1 = args[1].getNum();  x2 = args[2].getNum();  y2 = args[3].getNum();  x3 = x2;  y3 = y2;  state->curveTo(x1, y1, x2, y2, x3, y3);}void Gfx::opRectangle(Object args[], int numArgs) {  double x, y, w, h;  x = args[0].getNum();  y = args[1].getNum();  w = args[2].getNum();  h = args[3].getNum();  state->moveTo(x, y);  state->lineTo(x + w, y);  state->lineTo(x + w, y + h);  state->lineTo(x, y + h);  state->closePath();}void Gfx::opClosePath(Object args[], int numArgs) {  if (!state->isCurPt()) {    error(getPos(), "No current point in closepath");    return;  }  state->closePath();}//------------------------------------------------------------------------// path painting operators//------------------------------------------------------------------------void Gfx::opEndPath(Object args[], int numArgs) {  doEndPath();}void Gfx::opStroke(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in stroke");    return;  }  if (state->isPath())    out->stroke(state);  doEndPath();}void Gfx::opCloseStroke(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in closepath/stroke");    return;  }  if (state->isPath()) {    state->closePath();    out->stroke(state);  }  doEndPath();}void Gfx::opFill(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in fill");    return;  }  if (state->isPath()) {    if (state->getFillColorSpace()->getMode() == csPattern) {      doPatternFill(gFalse);    } else {      out->fill(state);    }  }  doEndPath();}void Gfx::opEOFill(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in eofill");    return;  }  if (state->isPath()) {    if (state->getFillColorSpace()->getMode() == csPattern) {      doPatternFill(gTrue);    } else {      out->eoFill(state);    }  }  doEndPath();}void Gfx::opFillStroke(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in fill/stroke");    return;  }  if (state->isPath()) {    if (state->getFillColorSpace()->getMode() == csPattern) {      doPatternFill(gFalse);    } else {      out->fill(state);    }    out->stroke(state);  }  doEndPath();}void Gfx::opCloseFillStroke(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in closepath/fill/stroke");    return;  }  if (state->isPath()) {    state->closePath();    if (state->getFillColorSpace()->getMode() == csPattern) {      doPatternFill(gFalse);    } else {      out->fill(state);    }    out->stroke(state);  }  doEndPath();}void Gfx::opEOFillStroke(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in eofill/stroke");    return;  }  if (state->isPath()) {    if (state->getFillColorSpace()->getMode() == csPattern) {      doPatternFill(gTrue);    } else {      out->eoFill(state);    }    out->stroke(state);  }  doEndPath();}void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {  if (!state->isCurPt()) {    //error(getPos(), "No path in closepath/eofill/stroke");    return;  }  if (state->isPath()) {    state->closePath();    if (state->getFillColorSpace()->getMode() == csPattern) {      doPatternFill(gTrue);    } else {      out->eoFill(state);    }    out->stroke(state);  }  doEndPath();}void Gfx::doPatternFill(GBool eoFill) {  GfxPatternColorSpace *patCS;  GfxPattern *pattern;  GfxTilingPattern *tPat;  GfxColorSpace *cs;  double xMin, yMin, xMax, yMax, x, y, x1, y1;  double cxMin, cyMin, cxMax, cyMax;  int xi0, yi0, xi1, yi1, xi, yi;  double *ctm, *btm, *ptm;  double m[6], ictm[6], m1[6], imb[6];  double det;  double xstep, ystep;  int i;  // this is a bit of a kludge -- patterns can be really slow, so we  // skip them if we're only doing text extraction, since they almost  // certainly don't contain any text  if (!out->needNonText()) {    return;  }  // get color space  patCS = (GfxPatternColorSpace *)state->getFillColorSpace();  // get pattern  if (!(pattern = state->getFillPattern())) {    return;  }  if (pattern->getType() != 1) {    return;  }  tPat = (GfxTilingPattern *)pattern;  // construct a (pattern space) -> (current space) transform matrix  ctm = state->getCTM();  btm = baseMatrix;  ptm = tPat->getMatrix();  // iCTM = invert CTM  det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);  ictm[0] = ctm[3] * det;  ictm[1] = -ctm[1] * det;  ictm[2] = -ctm[2] * det;  ictm[3] = ctm[0] * det;  ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;  ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;  // m1 = PTM * BTM = PTM * base transform matrix  m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];  m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];  m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];  m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];  m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];  m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];  // m = m1 * iCTM = (PTM * BTM) * (iCTM)  m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];  m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];  m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];  m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];  m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];  m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];  // construct a (base space) -> (pattern space) transform matrix  det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);  imb[0] = m1[3] * det;  imb[1] = -m1[1] * det;  imb[2] = -m1[2] * det;  imb[3] = m1[0] * det;  imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;  imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;  // save current graphics state  out->saveState(state);  state = state->save();  // set underlying color space (for uncolored tiling patterns)  if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {    state->setFillColorSpace(cs->copy());  } else {    state->setFillColorSpace(new GfxDeviceGrayColorSpace());  }  state->setFillPattern(NULL);  out->updateFillColor(state);  // clip to current path  state->clip();  if (eoFill) {    out->eoClip(state);  } else {    out->clip(state);  }  state->clearPath();  // transform clip region bbox to pattern space  state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);  xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];  yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];  x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];  y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];  if (x1 < xMin) {    xMin = x1;  } else if (x1 > xMax) {    xMax = x1;  }  if (y1 < yMin) {    yMin = y1;  } else if (y1 > yMax) {    yMax = y1;  }  x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];  y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];  if (x1 < xMin) {    xMin = x1;  } else if (x1 > xMax) {    xMax = x1;  }  if (y1 < yMin) {    yMin = y1;  } else if (y1 > yMax) {    yMax = y1;  }  x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];  y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];  if (x1 < xMin) {    xMin = x1;  } else if (x1 > xMax) {    xMax = x1;  }  if (y1 < yMin) {    yMin = y1;  } else if (y1 > yMax) {    yMax = y1;  }  // draw the pattern  //~ this should treat negative steps differently -- start at right/top  //~ edge instead of left/bottom (?)  xstep = fabs(tPat->getXStep());  ystep = fabs(tPat->getYStep());  xi0 = (int)floor(xMin / xstep);  xi1 = (int)ceil(xMax / xstep);  yi0 = (int)floor(yMin / ystep);  yi1 = (int)ceil(yMax / ystep);  for (i = 0; i < 4; ++i) {    m1[i] = m[i];  }  for (yi = yi0; yi < yi1; ++yi) {    for (xi = xi0; xi < xi1; ++xi) {      x = xi * xstep;      y = yi * ystep;      m1[4] = x * m[0] + y * m[2] + m[4];      m1[5] = x * m[1] + y * m[3] + m[5];      doForm1(tPat->getContentStream(), tPat->getResDict(),	      m1, tPat->getBBox());    }  }  // restore graphics state  state = state->restore();  out->restoreState(state);}void Gfx::opShFill(Object args[], int numArgs) {  GfxShading *shading;  double xMin, yMin, xMax, yMax;  if (!(shading = res->lookupShading(args[0].getName()))) {    return;  }  // save current graphics state  out->saveState(state);  state = state->save();  // clip to bbox  if (shading->getHasBBox()) {    shading->getBBox(&xMin, &yMin, &xMax, &yMax);    state->moveTo(xMin, yMin);    state->lineTo(xMax, yMin);    state->lineTo(xMax, yMax);    state->lineTo(xMin, yMax);    state->closePath();    state->clip();    out->clip(state);    state->clearPath();  }  // set the color space  state->setFillColorSpace(shading->getColorSpace()->copy());  // do shading type-specific operations  switch (shading->getType()) {  case 2:    doAxialShFill((GfxAxialShading *)shading);    break;  case 3:    doRadialShFill((GfxRadialShading *)shading);    break;  }  // restore graphics state  state = state->restore();  out->restoreState(state);  delete shading;}void Gfx::doAxialShFill(GfxAxialShading *shading) {  double xMin, yMin, xMax, yMax;  double x0, y0, x1, y1;  double dx, dy, mul;  double tMin, tMax, t, tx, ty;  double s[4], sMin, sMax, tmp;  double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;  double t0, t1, tt;  double ta[axialMaxSplits + 1];  int next[axialMaxSplits + 1];  GfxColor color0, color1;  int nComps;  int i, j, k, kk;  // get the clip region bbox  state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);  // compute min and max t values, based on the four corners of the  // clip region bbox  shading->getCoords(&x0, &y0, &x1, &y1);  dx = x1 - x0;  dy = y1 - y0;  mul = 1 / (dx * dx + dy * dy);  tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;  t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;  if (t < tMin) {    tMin = t;  } else if (t > tMax) {    tMax = t;  }  t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;  if (t < tMin) {    tMin = t;  } else if (t > tMax) {    tMax = t;  }  t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;  if (t < tMin) {    tMin = t;  } else if (t > tMax) {    tMax = t;  }  if (tMin < 0 && !shading->getExtend0()) {    tMin = 0;  }  if (tMax > 1 && !shading->getExtend1()) {    tMax = 1;  }  // get the function domain  t0 = shading->getDomain0();  t1 = shading->getDomain1();  // Traverse the t axis and do the shading.  //  // For each point (tx, ty) on the t axis, consider a line through  // that point perpendicular to the t axis:  //  //     x(s) = tx + s * -dy   -->   s = (x - tx) / -dy  //     y(s) = ty + s * dx    -->   s = (y - ty) / dx  //  // Then look at the intersection of this line with the bounding box  // (xMin, yMin, xMax, yMax).  In the general case, there are four  // intersection points:  //  //     s0 = (xMin - tx) / -dy  //     s1 = (xMax - tx) / -dy  //     s2 = (yMin - ty) / dx  //     s3 = (yMax - ty) / dx  //  // and we want the middle two s values.  //  // In the case where dx = 0, take s0 and s1; in the case where dy =  // 0, take s2 and s3.  //  // Each filled polygon is bounded by two of these line segments  // perpdendicular to the t axis.  //  // The t axis is bisected into smaller regions until the color  // difference across a region is small enough, and then the region  // is painted with a single color.  // set up  nComps = shading->getColorSpace()->getNComps();  ta[0] = tMin;  ta[axialMaxSplits] = tMax;  next[0] = axialMaxSplits;  // compute the color at t = tMin  if (tMin < 0) {    tt = t0;  } else if (tMin > 1) {    tt = t1;  } else {    tt = t0 + (t1 - t0) * tMin;  }  shading->getColor(tt, &color0);  // compute the coordinates of the point on the t axis at t = tMin;  // then compute the intersection of the perpendicular line with the  // bounding box  tx = x0 + tMin * dx;  ty = y0 + tMin * 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];  }  ux0 = tx - sMin * dy;  uy0 = ty + sMin * dx;  vx0 = tx - sMax * dy;  vy0 = ty + sMax * dx;  i = 0;  while (i < axialMaxSplits) {    // bisect until color difference is small enough or we hit the    // bisection limit    j = next[i];    while (j > i + 1) {      if (ta[j] < 0) {	tt = t0;      } else if (ta[j] > 1) {	tt = t1;      } else {	tt = t0 + (t1 - t0) * ta[j];      }      shading->getColor(tt, &color1);      for (k = 0; k < nComps; ++k) {	if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) {	  break;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?