From d743821ec3b71e00af5dc5541d4e7bf5b003c55e Mon Sep 17 00:00:00 2001 From: Akira Kakuto Date: Sun, 24 Apr 2022 03:42:26 +0000 Subject: xpdf 4.04 git-svn-id: svn://tug.org/texlive/trunk@63119 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc | 308 ++++++++++++++++------- 1 file changed, 224 insertions(+), 84 deletions(-) (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc') diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc index 5e9991e1b97..43503aaedb8 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc @@ -2071,6 +2071,7 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict Function *funcsA[gfxColorMaxComps]; int nFuncsA; Object obj1, obj2; + GBool ok; int i; x0A = y0A = 0; @@ -2139,14 +2140,21 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict return NULL; } - for (i = 0; i < shading->nFuncs; ++i) { - if (shading->funcs[i]->getOutputSize() - != shading->getColorSpace()->getNComps()) { - error(errSyntaxError, -1, "Invalid function in shading dictionary"); - delete shading; - return NULL; + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -2241,7 +2249,7 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict double t0A, t1A; Function *funcsA[gfxColorMaxComps]; int nFuncsA; - GBool extend0A, extend1A; + GBool extend0A, extend1A, ok; Object obj1, obj2; int i; @@ -2319,14 +2327,21 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict return NULL; } - for (i = 0; i < shading->nFuncs; ++i) { - if (shading->funcs[i]->getOutputSize() - != shading->getColorSpace()->getNComps()) { - error(errSyntaxError, -1, "Invalid function in shading dictionary"); - delete shading; - return NULL; + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -2420,7 +2435,7 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict double t0A, t1A; Function *funcsA[gfxColorMaxComps]; int nFuncsA; - GBool extend0A, extend1A; + GBool extend0A, extend1A, ok; Object obj1, obj2; int i; @@ -2501,14 +2516,21 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict return NULL; } - for (i = 0; i < shading->nFuncs; ++i) { - if (shading->funcs[i]->getOutputSize() - != shading->getColorSpace()->getNComps()) { - error(errSyntaxError, -1, "Invalid function in shading dictionary"); - delete shading; - return NULL; + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -2675,6 +2697,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( Guint c[gfxColorMaxComps]; GfxShadingBitBuf *bitBuf; Object obj1, obj2; + GBool ok; int i, j, k, state; if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { @@ -2883,14 +2906,23 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( return NULL; } - for (i = 0; i < shading->nFuncs; ++i) { - if (shading->funcs[i]->getOutputSize() - != shading->getColorSpace()->getNComps()) { - error(errSyntaxError, -1, "Invalid function in shading dictionary"); - delete shading; - return NULL; + ok = gFalse; + if (shading->nFuncs == 0) { + ok = shading->nComps == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -3042,6 +3074,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, Guint ci; GfxShadingBitBuf *bitBuf; Object obj1, obj2; + GBool ok; int i, j; nPatchesA = 0; @@ -3555,14 +3588,23 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, return NULL; } - for (i = 0; i < shading->nFuncs; ++i) { - if (shading->funcs[i]->getOutputSize() - != shading->getColorSpace()->getNComps()) { - error(errSyntaxError, -1, "Invalid function in shading dictionary"); - delete shading; - return NULL; + ok = gFalse; + if (shading->nFuncs == 0) { + ok = shading->nComps == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -4091,6 +4133,26 @@ GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1, subpaths[i] = subpaths1[i]->copy(); } +double GfxPath::getCurX() { + if (justMoved) { + return firstX; + } else if (n > 0) { + return subpaths[n-1]->getLastX(); + } else { + return 0; + } +} + +double GfxPath::getCurY() { + if (justMoved) { + return firstY; + } else if (n > 0) { + return subpaths[n-1]->getLastY(); + } else { + return 0; + } +} + void GfxPath::moveTo(double x, double y) { justMoved = gTrue; firstX = x; @@ -4581,65 +4643,143 @@ void GfxState::clip() { } void GfxState::clipToStrokePath() { - double xMin, yMin, xMax, yMax, x, y, t0, t1; - GfxSubpath *subpath; - int i, j; - - xMin = xMax = yMin = yMax = 0; // make gcc happy - for (i = 0; i < path->getNumSubpaths(); ++i) { - subpath = path->getSubpath(i); - for (j = 0; j < subpath->getNumPoints(); ++j) { - transform(subpath->getX(j), subpath->getY(j), &x, &y); + // We compute the stroke path bbox in user space (line width and + // miter limt are handled in user space), and then transform the + // bbox to device space. This can result in a larger-than-needed + // bbox if the matrix isn't "square", but that's ok. + // + // There are two cases for each point on the path: + // (1) miter join, under miter limit => compute the miter point + // (2) all other joins and caps => use the path point +/- 0.5 * line width + double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double w = 0.5 * lineWidth; + for (int i = 0; i < path->getNumSubpaths(); ++i) { + GfxSubpath *subpath = path->getSubpath(i); + for (int j = 0; j < subpath->getNumPoints(); ++j) { + double x1 = subpath->getX(j); + double y1 = subpath->getY(j); if (i == 0 && j == 0) { - xMin = xMax = x; - yMin = yMax = y; - } else { - if (x < xMin) { - xMin = x; - } else if (x > xMax) { - xMax = x; + xMin = xMax = x1; + yMin = yMax = y1; + } + GBool useMiter = gFalse; + if (lineJoin == 0 && // miter join + ((j > 0 && j < subpath->getNumPoints() - 1) || subpath->isClosed())) { + double x0, y0, x2, y2; + if (j > 0) { + x0 = subpath->getX(j - 1); + y0 = subpath->getY(j - 1); + } else { + x0 = subpath->getLastX(); + y0 = subpath->getLastY(); } - if (y < yMin) { - yMin = y; - } else if (y > yMax) { - yMax = y; + if (j < subpath->getNumPoints() - 1) { + x2 = subpath->getX(j + 1); + y2 = subpath->getY(j + 1); + } else { + x2 = subpath->getX(0); + y2 = subpath->getY(0); + } + if ((fabs(x1 - x0) > 0.0001 || fabs(y1 - y0) > 0.0001) && + (fabs(x2 - x1) > 0.0001 || fabs(y2 - y1) > 0.0001)) { + double d01 = 1 / sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + double ux = (x1 - x0) * d01; + double uy = (y1 - y0) * d01; + double d12 = 1 / sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + double vx = (x2 - x1) * d12; + double vy = (y2 - y1) * d12; + double dot = -ux * vx - uy * vy; + if (dot < 0.9999) { + double miter = sqrt(2 / (1 - dot)); + if (miter <= miterLimit) { + double cross = ux * vy - uy * vx; + double m = sqrt(2 / (1 - dot) - 1); + double ax, ay; + if (cross >= 0) { + ax = x1 + w * uy; + ay = y1 - w * ux; + } else { + ax = x1 - w * uy; + ay = y1 + w * ux; + } + double mx = ax + m * w * ux; + double my = ay + m * w * uy; + if (mx < xMin) { + xMin = mx; + } else if (mx > xMax) { + xMax = mx; + } + if (my < yMin) { + yMin = my; + } else if (my > yMax) { + yMax = my; + } + useMiter = gTrue; + } + } + } + } + if (!useMiter) { + if (x1 - w < xMin) { + xMin = x1 - w; + } + if (x1 + w > xMax) { + xMax = x1 + w; + } + if (y1 - w < yMin) { + yMin = y1 - w; + } + if (y1 + w > yMax) { + yMax = y1 + w; } } } } - // allow for the line width - //~ miter joins can extend farther than this - t0 = fabs(ctm[0]); - t1 = fabs(ctm[2]); - if (t0 > t1) { - xMin -= 0.5 * lineWidth * t0; - xMax += 0.5 * lineWidth * t0; - } else { - xMin -= 0.5 * lineWidth * t1; - xMax += 0.5 * lineWidth * t1; - } - t0 = fabs(ctm[0]); - t1 = fabs(ctm[3]); - if (t0 > t1) { - yMin -= 0.5 * lineWidth * t0; - yMax += 0.5 * lineWidth * t0; - } else { - yMin -= 0.5 * lineWidth * t1; - yMax += 0.5 * lineWidth * t1; - } - - if (xMin > clipXMin) { - clipXMin = xMin; - } - if (yMin > clipYMin) { - clipYMin = yMin; - } - if (xMax < clipXMax) { - clipXMax = xMax; - } - if (yMax < clipYMax) { - clipYMax = yMax; + double xx, yy; + transform(xMin, yMin, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMin, yMax, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMax, yMin, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMax, yMax, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; } } -- cgit v1.2.3