summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc308
1 files changed, 224 insertions, 84 deletions
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;
}
}