📄 gfx.cc
字号:
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); } if (state->getStrokeColorSpace()->getMode() == csPattern) { doPatternStroke(); } else { 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); } if (state->getStrokeColorSpace()->getMode() == csPattern) { doPatternStroke(); } else { out->stroke(state); } } doEndPath();}void Gfx::doPatternFill(GBool eoFill) { GfxPattern *pattern; // 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; } if (!(pattern = state->getFillPattern())) { return; } switch (pattern->getType()) { case 1: doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, eoFill); break; case 2: doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill); break; default: error(getPos(), "Unimplemented pattern type (%d) in fill", pattern->getType()); break; }}void Gfx::doPatternStroke() { GfxPattern *pattern; // 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; } if (!(pattern = state->getStrokePattern())) { return; } switch (pattern->getType()) { case 1: doTilingPatternFill((GfxTilingPattern *)pattern, gTrue, gFalse); break; case 2: doShadingPatternFill((GfxShadingPattern *)pattern, gTrue, gFalse); break; default: error(getPos(), "Unimplemented pattern type (%d) in stroke", pattern->getType()); break; }}void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool stroke, GBool eoFill) { GfxPatternColorSpace *patCS; GfxColorSpace *cs; GfxPath *savedPath; 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; // get color space patCS = (GfxPatternColorSpace *)(stroke ? state->getStrokeColorSpace() : state->getFillColorSpace()); // 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 (device 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 savedPath = state->getPath()->copy(); saveState(); // set underlying color space (for uncolored tiling patterns); set // various other parameters (stroke color, line width) to match // Adobe's behavior if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { state->setFillColorSpace(cs->copy()); out->updateFillColorSpace(state); state->setStrokeColorSpace(cs->copy()); out->updateStrokeColorSpace(state); state->setStrokeColor(state->getFillColor()); } else { state->setFillColorSpace(new GfxDeviceGrayColorSpace()); out->updateFillColorSpace(state); state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); out->updateStrokeColorSpace(state); } state->setFillPattern(NULL); out->updateFillColor(state); state->setStrokePattern(NULL); out->updateStrokeColor(state); if (!stroke) { state->setLineWidth(0); out->updateLineWidth(state); } // clip to current path if (stroke) { state->clipToStrokePath(); out->clipToStrokePath(state); } else { state->clip(); if (eoFill) { out->eoClip(state); } else { out->clip(state); } } state->clearPath(); // get the clip region, check for empty state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax); if (cxMin > cxMax || cyMin > cyMax) { goto err; } // transform clip region bbox to pattern space 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)ceil((xMin - tPat->getBBox()[2]) / xstep); xi1 = (int)floor((xMax - tPat->getBBox()[0]) / xstep) + 1; yi0 = (int)ceil((yMin - tPat->getBBox()[3]) / ystep); yi1 = (int)floor((yMax - tPat->getBBox()[1]) / ystep) + 1; for (i = 0; i < 4; ++i) { m1[i] = m[i]; } if (out->useTilingPatternFill()) { m1[4] = m[4]; m1[5] = m[5]; out->tilingPatternFill(state, tPat->getContentStream(), tPat->getPaintType(), tPat->getResDict(), m1, tPat->getBBox(), xi0, yi0, xi1, yi1, xstep, ystep); } else { 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 err: restoreState(); state->setPath(savedPath);}void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool stroke, GBool eoFill) { GfxShading *shading; GfxPath *savedPath; double *ctm, *btm, *ptm; double m[6], ictm[6], m1[6]; double xMin, yMin, xMax, yMax; double det; shading = sPat->getShading(); // save current graphics state savedPath = state->getPath()->copy(); saveState(); // 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->setPath(savedPath->copy()); } // clip to current path if (stroke) { state->clipToStrokePath(); out->clipToStrokePath(state); } else { state->clip(); if (eoFill) { out->eoClip(state); } else { out->clip(state); } } // set the color space state->setFillColorSpace(shading->getColorSpace()->copy()); out->updateFillColorSpace(state); // background color fill if (shading->getHasBackground()) { state->setFillColor(shading->getBackground()); out->updateFillColor(state); out->fill(state); } state->clearPath(); // construct a (pattern space) -> (current space) transform matrix ctm = state->getCTM(); btm = baseMatrix; ptm = sPat->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]; // set the new matrix state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]); out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);#if 1 //~tmp: turn off anti-aliasing temporarily GBool vaa = out->getVectorAntialias(); if (vaa) { out->setVectorAntialias(gFalse); }#endif // do shading type-specific operations switch (shading->getType()) { case 1: doFunctionShFill((GfxFunctionShading *)shading); break; case 2: doAxialShFill((GfxAxialShading *)shading); break; case 3: doRadialShFill((GfxRadialShading *)shading); break; case 4: case 5: doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); break; case 6: case 7: doPatchMeshShFill((GfxPatchMeshShading *)shading); break; }#if 1 //~tmp: turn off anti-aliasing temporarily if (vaa) { out->setVectorAntialias(gTrue); }#endif // restore graphics state restoreState(); state->setPath(savedPath);}void Gfx::opShFill(Object args[], int numArgs) { GfxShading *shading; GfxPath *savedPath; double xMin, yMin, xMax, yMax; if (!(shading = res->lookupShading(args[0].getName()))) { return; } // save current graphics state savedPath = state->getPath()->copy(); saveState(); // 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()); out->updateFillColorSpace(state);#if 1 //~tmp: turn off anti-aliasing temporarily GBool vaa = out->getVectorAntialias(); if (vaa) { out->setVectorAntialias(gFalse); }#endif // do shading type-specific operations switch (shading->getType()) { case 1: doFunctionShFill((GfxFunctionShading *)shading); break; case 2: doAxialShFill((GfxAxialShading *)shading); break; case 3: doRadialShFill((GfxRadialShading *)shading); break; case 4: case 5: doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); break; case 6: case 7: doPatchMeshShFill((GfxPatchMeshShading *)shading); break; }#if 1 //~tmp: turn off anti-aliasing temporarily if (vaa) { out->setVectorAntialias(gTrue); }#endif // restore graphics state restoreState(); state->setPath(savedPath); delete shading;}void Gfx::doFunctionShFill(GfxFunctionShading *shading) { double x0, y0, x1, y1; GfxColor colors[4]; if (out->useShadedFills() && out->functionShadedFill(state, shading)) { return; } shading->getDomain(&x0, &y0, &x1, &y1); shading->getColor(x0, y0, &colors[0]); shading->getColor(x0, y1, &colors[1]); shading->getColor(x1, y0, &colors[2]); shading->getColor(x1, y1, &colors[3]); doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0);}void Gfx::doFunctionShFill1(GfxFunctionShading *shading, double x0, double y0, double x1, double y1, GfxColor *colors, int depth) { GfxColor fillColor; GfxColor color0M, color1M, colorM0, colorM1, colorMM; GfxColor colors2[4]; double *matrix; double xM, yM; int nComps, i, j; nComps = shading->getColorSpace()->getNComps(); matrix = shading->getMatrix(); // compare the four corner colors for (i = 0; i < 4; ++i) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -