📄 gfx.cc
字号:
xi0 = (int)floor((xMin - tPat->getBBox()[0]) / xstep); xi1 = (int)ceil((xMax - tPat->getBBox()[0]) / xstep); yi0 = (int)floor((yMin - tPat->getBBox()[1]) / ystep); yi1 = (int)ceil((yMax - tPat->getBBox()[1]) / ystep); 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 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 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]); // 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; } // 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); // do shading type-specific operations switch (shading->getType()) { case 1: doFunctionShFill((GfxFunctionShading *)shading); printf("doFunctionShFill\n"); break; case 2: doAxialShFill((GfxAxialShading *)shading); printf("doAxialShFill\n"); break; case 3: doRadialShFill((GfxRadialShading *)shading); printf("doRadialShFill\n"); break; case 4: case 5: doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); printf("doGouraudTriangleShFill\n"); break; case 6: case 7: doPatchMeshShFill((GfxPatchMeshShading *)shading); printf("doPatchMeshShShFill\n"); break; } // 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); } else { 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) { for (j = 0; j < nComps; ++j) { if (abs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) { break; } } if (j < nComps) { break; } } // center of the rectangle xM = 0.5 * (x0 + x1); yM = 0.5 * (y0 + y1); // the four corner colors are close (or we hit the recursive limit) // -- fill the rectangle; but require at least one subdivision // (depth==0) to avoid problems when the four outer corners of the // shaded region are the same color if ((i == 4 && depth > 0) || depth == functionMaxDepth) { // use the center color shading->getColor(xM, yM, &fillColor); state->setFillColor(&fillColor); out->updateFillColor(state); // fill the rectangle state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4], x0 * matrix[1] + y0 * matrix[3] + matrix[5]); state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4], x1 * matrix[1] + y0 * matrix[3] + matrix[5]); state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4], x1 * matrix[1] + y1 * matrix[3] + matrix[5]); state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4], x0 * matrix[1] + y1 * matrix[3] + matrix[5]); state->closePath(); out->fill(state); state->clearPath(); // the four corner colors are not close enough -- subdivide the // rectangle } else { // colors[0] colorM0 colors[2] // (x0,y0) (xM,y0) (x1,y0) // +----------+----------+ // | | | // | UL | UR | // color0M | colorMM | color1M // (x0,yM) +----------+----------+ (x1,yM) // | (xM,yM) | // | LL | LR | // | | | // +----------+----------+ // colors[1] colorM1 colors[3] // (x0,y1) (xM,y1) (x1,y1) shading->getColor(x0, yM, &color0M); shading->getColor(x1, yM, &color1M); shading->getColor(xM, y0, &colorM0); shading->getColor(xM, y1, &colorM1); shading->getColor(xM, yM, &colorMM); // upper-left sub-rectangle colors2[0] = colors[0]; colors2[1] = color0M; colors2[2] = colorM0; colors2[3] = colorMM; doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1); // lower-left sub-rectangle colors2[0] = color0M; colors2[1] = colors[1]; colors2[2] = colorMM; colors2[3] = colorM1; doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1); // upper-right sub-rectangle colors2[0] = colorM0; colors2[1] = colorMM; colors2[2] = colors[2]; colors2[3] = color1M; doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1); // lower-right sub-rectangle colors2[0] = colorMM; colors2[1] = colorM1; colors2[2] = color1M; colors2[3] = colors[3]; doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1); }}void Gfx::doAxialShFill(GfxAxialShading *shading) { double xMin, yMin, xMax, yMax; double x0, y0, x1, y1; double dx, dy, mul; GBool dxZero, dyZero; 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; if (out->useShadedFills()) { out->axialShadedFill(state, shading); } else { // 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; dxZero = fabs(dx) < 0.001; dyZero = fabs(dy) < 0.001; 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: require at least one split to avoid problems when the two // ends of the t axis have the same color nComps = shading->getColorSpace()->getNComps(); ta[0] = tMin; next[0] = axialMaxSplits / 2; ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax); next[axialMaxSplits / 2] = axialMaxSplits; ta[axialMaxSplits] = tMax; // 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 (dxZero && dyZero) { sMin = sMax = 0; } if (dxZero) { sMin = (xMin - tx) / -dy; sMax = (xMax - tx) / -dy; if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } } else if (dyZero) { 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -