summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Astals Cid <aacid@kde.org>2012-01-15 23:31:51 +0100
committerAlbert Astals Cid <aacid@kde.org>2012-01-15 23:31:51 +0100
commitc885d0cb1e470ae19642f9c03b1c668bbeda1ae9 (patch)
treec5b2db470f20320221cc4eb8a43813d15e22cd2d
parent431fddbc14548cdce21d94cfa4d3779bc142839f (diff)
After more patches from Thomas
-rw-r--r--ALL_DIFF3613
1 files changed, 1 insertions, 3612 deletions
diff --git a/ALL_DIFF b/ALL_DIFF
index 149caaa..e63adba 100644
--- a/ALL_DIFF
+++ b/ALL_DIFF
@@ -38,52 +38,6 @@ diff -ru xpdf-3.02/xpdf/Gfx.cc xpdf-3.03/xpdf/Gfx.cc
#include "Gfx.h"
// the MSVC math.h doesn't define this
-@@ -461,6 +487,10 @@
- baseMatrix[i] = state->getCTM()[i];
- }
- formDepth = 0;
-+ textClipBBoxEmpty = gTrue;
-+ markedContentStack = new GList();
-+ ocState = gTrue;
-+ parser = NULL;
- abortCheckCbk = abortCheckCbkA;
- abortCheckCbkData = abortCheckCbkDataA;
-
-@@ -500,6 +531,10 @@
- baseMatrix[i] = state->getCTM()[i];
- }
- formDepth = 0;
-+ textClipBBoxEmpty = gTrue;
-+ markedContentStack = new GList();
-+ ocState = gTrue;
-+ parser = NULL;
- abortCheckCbk = abortCheckCbkA;
- abortCheckCbkData = abortCheckCbkDataA;
-
-@@ -517,18 +552,17 @@
- }
-
- Gfx::~Gfx() {
-- while (state->hasSaves()) {
-- restoreState();
-- }
- if (!subPage) {
- out->endPage();
- }
-+ while (state->hasSaves()) {
-+ restoreState();
-+ }
-+ delete state;
- while (res) {
- popResources();
- }
-- if (state) {
-- delete state;
-- }
-+ deleteGList(markedContentStack, GfxMarkedContent);
- }
-
- void Gfx::display(Object *obj, GBool topLevel) {
@@ -562,7 +596,8 @@
int lastAbortCheck;
@@ -239,19 +193,6 @@ diff -ru xpdf-3.02/xpdf/Gfx.cc xpdf-3.03/xpdf/Gfx.cc
}
}
obj3.free();
-@@ -1045,9 +1149,9 @@
-
- // draw it
- ++formDepth;
-- doForm1(str, resDict, m, bbox, gTrue, gTrue,
-- blendingColorSpace, isolated, knockout,
-- alpha, transferFunc, backdropColor);
-+ drawForm(str, resDict, m, bbox, gTrue, gTrue,
-+ blendingColorSpace, isolated, knockout,
-+ alpha, transferFunc, backdropColor);
- --formDepth;
-
- if (blendingColorSpace) {
@@ -1402,14 +1512,16 @@
void Gfx::opStroke(Object args[], int numArgs) {
@@ -471,1025 +412,7 @@ diff -ru xpdf-3.02/xpdf/Gfx.cc xpdf-3.03/xpdf/Gfx.cc
}
}
doEndPath();
-@@ -1558,13 +1684,13 @@
- }
- switch (pattern->getType()) {
- case 1:
-- doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, eoFill);
-+ doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, eoFill, gFalse);
- break;
- case 2:
-- doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill);
-+ doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill, gFalse);
- break;
- default:
-- error(getPos(), "Unimplemented pattern type (%d) in fill",
-+ error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in fill",
- pattern->getType());
- break;
- }
-@@ -1585,23 +1711,68 @@
- }
- switch (pattern->getType()) {
- case 1:
-- doTilingPatternFill((GfxTilingPattern *)pattern, gTrue, gFalse);
-+ doTilingPatternFill((GfxTilingPattern *)pattern, gTrue, gFalse, gFalse);
-+ break;
-+ case 2:
-+ doShadingPatternFill((GfxShadingPattern *)pattern, gTrue, gFalse, gFalse);
-+ break;
-+ default:
-+ error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in stroke",
-+ pattern->getType());
-+ break;
-+ }
-+}
-+
-+void Gfx::doPatternText() {
-+ 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, gFalse, gTrue);
- break;
- case 2:
-- doShadingPatternFill((GfxShadingPattern *)pattern, gTrue, gFalse);
-+ doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, gFalse, gTrue);
- break;
- default:
-- error(getPos(), "Unimplemented pattern type (%d) in stroke",
-+ error(errSyntaxError, getPos(), "Unknown pattern type ({0:d}) in fill",
- pattern->getType());
- break;
- }
- }
-
-+void Gfx::doPatternImageMask(Object *ref, Stream *str, int width, int height,
-+ GBool invert, GBool inlineImg) {
-+ saveState();
-+
-+ out->setSoftMaskFromImageMask(state, ref, str,
-+ width, height, invert, inlineImg);
-+
-+ state->clearPath();
-+ state->moveTo(0, 0);
-+ state->lineTo(1, 0);
-+ state->lineTo(1, 1);
-+ state->lineTo(0, 1);
-+ state->closePath();
-+ doPatternFill(gTrue);
-+
-+ restoreState();
-+}
-+
- void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
-- GBool stroke, GBool eoFill) {
-+ GBool stroke, GBool eoFill, GBool text) {
- GfxPatternColorSpace *patCS;
- GfxColorSpace *cs;
-- GfxPath *savedPath;
-+ GfxState *savedState;
- double xMin, yMin, xMax, yMax, x, y, x1, y1;
- double cxMin, cyMin, cxMax, cyMax;
- int xi0, yi0, xi1, yi1, xi, yi;
-@@ -1652,28 +1823,27 @@
- imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
-
- // save current graphics state
-- savedPath = state->getPath()->copy();
-- saveState();
-+ savedState = saveStateStack();
-
- // set underlying color space (for uncolored tiling patterns); set
- // various other parameters (stroke color, line width) to match
- // Adobe's behavior
-+ state->setFillPattern(NULL);
-+ state->setStrokePattern(NULL);
- 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());
-+ out->updateFillColor(state);
-+ out->updateStrokeColor(state);
- } 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);
-@@ -1683,7 +1853,7 @@
- if (stroke) {
- state->clipToStrokePath();
- out->clipToStrokePath(state);
-- } else {
-+ } else if (!text) {
- state->clip();
- if (eoFill) {
- out->eoClip(state);
-@@ -1754,7 +1924,7 @@
- if (out->useTilingPatternFill()) {
- m1[4] = m[4];
- m1[5] = m[5];
-- out->tilingPatternFill(state, tPat->getContentStream(),
-+ out->tilingPatternFill(state, this, tPat->getContentStream(),
- tPat->getPaintType(), tPat->getResDict(),
- m1, tPat->getBBox(),
- xi0, yi0, xi1, yi1, xstep, ystep);
-@@ -1765,22 +1935,21 @@
- 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());
-+ drawForm(tPat->getContentStream(), tPat->getResDict(),
-+ m1, tPat->getBBox());
- }
- }
- }
-
- // restore graphics state
- err:
-- restoreState();
-- state->setPath(savedPath);
-+ restoreStateStack(savedState);
- }
-
- void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
-- GBool stroke, GBool eoFill) {
-+ GBool stroke, GBool eoFill, GBool text) {
- GfxShading *shading;
-- GfxPath *savedPath;
-+ GfxState *savedState;
- double *ctm, *btm, *ptm;
- double m[6], ictm[6], m1[6];
- double xMin, yMin, xMax, yMax;
-@@ -1789,27 +1958,13 @@
- 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());
-- }
-+ savedState = saveStateStack();
-
- // clip to current path
- if (stroke) {
- state->clipToStrokePath();
- out->clipToStrokePath(state);
-- } else {
-+ } else if (!text) {
- state->clip();
- if (eoFill) {
- out->eoClip(state);
-@@ -1817,17 +1972,6 @@
- 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
-@@ -1861,11 +2005,39 @@
- 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);
-+ // 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);
-+
-+ // background color fill
-+ if (shading->getHasBackground()) {
-+ state->setFillColor(shading->getBackground());
-+ out->updateFillColor(state);
-+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
-+ state->moveTo(xMin, yMin);
-+ state->lineTo(xMax, yMin);
-+ state->lineTo(xMax, yMax);
-+ state->lineTo(xMin, yMax);
-+ state->closePath();
-+ out->fill(state);
-+ state->clearPath();
- }
-+
-+#if 1 //~tmp: turn off anti-aliasing temporarily
-+ out->setInShading(gTrue);
- #endif
-
- // do shading type-specific operations
-@@ -1890,28 +2062,28 @@
- }
-
- #if 1 //~tmp: turn off anti-aliasing temporarily
-- if (vaa) {
-- out->setVectorAntialias(gTrue);
-- }
-+ out->setInShading(gFalse);
- #endif
-
- // restore graphics state
-- restoreState();
-- state->setPath(savedPath);
-+ restoreStateStack(savedState);
- }
-
- void Gfx::opShFill(Object args[], int numArgs) {
- GfxShading *shading;
-- GfxPath *savedPath;
-+ GfxState *savedState;
- double xMin, yMin, xMax, yMax;
-
-+ if (!ocState) {
-+ return;
-+ }
-+
- if (!(shading = res->lookupShading(args[0].getName()))) {
- return;
- }
-
- // save current graphics state
-- savedPath = state->getPath()->copy();
-- saveState();
-+ savedState = saveStateStack();
-
- // clip to bbox
- if (shading->getHasBBox()) {
-@@ -1931,10 +2103,7 @@
- out->updateFillColorSpace(state);
-
- #if 1 //~tmp: turn off anti-aliasing temporarily
-- GBool vaa = out->getVectorAntialias();
-- if (vaa) {
-- out->setVectorAntialias(gFalse);
-- }
-+ out->setInShading(gTrue);
- #endif
-
- // do shading type-specific operations
-@@ -1959,14 +2128,11 @@
- }
-
- #if 1 //~tmp: turn off anti-aliasing temporarily
-- if (vaa) {
-- out->setVectorAntialias(gTrue);
-- }
-+ out->setInShading(gFalse);
- #endif
-
- // restore graphics state
-- restoreState();
-- state->setPath(savedPath);
-+ restoreStateStack(savedState);
-
- delete shading;
- }
-@@ -2100,16 +2266,16 @@
- double xMin, yMin, xMax, yMax;
- double x0, y0, x1, y1;
- double dx, dy, mul;
-- GBool dxZero, dyZero;
-+ GBool dxdyZero, horiz;
- double tMin, tMax, t, tx, ty;
-- double s[4], sMin, sMax, tmp;
-+ double 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;
-+ int i, j, k;
-
- if (out->useShadedFills() &&
- out->axialShadedFill(state, shading)) {
-@@ -2124,9 +2290,9 @@
- shading->getCoords(&x0, &y0, &x1, &y1);
- dx = x1 - x0;
- dy = y1 - y0;
-- dxZero = fabs(dx) < 0.01;
-- dyZero = fabs(dy) < 0.01;
-- if (dxZero && dyZero) {
-+ dxdyZero = fabs(dx) < 0.01 && fabs(dy) < 0.01;
-+ horiz = fabs(dy) < fabs(dx);
-+ if (dxdyZero) {
- tMin = tMax = 0;
- } else {
- mul = 1 / (dx * dx + dy * dy);
-@@ -2170,18 +2336,16 @@
- // 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:
-+ // (xMin, yMin, xMax, yMax). For -1 < |dy/dx| < 1, look at the
-+ // intersection with yMin, yMax:
- //
-- // s0 = (xMin - tx) / -dy
-- // s1 = (xMax - tx) / -dy
-- // s2 = (yMin - ty) / dx
-- // s3 = (yMax - ty) / dx
-+ // s0 = (yMin - ty) / dx
-+ // s1 = (yMax - ty) / dx
- //
-- // and we want the middle two s values.
-+ // else look at the intersection with xMin, xMax:
- //
-- // In the case where dx = 0, take s0 and s1; in the case where dy =
-- // 0, take s2 and s3.
-+ // s0 = (xMin - tx) / -dy
-+ // s1 = (xMax - tx) / -dy
- //
- // Each filled polygon is bounded by two of these line segments
- // perpdendicular to the t axis.
-@@ -2190,13 +2354,10 @@
- // 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
-+ // set up
- nComps = shading->getColorSpace()->getNComps();
- ta[0] = tMin;
-- next[0] = axialMaxSplits / 2;
-- ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax);
-- next[axialMaxSplits / 2] = axialMaxSplits;
-+ next[0] = axialMaxSplits;
- ta[axialMaxSplits] = tMax;
-
- // compute the color at t = tMin
-@@ -2214,32 +2375,19 @@
- // bounding box
- tx = x0 + tMin * dx;
- ty = y0 + tMin * dy;
-- if (dxZero && dyZero) {
-+ if (dxdyZero) {
- sMin = sMax = 0;
-- } else 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;
-+ if (horiz) {
-+ sMin = (yMin - ty) / dx;
-+ sMax = (yMax - ty) / dx;
-+ } else {
-+ sMin = (xMin - tx) / -dy;
-+ sMax = (xMax - tx) / -dy;
-+ }
-+ if (sMin > sMax) {
-+ tmp = sMin; sMin = sMax; sMax = tmp;
- }
-- sMin = s[1];
-- sMax = s[2];
- }
- ux0 = tx - sMin * dy;
- uy0 = ty + sMin * dx;
-@@ -2260,15 +2408,19 @@
- } else {
- tt = t0 + (t1 - t0) * ta[j];
- }
-- shading->getColor(tt, &color1);
-- for (k = 0; k < nComps; ++k) {
-- if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) {
-+ // require at least two splits (to avoid problems where the
-+ // color doesn't change smoothly along the t axis)
-+ if (j - i <= axialMaxSplits / 4) {
-+ shading->getColor(tt, &color1);
-+ for (k = 0; k < nComps; ++k) {
-+ if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) {
-+ break;
-+ }
-+ }
-+ if (k == nComps) {
- break;
- }
- }
-- if (k == nComps) {
-- break;
-- }
- k = (i + j) / 2;
- ta[k] = 0.5 * (ta[i] + ta[j]);
- next[i] = k;
-@@ -2286,32 +2438,19 @@
- // bounding box
- tx = x0 + ta[j] * dx;
- ty = y0 + ta[j] * dy;
-- if (dxZero && dyZero) {
-+ if (dxdyZero) {
- sMin = sMax = 0;
-- } else 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;
-+ if (horiz) {
-+ sMin = (yMin - ty) / dx;
-+ sMax = (yMax - ty) / dx;
-+ } else {
-+ sMin = (xMin - tx) / -dy;
-+ sMax = (xMax - tx) / -dy;
-+ }
-+ if (sMin > sMax) {
-+ tmp = sMin; sMin = sMax; sMax = tmp;
- }
-- sMin = s[1];
-- sMax = s[2];
- }
- ux1 = tx - sMin * dy;
- uy1 = ty + sMin * dx;
-@@ -2348,7 +2487,10 @@
- GfxColor colorA, colorB;
- double xa, ya, xb, yb, ra, rb;
- double ta, tb, sa, sb;
-- double sz, xz, yz, sMin, sMax;
-+ double sz, sMin, sMax, h;
-+ double sLeft, sRight, sTop, sBottom, sZero, sDiag;
-+ GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero;
-+ GBool haveSMin, haveSMax;
- GBool enclosed;
- int ia, ib, k, n;
- double *ctm;
-@@ -2367,23 +2509,23 @@
-
- // Compute the point at which r(s) = 0; check for the enclosed
- // circles case; and compute the angles for the tangent lines.
-- if (x0 == x1 && y0 == y1) {
-+ h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
-+ if (h == 0) {
- enclosed = gTrue;
- theta = 0; // make gcc happy
- sz = 0; // make gcc happy
-- } else if (r0 == r1) {
-+ } else if (r1 - r0 == 0) {
- enclosed = gFalse;
- theta = 0;
- sz = 0; // make gcc happy
-+ } else if (fabs(r1 - r0) >= h) {
-+ enclosed = gTrue;
-+ theta = 0; // make gcc happy
-+ sz = 0; // make gcc happy
- } else {
-+ enclosed = gFalse;
- sz = -r0 / (r1 - r0);
-- xz = x0 + sz * (x1 - x0);
-- yz = y0 + sz * (y1 - y0);
-- enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0;
-- theta = asin(r0 / sqrt((x0 - xz) * (x0 - xz) + (y0 - yz) * (y0 - yz)));
-- if (r0 > r1) {
-- theta = -theta;
-- }
-+ theta = asin((r1 - r0) / h);
- }
- if (enclosed) {
- alpha = 0;
-@@ -2397,59 +2539,101 @@
- sMin = 0;
- sMax = 1;
- } else {
-- sMin = 1;
-- sMax = 0;
-- // solve for x(s) + r(s) = xMin
-- if ((x1 + r1) - (x0 + r0) != 0) {
-- sa = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
-- if (sa < sMin) {
-- sMin = sa;
-- } else if (sa > sMax) {
-- sMax = sa;
-- }
-- }
-- // solve for x(s) - r(s) = xMax
-- if ((x1 - r1) - (x0 - r0) != 0) {
-- sa = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
-- if (sa < sMin) {
-- sMin = sa;
-- } else if (sa > sMax) {
-- sMax = sa;
-- }
-- }
-- // solve for y(s) + r(s) = yMin
-- if ((y1 + r1) - (y0 + r0) != 0) {
-- sa = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
-- if (sa < sMin) {
-- sMin = sa;
-- } else if (sa > sMax) {
-- sMax = sa;
-- }
-- }
-- // solve for y(s) - r(s) = yMax
-- if ((y1 - r1) - (y0 - r0) != 0) {
-- sa = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
-- if (sa < sMin) {
-- sMin = sa;
-- } else if (sa > sMax) {
-- sMax = sa;
-- }
-- }
-- // check against sz
-- if (r0 < r1) {
-- if (sMin < sz) {
-- sMin = sz;
-- }
-- } else if (r0 > r1) {
-- if (sMax > sz) {
-- sMax = sz;
-- }
-+ // solve x(sLeft) + r(sLeft) = xMin
-+ if ((haveSLeft = fabs((x1 + r1) - (x0 + r0)) > 0.000001)) {
-+ sLeft = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
-+ } else {
-+ sLeft = 0; // make gcc happy
- }
-- // check the 'extend' flags
-- if (!shading->getExtend0() && sMin < 0) {
-+ // solve x(sRight) - r(sRight) = xMax
-+ if ((haveSRight = fabs((x1 - r1) - (x0 - r0)) > 0.000001)) {
-+ sRight = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
-+ } else {
-+ sRight = 0; // make gcc happy
-+ }
-+ // solve y(sBottom) + r(sBottom) = yMin
-+ if ((haveSBottom = fabs((y1 + r1) - (y0 + r0)) > 0.000001)) {
-+ sBottom = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
-+ } else {
-+ sBottom = 0; // make gcc happy
-+ }
-+ // solve y(sTop) - r(sTop) = yMax
-+ if ((haveSTop = fabs((y1 - r1) - (y0 - r0)) > 0.000001)) {
-+ sTop = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
-+ } else {
-+ sTop = 0; // make gcc happy
-+ }
-+ // solve r(sZero) = 0
-+ if ((haveSZero = fabs(r1 - r0) > 0.000001)) {
-+ sZero = -r0 / (r1 - r0);
-+ } else {
-+ sZero = 0; // make gcc happy
-+ }
-+ // solve r(sDiag) = sqrt((xMax-xMin)^2 + (yMax-yMin)^2)
-+ if (haveSZero) {
-+ sDiag = (sqrt((xMax - xMin) * (xMax - xMin) +
-+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
-+ } else {
-+ sDiag = 0; // make gcc happy
-+ }
-+ // compute sMin
-+ if (shading->getExtend0()) {
-+ sMin = 0;
-+ haveSMin = gFalse;
-+ if (x0 < x1 && haveSLeft && sLeft < 0) {
-+ sMin = sLeft;
-+ haveSMin = gTrue;
-+ } else if (x0 > x1 && haveSRight && sRight < 0) {
-+ sMin = sRight;
-+ haveSMin = gTrue;
-+ }
-+ if (y0 < y1 && haveSBottom && sBottom < 0) {
-+ if (!haveSMin || sBottom > sMin) {
-+ sMin = sBottom;
-+ haveSMin = gTrue;
-+ }
-+ } else if (y0 > y1 && haveSTop && sTop < 0) {
-+ if (!haveSMin || sTop > sMin) {
-+ sMin = sTop;
-+ haveSMin = gTrue;
-+ }
-+ }
-+ if (haveSZero && sZero < 0) {
-+ if (!haveSMin || sZero > sMin) {
-+ sMin = sZero;
-+ }
-+ }
-+ } else {
- sMin = 0;
- }
-- if (!shading->getExtend1() && sMax > 1) {
-+ // compute sMax
-+ if (shading->getExtend1()) {
-+ sMax = 1;
-+ haveSMax = gFalse;
-+ if (x1 < x0 && haveSLeft && sLeft > 1) {
-+ sMax = sLeft;
-+ haveSMax = gTrue;
-+ } else if (x1 > x0 && haveSRight && sRight > 1) {
-+ sMax = sRight;
-+ haveSMax = gTrue;
-+ }
-+ if (y1 < y0 && haveSBottom && sBottom > 1) {
-+ if (!haveSMax || sBottom < sMax) {
-+ sMax = sBottom;
-+ haveSMax = gTrue;
-+ }
-+ } else if (y1 > y0 && haveSTop && sTop > 1) {
-+ if (!haveSMax || sTop < sMax) {
-+ sMax = sTop;
-+ haveSMax = gTrue;
-+ }
-+ }
-+ if (haveSZero && sDiag > 1) {
-+ if (!haveSMax || sDiag < sMax) {
-+ sMax = sDiag;
-+ }
-+ }
-+ } else {
- sMax = 1;
- }
- }
-@@ -2922,6 +3106,7 @@
- out->updateTextMat(state);
- out->updateTextPos(state);
- fontChanged = gTrue;
-+ textClipBBoxEmpty = gTrue;
- }
-
- void Gfx::opEndText(Object args[], int numArgs) {
-@@ -3028,19 +3213,23 @@
-
- void Gfx::opShowText(Object args[], int numArgs) {
- if (!state->getFont()) {
-- error(getPos(), "No font in show");
-+ error(errSyntaxError, getPos(), "No font in show");
- return;
- }
- if (fontChanged) {
- out->updateFont(state);
- fontChanged = gFalse;
- }
-- out->beginStringOp(state);
-- doShowText(args[0].getString());
-- out->endStringOp(state);
-+ if (ocState) {
-+ out->beginStringOp(state);
-+ doShowText(args[0].getString());
-+ out->endStringOp(state);
-+ } else {
-+ doIncCharCount(args[0].getString());
-+ }
- }
-
- void Gfx::opMoveShowText(Object args[], int numArgs) {
- double tx, ty;
-
- if (!state->getFont()) {
-@@ -3055,12 +3244,16 @@
- ty = state->getLineY() - state->getLeading();
- state->textMoveTo(tx, ty);
- out->updateTextPos(state);
-- out->beginStringOp(state);
-- doShowText(args[0].getString());
-- out->endStringOp(state);
-+ if (ocState) {
-+ out->beginStringOp(state);
-+ doShowText(args[0].getString());
-+ out->endStringOp(state);
-+ } else {
-+ doIncCharCount(args[0].getString());
-+ }
- }
-
- void Gfx::opMoveSetShowText(Object args[], int numArgs) {
- double tx, ty;
-
- if (!state->getFont()) {
-@@ -3079,9 +3272,13 @@
- out->updateWordSpace(state);
- out->updateCharSpace(state);
- out->updateTextPos(state);
-- out->beginStringOp(state);
-- doShowText(args[2].getString());
-- out->endStringOp(state);
-+ if (ocState) {
-+ out->beginStringOp(state);
-+ doShowText(args[2].getString());
-+ out->endStringOp(state);
-+ } else {
-+ doIncCharCount(args[2].getString());
-+ }
- }
-
- void Gfx::opShowSpaceText(Object args[], int numArgs) {
-@@ -3091,37 +3288,48 @@
- int i;
-
- if (!state->getFont()) {
-- error(getPos(), "No font in show/space");
-+ error(errSyntaxError, getPos(), "No font in show/space");
- return;
- }
- if (fontChanged) {
- out->updateFont(state);
- fontChanged = gFalse;
- }
-- out->beginStringOp(state);
-- wMode = state->getFont()->getWMode();
-- a = args[0].getArray();
-- for (i = 0; i < a->getLength(); ++i) {
-- a->get(i, &obj);
-- if (obj.isNum()) {
-- // this uses the absolute value of the font size to match
-- // Acrobat's behavior
-- if (wMode) {
-- state->textShift(0, -obj.getNum() * 0.001 *
-- fabs(state->getFontSize()));
-+ if (ocState) {
-+ out->beginStringOp(state);
-+ wMode = state->getFont()->getWMode();
-+ a = args[0].getArray();
-+ for (i = 0; i < a->getLength(); ++i) {
-+ a->get(i, &obj);
-+ if (obj.isNum()) {
-+ if (wMode) {
-+ state->textShift(0, -obj.getNum() * 0.001 *
-+ state->getFontSize());
-+ } else {
-+ state->textShift(-obj.getNum() * 0.001 *
-+ state->getFontSize() *
-+ state->getHorizScaling(), 0);
-+ }
-+ out->updateTextShift(state, obj.getNum());
-+ } else if (obj.isString()) {
-+ doShowText(obj.getString());
- } else {
-- state->textShift(-obj.getNum() * 0.001 *
-- fabs(state->getFontSize()), 0);
-+ error(errSyntaxError, getPos(),
-+ "Element of show/space array must be number or string");
- }
-- out->updateTextShift(state, obj.getNum());
-- } else if (obj.isString()) {
-- doShowText(obj.getString());
-- } else {
-- error(getPos(), "Element of show/space array must be number or string");
-+ obj.free();
-+ }
-+ out->endStringOp(state);
-+ } else {
-+ a = args[0].getArray();
-+ for (i = 0; i < a->getLength(); ++i) {
-+ a->get(i, &obj);
-+ if (obj.isString()) {
-+ doIncCharCount(obj.getString());
-+ }
-+ obj.free();
- }
-- obj.free();
- }
-- out->endStringOp(state);
- }
-
- void Gfx::doShowText(GString *s) {
-@@ -3130,14 +3338,18 @@
- double riseX, riseY;
- CharCode code;
- Unicode u[8];
-- double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY;
-+ double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, ddx, ddy;
- double originX, originY, tOriginX, tOriginY;
-+ double x0, y0, x1, y1;
- double oldCTM[6], newCTM[6];
- double *mat;
- Object charProc;
- Dict *resDict;
- Parser *oldParser;
-+ GfxState *savedState;
- char *p;
-+ int render;
-+ GBool patternFill;
- int len, n, uLen, nChars, nSpaces, i;
-
- font = state->getFont();
-@@ -3147,6 +3359,28 @@
- out->beginString(state, s);
- }
-
-+ // if we're doing a pattern fill, set up clipping
-+ render = state->getRender();
-+ if (!(render & 1) &&
-+ state->getFillColorSpace()->getMode() == csPattern) {
-+ patternFill = gTrue;
-+ saveState();
-+ // disable fill, enable clipping, leave stroke unchanged
-+ if ((render ^ (render >> 1)) & 1) {
-+ render = 5;
-+ } else {
-+ render = 7;
-+ }
-+ state->setRender(render);
-+ out->updateRender(state);
-+ } else {
-+ patternFill = gFalse;
-+ }
-+
-+ state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
-+ x0 = state->getCurX() + riseX;
-+ y0 = state->getCurY() + riseY;
-+
- // handle a Type 3 char
- if (font->getType() == fontType3 && out->interpretType3Chars()) {
- mat = state->getCTM();
-@@ -3169,11 +3403,8 @@
- newCTM[3] *= state->getFontSize();
- newCTM[0] *= state->getHorizScaling();
- newCTM[2] *= state->getHorizScaling();
-- state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
- curX = state->getCurX();
- curY = state->getCurY();
-- lineX = state->getLineX();
-- lineY = state->getLineY();
- oldParser = parser;
- p = s->getCString();
- len = s->getLength();
-@@ -3189,11 +3420,12 @@
- dy *= state->getFontSize();
- state->textTransformDelta(dx, dy, &tdx, &tdy);
- state->transform(curX + riseX, curY + riseY, &x, &y);
-- saveState();
-+ savedState = saveStateStack();
- state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
- //~ the CTM concat values here are wrong (but never used)
- out->updateCTM(state, 1, 0, 0, 1, 0, 0);
-- if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy,
-+ state->transformDelta(dx, dy, &ddx, &ddy);
-+ if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy,
- code, u, uLen)) {
- ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
- if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
-@@ -3210,20 +3443,16 @@
- }
- charProc.free();
- }
-- restoreState();
-- // GfxState::restore() does *not* restore the current position,
-- // so we deal with it here using (curX, curY) and (lineX, lineY)
-+ restoreStateStack(savedState);
- curX += tdx;
- curY += tdy;
- state->moveTo(curX, curY);
-- state->textSetPos(lineX, lineY);
- p += n;
- len -= n;
- }
- parser = oldParser;
-
- } else if (out->useDrawChar()) {
-- state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
- p = s->getCString();
- len = s->getLength();
- while (len > 0) {
-@@ -3294,9 +3523,52 @@
- out->endString(state);
- }
-
-+ if (patternFill) {
-+ out->saveTextPos(state);
-+ // tell the OutputDev to do the clipping
-+ out->endTextObject(state);
-+ // set up a clipping bbox so doPatternText will work -- assume
-+ // that the text bounding box does not extend past the baseline in
-+ // any direction by more than twice the font size
-+ x1 = state->getCurX() + riseX;
-+ y1 = state->getCurY() + riseY;
-+ if (x0 > x1) {
-+ x = x0; x0 = x1; x1 = x;
-+ }
-+ if (y0 > y1) {
-+ y = y0; y0 = y1; y1 = y;
-+ }
-+ state->textTransformDelta(0, state->getFontSize(), &dx, &dy);
-+ state->textTransformDelta(state->getFontSize(), 0, &dx2, &dy2);
-+ dx = fabs(dx);
-+ dx2 = fabs(dx2);
-+ if (dx2 > dx) {
-+ dx = dx2;
-+ }
-+ dy = fabs(dy);
-+ dy2 = fabs(dy2);
-+ if (dy2 > dy) {
-+ dy = dy2;
-+ }
-+ state->clipToRect(x0 - 2 * dx, y0 - 2 * dy, x1 + 2 * dx, y1 + 2 * dy);
-+ // set render mode to fill-only
-+ state->setRender(0);
-+ out->updateRender(state);
-+ doPatternText();
-+ restoreState();
-+ out->restoreTextPos(state);
-+ }
-+
- updateLevel += 10 * s->getLength();
- }
-
-+// NB: this is only called when ocState is false.
-+void Gfx::doIncCharCount(GString *s) {
-+ if (out->needCharCount()) {
-+ out->incCharCount(s->getLength());
-+ }
-+}
-+
- //------------------------------------------------------------------------
- // XObject operators
- //------------------------------------------------------------------------
-@@ -3308,8 +3580,11 @@
- Object opiDict;
- #endif
-
-+ if (!ocState && !out->needCharCount()) {
-+ return;
-+ }
- name = args[0].getName();
- if (!res->lookupXObject(name, &obj1)) {
- return;
- }
- if (!obj1.isStream()) {
+
@@ -3373,7 +3650,7 @@
GBool maskInvert;
Stream *maskStr;
@@ -1657,102 +580,6 @@ diff -ru xpdf-3.02/xpdf/Gfx.cc xpdf-3.03/xpdf/Gfx.cc
maskObj.free();
smaskObj.free();
}
-@@ -3683,11 +4014,12 @@
- double m[6], bbox[4];
- Object resObj;
- Dict *resDict;
-+ GBool oc, ocSaved;
- Object obj1, obj2, obj3;
- int i;
-
- // check for excessive recursion
- if (formDepth > 100) {
- return;
- }
-
-@@ -3697,7 +4029,20 @@
- // check form type
- dict->lookup("FormType", &obj1);
- if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) {
- error(errSyntaxError, getPos(), "Unknown form type");
-+ }
-+ obj1.free();
-+
-+ // check for optional content key
-+ ocSaved = ocState;
-+ dict->lookupNF("OC", &obj1);
-+ if (doc->getOptionalContent()->evalOCObject(&obj1, &oc) && !oc) {
-+ obj1.free();
-+ if (out->needCharCount()) {
-+ ocState = gFalse;
-+ } else {
-+ return;
-+ }
- }
- obj1.free();
-
-@@ -3705,7 +4050,8 @@
- dict->lookup("BBox", &bboxObj);
- if (!bboxObj.isArray()) {
- bboxObj.free();
- error(errSyntaxError, getPos(), "Bad form bounding box");
-+ ocState = ocSaved;
- return;
- }
- for (i = 0; i < 4; ++i) {
-@@ -3759,23 +4105,26 @@
-
- // draw it
- ++formDepth;
-- doForm1(str, resDict, m, bbox,
-- transpGroup, gFalse, blendingColorSpace, isolated, knockout);
-+ drawForm(str, resDict, m, bbox,
-+ transpGroup, gFalse, blendingColorSpace, isolated, knockout);
- --formDepth;
-
- if (blendingColorSpace) {
- delete blendingColorSpace;
- }
- resObj.free();
-+
-+ ocState = ocSaved;
- }
-
--void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
-- GBool transpGroup, GBool softMask,
-- GfxColorSpace *blendingColorSpace,
-- GBool isolated, GBool knockout,
-- GBool alpha, Function *transferFunc,
-- GfxColor *backdropColor) {
-+void Gfx::drawForm(Object *str, Dict *resDict, double *matrix, double *bbox,
-+ GBool transpGroup, GBool softMask,
-+ GfxColorSpace *blendingColorSpace,
-+ GBool isolated, GBool knockout,
-+ GBool alpha, Function *transferFunc,
-+ GfxColor *backdropColor) {
- Parser *oldParser;
-+ GfxState *savedState;
- double oldBaseMatrix[6];
- int i;
-
-@@ -3783,7 +4132,7 @@
- pushResources(resDict);
-
- // save current graphics state
-- saveState();
-+ savedState = saveStateStack();
-
- // kill any pre-existing path
- state->clearPath();
-@@ -3847,7 +4196,7 @@
- parser = oldParser;
-
- // restore graphics state
-- restoreState();
-+ restoreStateStack(savedState);
-
- // pop resource stack
- popResources();
@@ -3869,6 +4218,9 @@
Stream *str;
int c1, c2;
@@ -1848,44 +675,6 @@ diff -ru xpdf-3.02/xpdf/Gfx.cc xpdf-3.03/xpdf/Gfx.cc
printf("\n");
fflush(stdout);
}
-@@ -3996,45 +4419,23 @@
- dict->lookup("Resources", &resObj);
- resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
-
- // draw it
-- doForm1(str, resDict, m, bbox);
-+ drawForm(str, resDict, m, bbox);
-
- resObj.free();
- }
-@@ -4168,6 +4598,27 @@
- out->restoreState(state);
- }
-
-+// Create a new state stack, and initialize it with a copy of the
-+// current state.
-+GfxState *Gfx::saveStateStack() {
-+ GfxState *oldState;
-+
-+ out->saveState(state);
-+ oldState = state;
-+ state = state->copy(gTrue);
-+ return oldState;
-+}
-+
-+// Switch back to the previous state stack.
-+void Gfx::restoreStateStack(GfxState *oldState) {
-+ while (state->hasSaves()) {
-+ restoreState();
-+ }
-+ delete state;
-+ state = oldState;
-+ out->restoreState(state);
-+}
-+
- void Gfx::pushResources(Dict *resDict) {
- res = new GfxResources(xref, resDict, res);
- }
diff -ru xpdf-3.02/xpdf/GfxFont.cc xpdf-3.03/xpdf/GfxFont.cc
--- xpdf-3.02/xpdf/GfxFont.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/GfxFont.cc 2011-08-15 23:08:53.000000000 +0200
@@ -3151,92 +1940,6 @@ diff -ru xpdf-3.02/xpdf/GfxFont.h xpdf-3.03/xpdf/GfxFont.h
+ GBool ctuUsesCharCode; // true: ctu maps char code to Unicode;
+ // false: ctu maps CID to Unicode
GfxFontCIDWidths widths; // character widths
-diff -ru xpdf-3.02/xpdf/Gfx.h xpdf-3.03/xpdf/Gfx.h
---- xpdf-3.02/xpdf/Gfx.h 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/xpdf/Gfx.h 2011-08-15 23:08:53.000000000 +0200
-@@ -18,6 +18,8 @@
- #include "gtypes.h"
-
- class GString;
-+class GList;
- class PDFDoc;
- class XRef;
- class Array;
- class Stream;
-@@ -141,8 +169,16 @@
- // Get the current graphics state object.
- GfxState *getState() { return state; }
-
-+ void drawForm(Object *str, Dict *resDict, double *matrix, double *bbox,
-+ GBool transpGroup = gFalse, GBool softMask = gFalse,
-+ GfxColorSpace *blendingColorSpace = NULL,
-+ GBool isolated = gFalse, GBool knockout = gFalse,
-+ GBool alpha = gFalse, Function *transferFunc = NULL,
-+ GfxColor *backdropColor = NULL);
-+
- private:
-
- PDFDoc *doc;
- XRef *xref; // the xref table for this PDF file
- OutputDev *out; // output device
- GBool subPage; // is this a sub-page object?
-@@ -157,6 +193,12 @@
- double baseMatrix[6]; // default matrix for most recent
- // page/form/pattern
- int formDepth;
-+ double textClipBBox[4]; // text clipping bounding box
-+ GBool textClipBBoxEmpty; // true if textClipBBox has not been
-+ // initialized yet
-+ GBool ocState; // true if drawing is enabled, false if
-+ // disabled
-+ GList *markedContentStack; // BMC/BDC/EMC stack [GfxMarkedContent]
-
- Parser *parser; // parser for page content stream(s)
-
-@@ -224,10 +266,13 @@
- void opCloseEOFillStroke(Object args[], int numArgs);
- void doPatternFill(GBool eoFill);
- void doPatternStroke();
-+ void doPatternText();
-+ void doPatternImageMask(Object *ref, Stream *str, int width, int height,
-+ GBool invert, GBool inlineImg);
- void doTilingPatternFill(GfxTilingPattern *tPat,
-- GBool stroke, GBool eoFill);
-+ GBool stroke, GBool eoFill, GBool text);
- void doShadingPatternFill(GfxShadingPattern *sPat,
-- GBool stroke, GBool eoFill);
-+ GBool stroke, GBool eoFill, GBool text);
- void opShFill(Object args[], int numArgs);
- void doFunctionShFill(GfxFunctionShading *shading);
- void doFunctionShFill1(GfxFunctionShading *shading,
-@@ -274,17 +319,12 @@
- void opMoveSetShowText(Object args[], int numArgs);
- void opShowSpaceText(Object args[], int numArgs);
- void doShowText(GString *s);
-+ void doIncCharCount(GString *s);
-
- // XObject operators
- void opXObject(Object args[], int numArgs);
- void doImage(Object *ref, Stream *str, GBool inlineImg);
- void doForm(Object *str);
-- void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
-- GBool transpGroup = gFalse, GBool softMask = gFalse,
-- GfxColorSpace *blendingColorSpace = NULL,
-- GBool isolated = gFalse, GBool knockout = gFalse,
-- GBool alpha = gFalse, Function *transferFunc = NULL,
-- GfxColor *backdropColor = NULL);
-
- // in-line image operators
- void opBeginImage(Object args[], int numArgs);
-@@ -305,6 +345,8 @@
- void opEndMarkedContent(Object args[], int numArgs);
- void opMarkPoint(Object args[], int numArgs);
-
-+ GfxState *saveStateStack();
-+ void restoreStateStack(GfxState *oldState);
- void pushResources(Dict *resDict);
- void popResources();
- };
diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
--- xpdf-3.02/xpdf/GfxState.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/GfxState.cc 2011-08-15 23:08:53.000000000 +0200
@@ -3611,14 +2314,6 @@ diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
++n;
justMoved = gFalse;
}
-@@ -3658,6 +3872,7 @@
- strokeOpacity = 1;
- fillOverprint = gFalse;
- strokeOverprint = gFalse;
-+ overprintMode = 0;
- transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL;
-
- lineWidth = 1;
@@ -3719,13 +3934,10 @@
// this gets set to NULL by restore()
delete path;
@@ -3628,83 +2323,6 @@ diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
- }
}
- // Used for copy();
--GfxState::GfxState(GfxState *state) {
-+GfxState::GfxState(GfxState *state, GBool copyPath) {
- int i;
-
- memcpy(this, state, sizeof(GfxState));
-@@ -3750,6 +3962,9 @@
- lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
- memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
- }
-+ if (copyPath) {
-+ path = state->path->copy();
-+ }
- saved = NULL;
- }
-
-@@ -4056,6 +4271,60 @@
- }
- }
-
-+void GfxState::clipToRect(double xMin, double yMin, double xMax, double yMax) {
-+ double x, y, xMin1, yMin1, xMax1, yMax1;
-+
-+ transform(xMin, yMin, &x, &y);
-+ xMin1 = xMax1 = x;
-+ yMin1 = yMax1 = y;
-+ transform(xMax, yMin, &x, &y);
-+ if (x < xMin1) {
-+ xMin1 = x;
-+ } else if (x > xMax1) {
-+ xMax1 = x;
-+ }
-+ if (y < yMin1) {
-+ yMin1 = y;
-+ } else if (y > yMax1) {
-+ yMax1 = y;
-+ }
-+ transform(xMax, yMax, &x, &y);
-+ if (x < xMin1) {
-+ xMin1 = x;
-+ } else if (x > xMax1) {
-+ xMax1 = x;
-+ }
-+ if (y < yMin1) {
-+ yMin1 = y;
-+ } else if (y > yMax1) {
-+ yMax1 = y;
-+ }
-+ transform(xMin, yMax, &x, &y);
-+ if (x < xMin1) {
-+ xMin1 = x;
-+ } else if (x > xMax1) {
-+ xMax1 = x;
-+ }
-+ if (y < yMin1) {
-+ yMin1 = y;
-+ } else if (y > yMax1) {
-+ yMax1 = y;
-+ }
-+
-+ if (xMin1 > clipXMin) {
-+ clipXMin = xMin1;
-+ }
-+ if (yMin1 > clipYMin) {
-+ clipYMin = yMin1;
-+ }
-+ if (xMax1 < clipXMax) {
-+ clipXMax = xMax1;
-+ }
-+ if (yMax1 < clipYMax) {
-+ clipYMax = yMax1;
-+ }
-+}
-+
- void GfxState::textShift(double tx, double ty) {
- double dx, dy;
-
diff -ru xpdf-3.02/xpdf/GfxState.h xpdf-3.03/xpdf/GfxState.h
--- xpdf-3.02/xpdf/GfxState.h 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/GfxState.h 2011-08-15 23:08:53.000000000 +0200
@@ -3729,57 +2347,6 @@ diff -ru xpdf-3.02/xpdf/GfxState.h xpdf-3.03/xpdf/GfxState.h
double // minimum values for each component
decodeLow[gfxColorMaxComps];
double // max - min value for each component
-@@ -1023,7 +1046,8 @@
- ~GfxState();
-
- // Copy.
-- GfxState *copy() { return new GfxState(this); }
-+ GfxState *copy(GBool copyPath = gFalse)
-+ { return new GfxState(this, copyPath); }
-
- // Accessors.
- double getHDPI() { return hDPI; }
-@@ -1059,6 +1083,7 @@
- double getStrokeOpacity() { return strokeOpacity; }
- GBool getFillOverprint() { return fillOverprint; }
- GBool getStrokeOverprint() { return strokeOverprint; }
-+ int getOverprintMode() { return overprintMode; }
- Function **getTransfer() { return transfer; }
- double getLineWidth() { return lineWidth; }
- void getLineDash(double **dash, int *length, double *start)
-@@ -1127,6 +1152,7 @@
- void setStrokeOpacity(double opac) { strokeOpacity = opac; }
- void setFillOverprint(GBool op) { fillOverprint = op; }
- void setStrokeOverprint(GBool op) { strokeOverprint = op; }
-+ void setOverprintMode(int opm) { overprintMode = opm; }
- void setTransfer(Function **funcs);
- void setLineWidth(double width) { lineWidth = width; }
- void setLineDash(double *dash, int length, double start);
-@@ -1169,6 +1195,7 @@
- // Update clip region.
- void clip();
- void clipToStrokePath();
-+ void clipToRect(double xMin, double yMin, double xMax, double yMax);
-
- // Text position.
- void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
-@@ -1204,6 +1231,7 @@
- double strokeOpacity; // stroke opacity
- GBool fillOverprint; // fill overprint
- GBool strokeOverprint; // stroke overprint
-+ int overprintMode; // overprint mode ("OPM")
- Function *transfer[4]; // transfer function (entries may be: all
- // NULL = identity; last three NULL =
- // single function; all four non-NULL =
-@@ -1238,7 +1266,7 @@
-
- GfxState *saved; // next GfxState on stack
-
-- GfxState(GfxState *state);
-+ GfxState(GfxState *state, GBool copyPath);
- };
-
- #endif
diff -ru xpdf-3.02/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc
--- xpdf-3.02/xpdf/GlobalParams.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/GlobalParams.cc 2011-08-15 23:08:53.000000000 +0200
@@ -4789,22 +3356,6 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc
GBool GlobalParams::getStrokeAdjust() {
GBool f;
-@@ -2418,6 +2579,24 @@
- return thresh;
- }
-
-+double GlobalParams::getMinLineWidth() {
-+ double w;
-+
-+ lockGlobalParams;
-+ w = minLineWidth;
-+ unlockGlobalParams;
-+ return w;
-+}
-+
- GBool GlobalParams::getMapNumericCharNames() {
- GBool map;
-
@@ -2552,14 +2731,9 @@
// functions to set parameters
//------------------------------------------------------------------------
@@ -5063,15 +3614,6 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h
GBool strokeAdjust; // stroke adjustment enable flag
ScreenType screenType; // halftone screen type
int screenSize; // screen matrix size
-@@ -434,6 +438,10 @@
- double screenGamma; // screen gamma correction
- double screenBlackThreshold; // screen black clamping threshold
- double screenWhiteThreshold; // screen white clamping threshold
-+ double minLineWidth; // minimum line width
-+ GBool overprintPreview; // enable overprint preview
- GString *urlCommand; // command executed for URL links
- GString *movieCommand; // command executed for movie annotations
- GBool mapNumericCharNames; // map numeric char names (from font subsets)?
Només a xpdf-3.03/xpdf: OptionalContent.cc
Només a xpdf-3.03/xpdf: OptionalContent.h
diff -ru xpdf-3.02/xpdf/OutputDev.cc xpdf-3.03/xpdf/OutputDev.cc
@@ -5099,78 +3641,6 @@ diff -ru xpdf-3.02/xpdf/OutputDev.cc xpdf-3.03/xpdf/OutputDev.cc
void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg) {
-diff -ru xpdf-3.02/xpdf/OutputDev.h xpdf-3.03/xpdf/OutputDev.h
---- xpdf-3.02/xpdf/OutputDev.h 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/xpdf/OutputDev.h 2011-08-15 23:08:53.000000000 +0200
-@@ -19,6 +19,7 @@
- #include "CharTypes.h"
-
- class GString;
-+class Gfx;
- class GfxState;
- struct GfxColor;
- class GfxColorSpace;
-@@ -76,6 +77,11 @@
- // Does this device need non-text content?
- virtual GBool needNonText() { return gTrue; }
-
-+ // Does this device require incCharCount to be called for text on
-+ // non-shown layers?
-+ virtual GBool needCharCount() { return gFalse; }
-+
-+
- //----- initialization and control
-
- // Set default transform matrix.
-@@ -135,6 +141,7 @@
- virtual void updateStrokeOpacity(GfxState *state) {}
- virtual void updateFillOverprint(GfxState *state) {}
- virtual void updateStrokeOverprint(GfxState *state) {}
-+ virtual void updateOverprintMode(GfxState *state) {}
- virtual void updateTransfer(GfxState *state) {}
-
- //----- update text state
-@@ -147,12 +154,14 @@
- virtual void updateHorizScaling(GfxState *state) {}
- virtual void updateTextPos(GfxState *state) {}
- virtual void updateTextShift(GfxState *state, double shift) {}
-+ virtual void saveTextPos(GfxState *state) {}
-+ virtual void restoreTextPos(GfxState *state) {}
-
- //----- path painting
- virtual void stroke(GfxState *state) {}
- virtual void fill(GfxState *state) {}
- virtual void eoFill(GfxState *state) {}
-@@ -185,11 +194,18 @@
- CharCode code, Unicode *u, int uLen);
- virtual void endType3Char(GfxState *state) {}
- virtual void endTextObject(GfxState *state) {}
-+ virtual void incCharCount(int nChars) {}
-
- //----- image drawing
- virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg);
-+ virtual void setSoftMaskFromImageMask(GfxState *state,
-+ Object *ref, Stream *str,
-+ int width, int height, GBool invert,
-+ GBool inlineImg);
- virtual void drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg);
-@@ -234,11 +250,10 @@
- virtual void clearSoftMask(GfxState *state) {}
-
- //----- links
- virtual void processLink(Link *link) {}
-
- #if 1 //~tmp: turn off anti-aliasing temporarily
-- virtual GBool getVectorAntialias() { return gFalse; }
-- virtual void setVectorAntialias(GBool vaa) {}
-+ virtual void setInShading(GBool sh) {}
- #endif
-
- private:
diff -ru xpdf-3.02/xpdf/PDFDoc.cc xpdf-3.03/xpdf/PDFDoc.cc
--- xpdf-3.02/xpdf/PDFDoc.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/PDFDoc.cc 2011-08-15 23:08:53.000000000 +0200
@@ -7946,14 +6416,6 @@ diff -ru xpdf-3.02/xpdf/PSOutputDev.cc xpdf-3.03/xpdf/PSOutputDev.cc
void PSOutputDev::endPage() {
@@ -3458,25 +3693,33 @@
-+void PSOutputDev::saveTextPos(GfxState *state) {
-+ writePS("currentpoint\n");
-+}
-+
-+void PSOutputDev::restoreTextPos(GfxState *state) {
-+ writePS("m\n");
-+}
-+
void PSOutputDev::stroke(GfxState *state) {
doPath(state->getPath());
- if (t3String) {
@@ -8687,17 +7149,6 @@ diff -ru xpdf-3.02/xpdf/PSOutputDev.h xpdf-3.03/xpdf/PSOutputDev.h
// Destructor -- writes the trailer and closes the file.
virtual ~PSOutputDev();
-@@ -171,12 +189,14 @@
- virtual void updateHorizScaling(GfxState *state);
- virtual void updateTextPos(GfxState *state);
- virtual void updateTextShift(GfxState *state, double shift);
-+ virtual void saveTextPos(GfxState *state);
-+ virtual void restoreTextPos(GfxState *state);
-
- //----- path painting
- virtual void stroke(GfxState *state);
- virtual void fill(GfxState *state);
- virtual void eoFill(GfxState *state);
@@ -244,10 +264,10 @@
private:
@@ -8792,2031 +7243,6 @@ diff -ru xpdf-3.02/xpdf/PSOutputDev.h xpdf-3.03/xpdf/PSOutputDev.h
friend class WinPDFPrinter;
};
-diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev..cc
---- xpdf-3.02/xpdf/SplashOutputDev.cc 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/xpdf/SplashOutputDev.cc 2011-08-15 23:08:53.000000000 +0200
-@@ -14,14 +14,18 @@
-
- #include <string.h>
- #include <math.h>
-+#include <limits.h>
- #include "gfile.h"
- #include "GlobalParams.h"
- #include "Error.h"
- #include "Object.h"
-+#include "Gfx.h"
- #include "GfxFont.h"
- #include "Link.h"
- #include "CharCodeToUnicode.h"
- #include "FontEncodingTables.h"
-+#include "BuiltinFont.h"
-+#include "BuiltinFontTables.h"
- #include "FoFiTrueType.h"
- #include "SplashBitmap.h"
- #include "SplashGlyphBitmap.h"
-@@ -45,6 +49,13 @@
-
- //------------------------------------------------------------------------
-
-+// Type 3 font cache size parameters
-+#define type3FontCacheAssoc 8
-+#define type3FontCacheMaxSets 8
-+#define type3FontCacheSize (128*1024)
-+
-+//------------------------------------------------------------------------
-+
- // Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
- static inline Guchar div255(int x) {
- return (Guchar)((x + (x >> 8) + 0x80) >> 8);
-@@ -180,64 +191,100 @@
- }
- }
-
--static void cvtRGBToHSV(Guchar r, Guchar g, Guchar b, int *h, int *s, int *v) {
-- int cmax, cmid, cmin, x;
-+static int getLum(int r, int g, int b) {
-+ return (int)(0.3 * r + 0.59 * g + 0.11 * b);
-+}
-
-- if (r >= g) {
-- if (g >= b) { x = 0; cmax = r; cmid = g; cmin = b; }
-- else if (b >= r) { x = 4; cmax = b; cmid = r; cmin = g; }
-- else { x = 5; cmax = r; cmid = b; cmin = g; }
-- } else {
-- if (r >= b) { x = 1; cmax = g; cmid = r; cmin = b; }
-- else if (g >= b) { x = 2; cmax = g; cmid = b; cmin = r; }
-- else { x = 3; cmax = b; cmid = g; cmin = r; }
-- }
-- if (cmax == cmin) {
-- *h = *s = 0;
-+static int getSat(int r, int g, int b) {
-+ int rgbMin, rgbMax;
-+
-+ rgbMin = rgbMax = r;
-+ if (g < rgbMin) {
-+ rgbMin = g;
-+ } else if (g > rgbMax) {
-+ rgbMax = g;
-+ }
-+ if (b < rgbMin) {
-+ rgbMin = b;
-+ } else if (b > rgbMax) {
-+ rgbMax = b;
-+ }
-+ return rgbMax - rgbMin;
-+}
-+
-+static void clipColor(int rIn, int gIn, int bIn,
-+ Guchar *rOut, Guchar *gOut, Guchar *bOut) {
-+ int lum, rgbMin, rgbMax;
-+
-+ lum = getLum(rIn, gIn, bIn);
-+ rgbMin = rgbMax = rIn;
-+ if (gIn < rgbMin) {
-+ rgbMin = gIn;
-+ } else if (gIn > rgbMax) {
-+ rgbMax = gIn;
-+ }
-+ if (bIn < rgbMin) {
-+ rgbMin = bIn;
-+ } else if (bIn > rgbMax) {
-+ rgbMax = bIn;
-+ }
-+ if (rgbMin < 0) {
-+ *rOut = (Guchar)(lum + ((rIn - lum) * lum) / (lum - rgbMin));
-+ *gOut = (Guchar)(lum + ((gIn - lum) * lum) / (lum - rgbMin));
-+ *bOut = (Guchar)(lum + ((bIn - lum) * lum) / (lum - rgbMin));
-+ } else if (rgbMax > 255) {
-+ *rOut = (Guchar)(lum + ((rIn - lum) * (255 - lum)) / (rgbMax - lum));
-+ *gOut = (Guchar)(lum + ((gIn - lum) * (255 - lum)) / (rgbMax - lum));
-+ *bOut = (Guchar)(lum + ((bIn - lum) * (255 - lum)) / (rgbMax - lum));
- } else {
-- *h = x * 60;
-- if (x & 1) {
-- *h += ((cmax - cmid) * 60) / (cmax - cmin);
-- } else {
-- *h += ((cmid - cmin) * 60) / (cmax - cmin);
-- }
-- *s = (255 * (cmax - cmin)) / cmax;
-+ *rOut = rIn;
-+ *gOut = gIn;
-+ *bOut = bIn;
- }
-- *v = cmax;
- }
-
--static void cvtHSVToRGB(int h, int s, int v, Guchar *r, Guchar *g, Guchar *b) {
-- int x, f, cmax, cmid, cmin;
-+static void setLum(Guchar rIn, Guchar gIn, Guchar bIn, int lum,
-+ Guchar *rOut, Guchar *gOut, Guchar *bOut) {
-+ int d;
-+
-+ d = lum - getLum(rIn, gIn, bIn);
-+ clipColor(rIn + d, gIn + d, bIn + d, rOut, gOut, bOut);
-+}
-+
-+static void setSat(Guchar rIn, Guchar gIn, Guchar bIn, int sat,
-+ Guchar *rOut, Guchar *gOut, Guchar *bOut) {
-+ int rgbMin, rgbMid, rgbMax;
-+ Guchar *minOut, *midOut, *maxOut;
-
-- if (s == 0) {
-- *r = *g = *b = v;
-+ if (rIn < gIn) {
-+ rgbMin = rIn; minOut = rOut;
-+ rgbMid = gIn; midOut = gOut;
- } else {
-- x = h / 60;
-- f = h % 60;
-- cmax = v;
-- if (x & 1) {
-- cmid = div255(v * 255 - ((s * f) / 60));
-- } else {
-- cmid = div255(v * (255 - ((s * (60 - f)) / 60)));
-- }
-- cmin = div255(v * (255 - s));
-- switch (x) {
-- case 0: *r = cmax; *g = cmid; *b = cmin; break;
-- case 1: *g = cmax; *r = cmid; *b = cmin; break;
-- case 2: *g = cmax; *b = cmid; *r = cmin; break;
-- case 3: *b = cmax; *g = cmid; *r = cmin; break;
-- case 4: *b = cmax; *r = cmid; *g = cmin; break;
-- case 5: *r = cmax; *b = cmid; *g = cmin; break;
-- }
-+ rgbMin = gIn; minOut = gOut;
-+ rgbMid = rIn; midOut = rOut;
- }
-+ if (bIn > rgbMid) {
-+ rgbMax = bIn; maxOut = bOut;
-+ } else if (bIn > rgbMin) {
-+ rgbMax = rgbMid; maxOut = midOut;
-+ rgbMid = bIn; midOut = bOut;
-+ } else {
-+ rgbMax = rgbMid; maxOut = midOut;
-+ rgbMid = rgbMin; midOut = minOut;
-+ rgbMin = bIn; minOut = bOut;
-+ }
-+ if (rgbMax > rgbMin) {
-+ *midOut = (Guchar)((rgbMid - rgbMin) * sat) / (rgbMax - rgbMin);
-+ *maxOut = (Guchar)sat;
-+ } else {
-+ *midOut = *maxOut = 0;
-+ }
-+ *minOut = 0;
- }
-
- static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
-- int hs, ss, vs, hd, sd, vd;
--#if SPLASH_CMYK
-- Guchar r, g, b;
--#endif
-+ Guchar r0, g0, b0, r1, g1, b1;
-
- switch (cm) {
- case splashModeMono1:
-@@ -246,25 +293,22 @@
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
-- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
-- cvtHSVToRGB(hs, sd, vd, &blend[0], &blend[1], &blend[2]);
-+ setSat(src[0], src[1], src[2], getSat(dest[0], dest[1], dest[2]),
-+ &r0, &g0, &b0);
-+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
-+ &blend[0], &blend[1], &blend[2]);
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- //~ (0xff - ...) should be clipped
-- cvtRGBToHSV(0xff - (src[0] + src[3]),
-- 0xff - (src[1] + src[3]),
-- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
-- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
-- 0xff - (dest[1] + dest[3]),
-- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
-- cvtHSVToRGB(hs, sd, vd, &r, &g, &b);
-- //~ should do black generation
-- blend[0] = 0xff - r;
-- blend[1] = 0xff - g;
-- blend[2] = 0xff - b;
-- blend[3] = 0;
-+ // NB: inputs have already been converted to additive mode
-+ setSat(src[0], src[1], src[2], getSat(dest[0], dest[1], dest[2]),
-+ &r0, &g0, &b0);
-+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
-+ &r1, &g1, &b1);
-+ blend[0] = r1;
-+ blend[1] = g1;
-+ blend[2] = b1;
-+ blend[3] = dest[3];
- break;
- #endif
- }
-@@ -273,10 +317,7 @@
- static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend,
- SplashColorMode cm) {
-- int hs, ss, vs, hd, sd, vd;
--#if SPLASH_CMYK
-- Guchar r, g, b;
--#endif
-+ Guchar r0, g0, b0, r1, g1, b1;
-
- switch (cm) {
- case splashModeMono1:
-@@ -285,25 +326,22 @@
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
-- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
-- cvtHSVToRGB(hd, ss, vd, &blend[0], &blend[1], &blend[2]);
-+ setSat(dest[0], dest[1], dest[2], getSat(src[0], src[1], src[2]),
-+ &r0, &g0, &b0);
-+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
-+ &blend[0], &blend[1], &blend[2]);
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- //~ (0xff - ...) should be clipped
-- cvtRGBToHSV(0xff - (src[0] + src[3]),
-- 0xff - (src[1] + src[3]),
-- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
-- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
-- 0xff - (dest[1] + dest[3]),
-- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
-- cvtHSVToRGB(hd, ss, vd, &r, &g, &b);
-- //~ should do black generation
-- blend[0] = 0xff - r;
-- blend[1] = 0xff - g;
-- blend[2] = 0xff - b;
-- blend[3] = 0;
-+ // NB: inputs have already been converted to additive mode
-+ setSat(dest[0], dest[1], dest[2], getSat(src[0], src[1], src[2]),
-+ &r0, &g0, &b0);
-+ setLum(r0, g0, b0, getLum(dest[0], dest[1], dest[2]),
-+ &r1, &g1, &b1);
-+ blend[0] = r1;
-+ blend[1] = g1;
-+ blend[2] = b1;
-+ blend[3] = dest[3];
- break;
- #endif
- }
-@@ -311,7 +349,6 @@
-
- static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
-- int hs, ss, vs, hd, sd, vd;
- #if SPLASH_CMYK
- Guchar r, g, b;
- #endif
-@@ -323,25 +360,18 @@
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
-- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
-- cvtHSVToRGB(hs, ss, vd, &blend[0], &blend[1], &blend[2]);
-+ setLum(src[0], src[1], src[2], getLum(dest[0], dest[1], dest[2]),
-+ &blend[0], &blend[1], &blend[2]);
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- //~ (0xff - ...) should be clipped
-- cvtRGBToHSV(0xff - (src[0] + src[3]),
-- 0xff - (src[1] + src[3]),
-- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
-- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
-- 0xff - (dest[1] + dest[3]),
-- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
-- cvtHSVToRGB(hs, ss, vd, &r, &g, &b);
-- //~ should do black generation
-- blend[0] = 0xff - r;
-- blend[1] = 0xff - g;
-- blend[2] = 0xff - b;
-- blend[3] = 0;
-+ // NB: inputs have already been converted to additive mode
-+ setLum(src[0], src[1], src[2], getLum(dest[0], dest[1], dest[2]),
-+ &r, &g, &b);
-+ blend[0] = r;
-+ blend[1] = g;
-+ blend[2] = b;
-+ blend[3] = dest[3];
- break;
- #endif
- }
-@@ -350,7 +380,6 @@
- static void splashOutBlendLuminosity(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend,
- SplashColorMode cm) {
-- int hs, ss, vs, hd, sd, vd;
- #if SPLASH_CMYK
- Guchar r, g, b;
- #endif
-@@ -362,25 +391,18 @@
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs);
-- cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd);
-- cvtHSVToRGB(hd, sd, vs, &blend[0], &blend[1], &blend[2]);
-+ setLum(dest[0], dest[1], dest[2], getLum(src[0], src[1], src[2]),
-+ &blend[0], &blend[1], &blend[2]);
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- //~ (0xff - ...) should be clipped
-- cvtRGBToHSV(0xff - (src[0] + src[3]),
-- 0xff - (src[1] + src[3]),
-- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
-- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
-- 0xff - (dest[1] + dest[3]),
-- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
-- cvtHSVToRGB(hd, sd, vs, &r, &g, &b);
-- //~ should do black generation
-- blend[0] = 0xff - r;
-- blend[1] = 0xff - g;
-- blend[2] = 0xff - b;
-- blend[3] = 0;
-+ // NB: inputs have already been converted to additive mode
-+ setLum(dest[0], dest[1], dest[2], getLum(src[0], src[1], src[2]),
-+ &r, &g, &b);
-+ blend[0] = r;
-+ blend[1] = g;
-+ blend[2] = b;
-+ blend[3] = src[3];
- break;
- #endif
- }
-@@ -510,21 +503,23 @@
- glyphW = glyphWA;
- glyphH = glyphHA;
- validBBox = validBBoxA;
-+ // sanity check for excessively large glyphs (which most likely
-+ // indicate an incorrect BBox)
-+ i = glyphW * glyphH;
-+ if (i > 100000 || glyphW > INT_MAX / glyphH || glyphW <= 0 || glyphH <= 0) {
-+ glyphW = glyphH = 100;
-+ validBBox = gFalse;
-+ }
- if (aa) {
- glyphSize = glyphW * glyphH;
- } else {
- glyphSize = ((glyphW + 7) >> 3) * glyphH;
- }
-- cacheAssoc = 8;
-- if (glyphSize <= 256) {
-- cacheSets = 8;
-- } else if (glyphSize <= 512) {
-- cacheSets = 4;
-- } else if (glyphSize <= 1024) {
-- cacheSets = 2;
-- } else {
-- cacheSets = 1;
-- }
-+ cacheAssoc = type3FontCacheAssoc;
-+ for (cacheSets = type3FontCacheMaxSets;
-+ cacheSets > 1 &&
-+ cacheSets * cacheAssoc * glyphSize > type3FontCacheSize;
-+ cacheSets >>= 1) ;
- cacheData = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
- cacheTags = (T3FontCacheTag *)gmallocn(cacheSets * cacheAssoc,
- sizeof(T3FontCacheTag));
-@@ -584,6 +579,7 @@
- colorMode = colorModeA;
- bitmapRowPad = bitmapRowPadA;
- bitmapTopDown = bitmapTopDownA;
-+ bitmapUpsideDown = gFalse;
- allowAntialias = allowAntialiasA;
- vectorAntialias = allowAntialias &&
- globalParams->getVectorAntialias() &&
-@@ -591,12 +587,15 @@
- setupScreenParams(72.0, 72.0);
- reverseVideo = reverseVideoA;
- splashColorCopy(paperColor, paperColorA);
-+ skipHorizText = gFalse;
-+ skipRotatedText = gFalse;
-
- xref = NULL;
-
- bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
- splash = new Splash(bitmap, vectorAntialias, &screenParams);
-+ splash->setMinLineWidth(globalParams->getMinLineWidth());
- splash->clear(paperColor, 0);
-
- fontEngine = NULL;
-@@ -609,6 +608,8 @@
- textClipPath = NULL;
-
- transpGroupStack = NULL;
-+
-+ nestCount = 0;
- }
-
- void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) {
-@@ -723,15 +726,18 @@
- bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
- }
- splash = new Splash(bitmap, vectorAntialias, &screenParams);
-+ splash->setMinLineWidth(globalParams->getMinLineWidth());
- if (state) {
- ctm = state->getCTM();
- mat[0] = (SplashCoord)ctm[0];
-@@ -835,7 +841,10 @@
- }
-
- void SplashOutputDev::updateFlatness(GfxState *state) {
-+#if 0 // Acrobat ignores the flatness setting, and always renders curves
-+ // with a fairly small flatness value
- splash->setFlatness(state->getFlatness());
-+#endif
- }
-
- void SplashOutputDev::updateLineJoin(GfxState *state) {
-@@ -868,14 +877,24 @@
- GfxCMYK cmyk;
- #endif
-
-- state->getFillGray(&gray);
-- state->getFillRGB(&rgb);
-+ switch (colorMode) {
-+ case splashModeMono1:
-+ case splashModeMono8:
-+ state->getFillGray(&gray);
-+ splash->setFillPattern(getColor(gray));
-+ break;
-+ case splashModeRGB8:
-+ case splashModeBGR8:
-+ state->getFillRGB(&rgb);
-+ splash->setFillPattern(getColor(&rgb));
-+ break;
- #if SPLASH_CMYK
-- state->getFillCMYK(&cmyk);
-- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
--#else
-- splash->setFillPattern(getColor(gray, &rgb));
-+ case splashModeCMYK8:
-+ state->getFillCMYK(&cmyk);
-+ splash->setFillPattern(getColor(&cmyk));
-+ break;
- #endif
-+ }
- }
-
- void SplashOutputDev::updateStrokeColor(GfxState *state) {
-@@ -885,28 +904,41 @@
- GfxCMYK cmyk;
- #endif
-
-- state->getStrokeGray(&gray);
-- state->getStrokeRGB(&rgb);
-+ switch (colorMode) {
-+ case splashModeMono1:
-+ case splashModeMono8:
-+ state->getStrokeGray(&gray);
-+ splash->setStrokePattern(getColor(gray));
-+ break;
-+ case splashModeRGB8:
-+ case splashModeBGR8:
-+ state->getStrokeRGB(&rgb);
-+ splash->setStrokePattern(getColor(&rgb));
-+ break;
- #if SPLASH_CMYK
-- state->getStrokeCMYK(&cmyk);
-- splash->setStrokePattern(getColor(gray, &rgb, &cmyk));
--#else
-- splash->setStrokePattern(getColor(gray, &rgb));
-+ case splashModeCMYK8:
-+ state->getStrokeCMYK(&cmyk);
-+ splash->setStrokePattern(getColor(&cmyk));
-+ break;
- #endif
-+ }
- }
-
--#if SPLASH_CMYK
--SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb,
-- GfxCMYK *cmyk) {
--#else
--SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
--#endif
-- SplashPattern *pattern;
-+SplashPattern *SplashOutputDev::getColor(GfxGray gray) {
- SplashColor color;
-- GfxColorComp r, g, b;
-
- if (reverseVideo) {
- gray = gfxColorComp1 - gray;
-+ }
-+ color[0] = colToByte(gray);
-+ return new SplashSolidColor(color);
-+}
-+
-+SplashPattern *SplashOutputDev::getColor(GfxRGB *rgb) {
-+ GfxColorComp r, g, b;
-+ SplashColor color;
-+
-+ if (reverseVideo) {
- r = gfxColorComp1 - rgb->r;
- g = gfxColorComp1 - rgb->g;
- b = gfxColorComp1 - rgb->b;
-@@ -915,33 +947,58 @@
- g = rgb->g;
- b = rgb->b;
- }
-+ color[0] = colToByte(r);
-+ color[1] = colToByte(g);
-+ color[2] = colToByte(b);
-+ return new SplashSolidColor(color);
-+}
-
-- pattern = NULL; // make gcc happy
-- switch (colorMode) {
-- case splashModeMono1:
-- case splashModeMono8:
-- color[0] = colToByte(gray);
-- pattern = new SplashSolidColor(color);
-- break;
-- case splashModeRGB8:
-- case splashModeBGR8:
-- color[0] = colToByte(r);
-- color[1] = colToByte(g);
-- color[2] = colToByte(b);
-- pattern = new SplashSolidColor(color);
-- break;
- #if SPLASH_CMYK
-- case splashModeCMYK8:
-- color[0] = colToByte(cmyk->c);
-- color[1] = colToByte(cmyk->m);
-- color[2] = colToByte(cmyk->y);
-- color[3] = colToByte(cmyk->k);
-- pattern = new SplashSolidColor(color);
-- break;
-+SplashPattern *SplashOutputDev::getColor(GfxCMYK *cmyk) {
-+ SplashColor color;
-+
-+ color[0] = colToByte(cmyk->c);
-+ color[1] = colToByte(cmyk->m);
-+ color[2] = colToByte(cmyk->y);
-+ color[3] = colToByte(cmyk->k);
-+ return new SplashSolidColor(color);
-+}
- #endif
-- }
-
-- return pattern;
- }
-
- void SplashOutputDev::updateBlendMode(GfxState *state) {
-@@ -956,35 +1013,82 @@
- splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity());
- }
-
- void SplashOutputDev::updateFont(GfxState *state) {
- needFontUpdate = gTrue;
- }
-
- void SplashOutputDev::doUpdateFont(GfxState *state) {
- GfxFont *gfxFont;
-+ GfxFontLoc *fontLoc;
- GfxFontType fontType;
- SplashOutFontFileID *id;
- SplashFontFile *fontFile;
-+ int fontNum;
- FoFiTrueType *ff;
- Ref embRef;
- Object refObj, strObj;
-- GString *tmpFileName, *fileName, *substName;
-+ GString *tmpFileName, *fileName;
- FILE *tmpFile;
- int *codeToGID;
-- DisplayFontParam *dfp;
- CharCodeToUnicode *ctu;
- double *textMat;
-- double m11, m12, m21, m22, w1, w2, fontSize;
-+ double m11, m12, m21, m22, fontSize;
-+ double w, fontScaleMin, fontScaleAvg, fontScale;
-+ Gushort ww;
- SplashCoord mat[4];
- char *name;
- Unicode uBuf[8];
-- int c, substIdx, n, code, cmap;
-+ int c, substIdx, n, code, cmap, i;
-
- needFontUpdate = gFalse;
- font = NULL;
- tmpFileName = NULL;
- substIdx = -1;
-- dfp = NULL;
-
- if (!(gfxFont = state->getFont())) {
- goto err1;
-@@ -994,6 +1098,13 @@
- goto err1;
- }
-
-+ // sanity-check the font size - skip anything larger than 10 inches
-+ // (this avoids problems allocating memory for the font cache)
-+ if (state->getTransformedFontSize()
-+ > 10 * (state->getHDPI() + state->getVDPI())) {
-+ goto err1;
-+ }
-+
- // check the font file cache
- id = new SplashOutFontFileID(gfxFont->getID());
- if ((fontFile = fontEngine->getFontFile(id))) {
-@@ -1001,19 +1112,32 @@
-
- } else {
-
-- // if there is an embedded font, write it to disk
-- if (gfxFont->getEmbeddedFontID(&embRef)) {
-+ fileName = NULL;
-+ fontNum = 0;
-+
-+ if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
-+ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
-+ gfxFont->getName() ? gfxFont->getName()->getCString()
-+ : "(unnamed)");
-+ goto err2;
-+ }
-+
-+ // embedded font
-+ if (fontLoc->locType == gfxFontLocEmbedded) {
-+ gfxFont->getEmbeddedFontID(&embRef);
- if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
-- error(-1, "Couldn't create temporary font file");
-+ error(errIO, -1, "Couldn't create temporary font file");
-+ delete fontLoc;
- goto err2;
- }
- refObj.initRef(embRef.num, embRef.gen);
- refObj.fetch(xref, &strObj);
- refObj.free();
- if (!strObj.isStream()) {
-- error(-1, "Embedded font object is wrong type");
-+ error(errSyntaxError, -1, "Embedded font object is wrong type");
- strObj.free();
- fclose(tmpFile);
-+ delete fontLoc;
- goto err2;
- }
- strObj.streamReset();
-@@ -1025,94 +1149,53 @@
- fclose(tmpFile);
- fileName = tmpFileName;
-
-- // if there is an external font file, use it
-- } else if (!(fileName = gfxFont->getExtFontFile())) {
--
-- // look for a display font mapping or a substitute font
-- if (gfxFont->isCIDFont()) {
-- if (((GfxCIDFont *)gfxFont)->getCollection()) {
-- dfp = globalParams->
-- getDisplayCIDFont(gfxFont->getName(),
-- ((GfxCIDFont *)gfxFont)->getCollection());
-- }
-- } else {
-- if (gfxFont->getName()) {
-- dfp = globalParams->getDisplayFont(gfxFont->getName());
-- }
-- if (!dfp) {
-- // 8-bit font substitution
-- if (gfxFont->isFixedWidth()) {
-- substIdx = 8;
-- } else if (gfxFont->isSerif()) {
-- substIdx = 4;
-- } else {
-- substIdx = 0;
-- }
-- if (gfxFont->isBold()) {
-- substIdx += 2;
-- }
-- if (gfxFont->isItalic()) {
-- substIdx += 1;
-- }
-- substName = new GString(splashOutSubstFonts[substIdx].name);
-- dfp = globalParams->getDisplayFont(substName);
-- delete substName;
-- id->setSubstIdx(substIdx);
-- }
-- }
-- if (!dfp) {
-- error(-1, "Couldn't find a font for '%s'",
-- gfxFont->getName() ? gfxFont->getName()->getCString()
-- : "(unnamed)");
-- goto err2;
-- }
-- switch (dfp->kind) {
-- case displayFontT1:
-- fileName = dfp->t1.fileName;
-- fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
-- break;
-- case displayFontTT:
-- fileName = dfp->tt.fileName;
-- fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
-- break;
-+ // external font
-+ } else { // gfxFontLocExternal
-+ fileName = fontLoc->path;
-+ fontNum = fontLoc->fontNum;
-+ if (fontLoc->substIdx >= 0) {
-+ id->setSubstIdx(fontLoc->substIdx);
- }
- }
-
- // load the font file
-- switch (fontType) {
-+ switch (fontLoc->fontType) {
- case fontType1:
- if (!(fontFile = fontEngine->loadType1Font(
-- id,
-- fileName->getCString(),
-- fileName == tmpFileName,
-- (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-- error(-1, "Couldn't create a font for '%s'",
-+ id,
-+ fileName->getCString(),
-+ fileName == tmpFileName,
-+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
- case fontType1C:
- if (!(fontFile = fontEngine->loadType1CFont(
-- id,
-- fileName->getCString(),
-- fileName == tmpFileName,
-- (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-- error(-1, "Couldn't create a font for '%s'",
-+ id,
-+ fileName->getCString(),
-+ fileName == tmpFileName,
-+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
- case fontType1COT:
- if (!(fontFile = fontEngine->loadOpenTypeT1CFont(
-- id,
-- fileName->getCString(),
-- fileName == tmpFileName,
-- (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-- error(-1, "Couldn't create a font for '%s'",
-+ id,
-+ fileName->getCString(),
-+ fileName == tmpFileName,
-+ (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
-+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
-@@ -1122,18 +1205,33 @@
- codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
- n = 256;
- delete ff;
-+ // if we're substituting for a non-TrueType font, we need to mark
-+ // all notdef codes as "do not draw" (rather than drawing TrueType
-+ // notdef glyphs)
-+ if (gfxFont->getType() != fontTrueType &&
-+ gfxFont->getType() != fontTrueTypeOT) {
-+ for (i = 0; i < 256; ++i) {
-+ if (codeToGID[i] == 0) {
-+ codeToGID[i] = -1;
-+ }
-+ }
-+ }
- } else {
- codeToGID = NULL;
- n = 0;
- }
- if (!(fontFile = fontEngine->loadTrueTypeFont(
- id,
-- fileName->getCString(),
-+ fileName->getCString(), fontNum,
- fileName == tmpFileName,
-- codeToGID, n))) {
-- error(-1, "Couldn't create a font for '%s'",
-+ codeToGID, n,
-+ gfxFont->getEmbeddedFontName()
-+ ? gfxFont->getEmbeddedFontName()->getCString()
-+ : (char *)NULL))) {
-+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
-@@ -1143,20 +1241,32 @@
- id,
- fileName->getCString(),
- fileName == tmpFileName))) {
-- error(-1, "Couldn't create a font for '%s'",
-+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
- case fontCIDType0COT:
- if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
- n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
- codeToGID = (int *)gmallocn(n, sizeof(int));
- memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
- n * sizeof(int));
- } else {
- codeToGID = NULL;
- n = 0;
- }
- if (!(fontFile = fontEngine->loadOpenTypeCFFFont(
- id,
- codeToGID, n))) {
- error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
-@@ -1164,9 +1274,17 @@
- case fontCIDType2OT:
- codeToGID = NULL;
- n = 0;
-- if (dfp) {
-+ if (fontLoc->locType == gfxFontLocEmbedded) {
-+ if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
-+ n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
-+ codeToGID = (int *)gmallocn(n, sizeof(int));
-+ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
-+ n * sizeof(int));
-+ }
-+ } else {
- // create a CID-to-GID mapping, via Unicode
- if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
-+ //~ this should use fontNum to load the correct font
- if ((ff = FoFiTrueType::load(fileName->getCString()))) {
- // look for a Unicode cmap
- for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
-@@ -1179,12 +1297,12 @@
- if (cmap < ff->getNumCmaps()) {
- // map CID -> Unicode -> GID
- n = ctu->getLength();
-- codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
-+ codeToGID = (int *)gmallocn(n, sizeof(int));
- for (code = 0; code < n; ++code) {
- if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
- codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]);
- } else {
-- codeToGID[code] = 0;
-+ codeToGID[code] = -1;
- }
- }
- }
-@@ -1192,26 +1310,24 @@
- }
- ctu->decRefCnt();
- } else {
-- error(-1, "Couldn't find a mapping to Unicode for font '%s'",
-+ error(errSyntaxError, -1,
-+ "Couldn't find a mapping to Unicode for font '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
- }
-- } else {
-- if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
-- n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
-- codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
-- memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
-- n * sizeof(Gushort));
-- }
- }
- if (!(fontFile = fontEngine->loadTrueTypeFont(
- id,
-- fileName->getCString(),
-+ fileName->getCString(), fontNum,
- fileName == tmpFileName,
-- codeToGID, n))) {
-- error(-1, "Couldn't create a font for '%s'",
-+ codeToGID, n,
-+ gfxFont->getEmbeddedFontName()
-+ ? gfxFont->getEmbeddedFontName()->getCString()
-+ : (char *)NULL))) {
-+ error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
- gfxFont->getName() ? gfxFont->getName()->getCString()
- : "(unnamed)");
-+ delete fontLoc;
- goto err2;
- }
- break;
-@@ -1219,6 +1335,8 @@
- // this shouldn't happen
- goto err2;
- }
-+
-+ delete fontLoc;
- }
-
- // get the font matrix
-@@ -1230,26 +1348,42 @@
- m22 = textMat[3] * fontSize;
-
- // for substituted fonts: adjust the font matrix -- compare the
-- // width of 'm' in the original font and the substituted font
-+ // widths of letters and digits (A-Z, a-z, 0-9) in the original font
-+ // and the substituted font
- substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx();
-- if (substIdx >= 0) {
-+ if (substIdx >= 0 && substIdx < 12) {
-+ fontScaleMin = 1;
-+ fontScaleAvg = 0;
-+ n = 0;
- for (code = 0; code < 256; ++code) {
- if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
-- name[0] == 'm' && name[1] == '\0') {
-- break;
-+ name[0] && !name[1] &&
-+ ((name[0] >= 'A' && name[0] <= 'Z') ||
-+ (name[0] >= 'a' && name[0] <= 'z') ||
-+ (name[0] >= '0' && name[0] <= '9'))) {
-+ w = ((Gfx8BitFont *)gfxFont)->getWidth(code);
-+ builtinFontSubst[substIdx]->widths->getWidth(name, &ww);
-+ if (w > 0.01 && ww > 10) {
-+ w /= ww * 0.001;
-+ if (w < fontScaleMin) {
-+ fontScaleMin = w;
-+ }
-+ fontScaleAvg += w;
-+ ++n;
-+ }
- }
- }
-- if (code < 256) {
-- w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
-- w2 = splashOutSubstFonts[substIdx].mWidth;
-- if (!gfxFont->isSymbolic()) {
-- // if real font is substantially narrower than substituted
-- // font, reduce the font size accordingly
-- if (w1 > 0.01 && w1 < 0.9 * w2) {
-- w1 /= w2;
-- m11 *= w1;
-- m21 *= w1;
-- }
-+ // if real font is narrower than substituted font, reduce the font
-+ // size accordingly -- this currently uses a scale factor halfway
-+ // between the minimum and average computed scale factors, which
-+ // is a bit of a kludge, but seems to produce mostly decent
-+ // results
-+ if (n) {
-+ fontScaleAvg /= n;
-+ if (fontScaleAvg < 1) {
-+ fontScale = 0.5 * (fontScaleMin + fontScaleAvg);
-+ m11 *= fontScale;
-+ m12 *= fontScale;
- }
- }
- }
-@@ -1375,6 +1655,18 @@
- Unicode *u, int uLen) {
- SplashPath *path;
- int render;
-+ GBool doFill, doStroke, doClip, strokeAdjust;
-+ double m[4];
-+ GBool horiz;
-+
-+ if (skipHorizText || skipRotatedText) {
-+ state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]);
-+ horiz = m[0] > 0 && fabs(m[1]) < 0.001 &&
-+ fabs(m[2]) < 0.001 && m[3] < 0;
-+ if ((skipHorizText && horiz) || (skipRotatedText && !horiz)) {
-+ return;
-+ }
-+ }
-
- // check for invisible text -- this is used by Acrobat Capture
- render = state->getRender();
-@@ -1392,36 +1684,76 @@
- x -= originX;
- y -= originY;
-
-- // fill
-- if (!(render & 1)) {
-- if (!state->getFillColorSpace()->isNonMarking()) {
-- splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font);
-+ doFill = !(render & 1) && !state->getFillColorSpace()->isNonMarking();
-+ doStroke = ((render & 3) == 1 || (render & 3) == 2) &&
-+ !state->getStrokeColorSpace()->isNonMarking();
-+ doClip = render & 4;
-+
-+ path = NULL;
-+ if (doStroke || doClip) {
-+ if ((path = font->getGlyphPath(code))) {
-+ path->offset((SplashCoord)x, (SplashCoord)y);
- }
- }
-
-+ // don't use stroke adjustment when stroking text -- the results
-+ // tend to be ugly (because characters with horizontal upper or
-+ // lower edges get misaligned relative to the other characters)
-+ strokeAdjust = gFalse; // make gcc happy
-+ if (doStroke) {
-+ strokeAdjust = splash->getStrokeAdjust();
-+ splash->setStrokeAdjust(gFalse);
-+ }
-+
-+ // fill and stroke
-+ if (doFill && doStroke) {
-+ if (path) {
-+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
-+ state->getOverprintMode(), state->getFillColor());
-+ splash->fill(path, gFalse);
-+ setOverprintMask(state->getStrokeColorSpace(),
-+ state->getStrokeOverprint(),
-+ state->getOverprintMode(),
-+ state->getStrokeColor());
-+ splash->stroke(path);
-+ }
-+
-+ // fill
-+ } else if (doFill) {
-+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
-+ state->getOverprintMode(), state->getFillColor());
-+ splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font);
-+
- // stroke
-- if ((render & 3) == 1 || (render & 3) == 2) {
-- if (!state->getStrokeColorSpace()->isNonMarking()) {
-- if ((path = font->getGlyphPath(code))) {
-- path->offset((SplashCoord)x, (SplashCoord)y);
-- splash->stroke(path);
-- delete path;
-- }
-+ } else if (doStroke) {
-+ if (path) {
-+ setOverprintMask(state->getStrokeColorSpace(),
-+ state->getStrokeOverprint(),
-+ state->getOverprintMode(),
-+ state->getStrokeColor());
-+ splash->stroke(path);
- }
- }
-
- // clip
-- if (render & 4) {
-- if ((path = font->getGlyphPath(code))) {
-- path->offset((SplashCoord)x, (SplashCoord)y);
-+ if (doClip) {
-+ if (path) {
- if (textClipPath) {
- textClipPath->append(path);
-- delete path;
- } else {
- textClipPath = path;
-+ path = NULL;
- }
- }
- }
-+
-+ if (doStroke) {
-+ splash->setStrokeAdjust(strokeAdjust);
-+ }
-+
-+ if (path) {
-+ delete path;
-+ }
- }
-
- GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
-@@ -1433,9 +1765,20 @@
- T3FontCache *t3Font;
- T3GlyphStack *t3gs;
- GBool validBBox;
-+ double m[4];
-+ GBool horiz;
- double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
- int i, j;
-
-+ if (skipHorizText || skipRotatedText) {
-+ state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]);
-+ horiz = m[0] > 0 && fabs(m[1]) < 0.001 &&
-+ fabs(m[2]) < 0.001 && m[3] < 0;
-+ if ((skipHorizText && horiz) || (skipRotatedText && !horiz)) {
-+ return gTrue;
-+ }
-+ }
-+
- if (!(gfxFont = state->getFont())) {
- return gFalse;
- }
-@@ -1517,10 +1860,10 @@
- validBBox = gTrue;
- }
- t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
-- (int)floor(xMin - xt),
-- (int)floor(yMin - yt),
-- (int)ceil(xMax) - (int)floor(xMin) + 3,
-- (int)ceil(yMax) - (int)floor(yMin) + 3,
-+ (int)floor(xMin - xt) - 2,
-+ (int)floor(yMin - yt) - 2,
-+ (int)ceil(xMax) - (int)floor(xMin) + 4,
-+ (int)ceil(yMax) - (int)floor(yMin) + 4,
- validBBox,
- colorMode != splashModeMono1);
- }
-@@ -1532,7 +1875,7 @@
- for (j = 0; j < t3Font->cacheAssoc; ++j) {
- if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
- t3Font->cacheTags[i+j].code == code) {
-- drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
-+ drawType3Glyph(state, t3Font, &t3Font->cacheTags[i+j],
- t3Font->cacheData + (i+j) * t3Font->glyphSize);
- return gTrue;
- }
-@@ -1547,6 +1890,8 @@
- t3GlyphStack->cacheTag = NULL;
- t3GlyphStack->cacheData = NULL;
-
-+ haveT3Dx = gFalse;
-+
- return gFalse;
- }
-
-@@ -1555,6 +1900,7 @@
- double *ctm;
-
- if (t3GlyphStack->cacheTag) {
-+ --nestCount;
- memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr(),
- t3GlyphStack->cache->glyphSize);
- delete bitmap;
-@@ -1565,7 +1911,7 @@
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-- drawType3Glyph(t3GlyphStack->cache,
-+ drawType3Glyph(state, t3GlyphStack->cache,
- t3GlyphStack->cacheTag, t3GlyphStack->cacheData);
- }
- t3gs = t3GlyphStack;
-@@ -1574,6 +1920,7 @@
- }
-
- void SplashOutputDev::type3D0(GfxState *state, double wx, double wy) {
-+ haveT3Dx = gTrue;
- }
-
- void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
-@@ -1584,6 +1931,12 @@
- double xt, yt, xMin, xMax, yMin, yMax, x1, y1;
- int i, j;
-
-+ // ignore multiple d0/d1 operators
-+ if (haveT3Dx) {
-+ return;
-+ }
-+ haveT3Dx = gTrue;
-+
- t3Font = t3GlyphStack->cache;
-
- // check for a valid bbox
-@@ -1662,7 +2015,7 @@
- t3GlyphStack->origSplash->getScreen());
- color[0] = 0;
- splash->clear(color);
-- color[0] = 1;
-+ color[0] = 0xff;
- } else {
- bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
- splashModeMono8, gFalse);
-@@ -1672,18 +2025,23 @@
- splash->clear(color);
- color[0] = 0xff;
- }
-+ splash->setMinLineWidth(globalParams->getMinLineWidth());
- splash->setFillPattern(new SplashSolidColor(color));
- splash->setStrokePattern(new SplashSolidColor(color));
- //~ this should copy other state from t3GlyphStack->origSplash?
-+ //~ [this is likely the same situation as in beginTransparencyGroup()]
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- -t3Font->glyphX, -t3Font->glyphY);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-+ ++nestCount;
- }
-
--void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
-+void SplashOutputDev::drawType3Glyph(GfxState *state, T3FontCache *t3Font,
- T3FontCacheTag *tag, Guchar *data) {
- SplashGlyphBitmap glyph;
-
-+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
-+ state->getOverprintMode(), state->getFillColor());
- glyph.x = -t3Font->glyphX;
- glyph.y = -t3Font->glyphY;
- glyph.w = t3Font->glyphW;
-@@ -1717,9 +2075,10 @@
- if (imgMaskData->y == imgMaskData->height) {
- return gFalse;
- }
-- for (x = 0, p = imgMaskData->imgStr->getLine(), q = line;
-- x < imgMaskData->width;
-- ++x) {
-+ if (!(p = imgMaskData->imgStr->getLine())) {
-+ return gFalse;
-+ }
-+ for (x = 0, q = line; x < imgMaskData->width; ++x) {
- *q++ = *p++ ^ imgMaskData->invert;
- }
- ++imgMaskData->y;
-@@ -1765,6 +2126,46 @@
- str->close();
- }
-
-+void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state,
-+ Object *ref, Stream *str,
-+ int width, int height,
-+ GBool invert,
-+ GBool inlineImg) {
-+ double *ctm;
-+ SplashCoord mat[6];
-+ SplashOutImageMaskData imgMaskData;
-+ SplashBitmap *maskBitmap;
-+ Splash *maskSplash;
-+ SplashColor maskColor;
-+
-+ ctm = state->getCTM();
-+ mat[0] = ctm[0];
-+ mat[1] = ctm[1];
-+ mat[2] = -ctm[2];
-+ mat[3] = -ctm[3];
-+ mat[4] = ctm[2] + ctm[4];
-+ mat[5] = ctm[3] + ctm[5];
-+ imgMaskData.imgStr = new ImageStream(str, width, 1, 1);
-+ imgMaskData.imgStr->reset();
-+ imgMaskData.invert = invert ? 0 : 1;
-+ imgMaskData.width = width;
-+ imgMaskData.height = height;
-+ imgMaskData.y = 0;
-+ maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
-+ 1, splashModeMono8, gFalse);
-+ maskSplash = new Splash(maskBitmap, gTrue);
-+ maskColor[0] = 0;
-+ maskSplash->clear(maskColor);
-+ maskColor[0] = 0xff;
-+ maskSplash->setFillPattern(new SplashSolidColor(maskColor));
-+ maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
-+ width, height, mat, gFalse);
-+ delete imgMaskData.imgStr;
-+ str->close();
-+ delete maskSplash;
-+ splash->setSoftMask(maskBitmap);
-+}
-+
- struct SplashOutImageData {
- ImageStream *imgStr;
- GfxImageColorMap *colorMap;
-@@ -1789,6 +2190,9 @@
- if (imgData->y == imgData->height) {
- return gFalse;
- }
-+ if (!(p = imgData->imgStr->getLine())) {
-+ return gFalse;
-+ }
-
- nComps = imgData->colorMap->getNumPixelComps();
-
-@@ -1796,17 +2200,13 @@
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
-- x < imgData->width;
-- ++x, ++p) {
-+ for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) {
- *q++ = imgData->lookup[*p];
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
-- x < imgData->width;
-- ++x, ++p) {
-+ for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) {
- col = &imgData->lookup[3 * *p];
- *q++ = col[0];
- *q++ = col[1];
-@@ -1815,9 +2215,7 @@
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
-- x < imgData->width;
-- ++x, ++p) {
-+ for (x = 0, q = colorLine; x < imgData->width; ++x, ++p) {
- col = &imgData->lookup[4 * *p];
- *q++ = col[0];
- *q++ = col[1];
-@@ -1831,18 +2229,14 @@
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
-- x < imgData->width;
-- ++x, p += nComps) {
-+ for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) {
- imgData->colorMap->getGray(p, &gray);
- *q++ = colToByte(gray);
- }
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
-- x < imgData->width;
-- ++x, p += nComps) {
-+ for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) {
- imgData->colorMap->getRGB(p, &rgb);
- *q++ = colToByte(rgb.r);
- *q++ = colToByte(rgb.g);
-@@ -1851,9 +2245,7 @@
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine;
-- x < imgData->width;
-- ++x, p += nComps) {
-+ for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) {
- imgData->colorMap->getCMYK(p, &cmyk);
- *q++ = colToByte(cmyk.c);
- *q++ = colToByte(cmyk.m);
-@@ -1885,10 +2277,13 @@
- if (imgData->y == imgData->height) {
- return gFalse;
- }
-+ if (!(p = imgData->imgStr->getLine())) {
-+ return gFalse;
-+ }
-
- nComps = imgData->colorMap->getNumPixelComps();
-
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
-+ for (x = 0, q = colorLine, aq = alphaLine;
- x < imgData->width;
- ++x, p += nComps) {
- alpha = 0;
-@@ -1904,7 +2299,6 @@
- case splashModeMono1:
- case splashModeMono8:
- *q++ = imgData->lookup[*p];
-- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-@@ -1912,7 +2306,6 @@
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
-- *aq++ = alpha;
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-@@ -1921,17 +2314,16 @@
- *q++ = col[1];
- *q++ = col[2];
- *q++ = col[3];
-- *aq++ = alpha;
- break;
- #endif
- }
-+ *aq++ = alpha;
- } else {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData->colorMap->getGray(p, &gray);
- *q++ = colToByte(gray);
-- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-@@ -1939,7 +2331,6 @@
- *q++ = colToByte(rgb.r);
- *q++ = colToByte(rgb.g);
- *q++ = colToByte(rgb.b);
-- *aq++ = alpha;
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-@@ -1948,10 +2339,10 @@
- *q++ = colToByte(cmyk.m);
- *q++ = colToByte(cmyk.y);
- *q++ = colToByte(cmyk.k);
-- *aq++ = alpha;
- break;
- #endif
- }
-+ *aq++ = alpha;
- }
- }
-
-@@ -2012,7 +2406,7 @@
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-- imgData.lookup = (SplashColorPtr)gmalloc(3 * n);
-+ imgData.lookup = (SplashColorPtr)gmallocn(n, 3);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getRGB(&pix, &rgb);
-@@ -2023,7 +2417,7 @@
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- imgData.lookup = (SplashColorPtr)gmalloc(4 * n);
-+ imgData.lookup = (SplashColorPtr)gmallocn(n, 4);
- for (i = 0; i < n; ++i) {
- pix = (Guchar)i;
- colorMap->getCMYK(&pix, &cmyk);
-@@ -2034,7 +2428,6 @@
- }
- break;
- #endif
-- break;
- }
- }
-
-@@ -2071,7 +2464,6 @@
- Guchar *alphaLine) {
- SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data;
- Guchar *p, *aq;
-- SplashColor maskColor;
- SplashColorPtr q, col;
- GfxRGB rgb;
- GfxGray gray;
-@@ -2079,25 +2471,35 @@
- GfxCMYK cmyk;
- #endif
- Guchar alpha;
-+ Guchar *maskPtr;
-+ int maskBit;
- int nComps, x;
-
- if (imgData->y == imgData->height) {
- return gFalse;
- }
-+ if (!(p = imgData->imgStr->getLine())) {
-+ return gFalse;
-+ }
-
- nComps = imgData->colorMap->getNumPixelComps();
-
-- for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine;
-+ maskPtr = imgData->mask->getDataPtr() +
-+ imgData->y * imgData->mask->getRowSize();
-+ maskBit = 0x80;
-+ for (x = 0, q = colorLine, aq = alphaLine;
- x < imgData->width;
- ++x, p += nComps) {
-- imgData->mask->getPixel(x, imgData->y, maskColor);
-- alpha = maskColor[0] ? 0xff : 0x00;
-+ alpha = (*maskPtr & maskBit) ? 0xff : 0x00;
-+ if (!(maskBit >>= 1)) {
-+ ++maskPtr;
-+ maskBit = 0x80;
-+ }
- if (imgData->lookup) {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- *q++ = imgData->lookup[*p];
-- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-@@ -2105,7 +2507,6 @@
- *q++ = col[0];
- *q++ = col[1];
- *q++ = col[2];
-- *aq++ = alpha;
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-@@ -2114,17 +2515,16 @@
- *q++ = col[1];
- *q++ = col[2];
- *q++ = col[3];
-- *aq++ = alpha;
- break;
- #endif
- }
-+ *aq++ = alpha;
- } else {
- switch (imgData->colorMode) {
- case splashModeMono1:
- case splashModeMono8:
- imgData->colorMap->getGray(p, &gray);
- *q++ = colToByte(gray);
-- *aq++ = alpha;
- break;
- case splashModeRGB8:
- case splashModeBGR8:
-@@ -2132,7 +2532,6 @@
- *q++ = colToByte(rgb.r);
- *q++ = colToByte(rgb.g);
- *q++ = colToByte(rgb.b);
-- *aq++ = alpha;
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-@@ -2141,10 +2540,10 @@
- *q++ = colToByte(cmyk.m);
- *q++ = colToByte(cmyk.y);
- *q++ = colToByte(cmyk.k);
-- *aq++ = alpha;
- break;
- #endif
- }
-+ *aq++ = alpha;
- }
- }
-
-@@ -2433,7 +2838,7 @@
- SplashTransparencyGroup *transpGroup;
- SplashColor color;
- double xMin, yMin, xMax, yMax, x, y;
-- int tx, ty, w, h;
-+ int tx, ty, w, h, i;
-
- // transform the bbox
- state->transform(bbox[0], bbox[1], &x, &y);
-@@ -2475,14 +2880,14 @@
- tx = (int)floor(xMin);
- if (tx < 0) {
- tx = 0;
-- } else if (tx > bitmap->getWidth()) {
-- tx = bitmap->getWidth();
-+ } else if (tx >= bitmap->getWidth()) {
-+ tx = bitmap->getWidth() - 1;
- }
- ty = (int)floor(yMin);
- if (ty < 0) {
- ty = 0;
-- } else if (ty > bitmap->getHeight()) {
-- ty = bitmap->getHeight();
-+ } else if (ty >= bitmap->getHeight()) {
-+ ty = bitmap->getHeight() - 1;
- }
- w = (int)ceil(xMax) - tx + 1;
- if (tx + w > bitmap->getWidth()) {
-@@ -2512,31 +2917,47 @@
- transpGroup->origBitmap = bitmap;
- transpGroup->origSplash = splash;
-
-- //~ this ignores the blendingColorSpace arg
-+ //~ this handles the blendingColorSpace arg for soft masks, but
-+ //~ not yet for transparency groups
-+
-+ // switch to the blending color space
-+ if (forSoftMask && isolated && blendingColorSpace) {
-+ if (blendingColorSpace->getMode() == csDeviceGray ||
-+ blendingColorSpace->getMode() == csCalGray ||
-+ (blendingColorSpace->getMode() == csICCBased &&
-+ blendingColorSpace->getNComps() == 1)) {
-+ colorMode = splashModeMono8;
-+ } else if (blendingColorSpace->getMode() == csDeviceRGB ||
-+ blendingColorSpace->getMode() == csCalRGB ||
-+ (blendingColorSpace->getMode() == csICCBased &&
-+ blendingColorSpace->getNComps() == 3)) {
-+ //~ does this need to use BGR8?
-+ colorMode = splashModeRGB8;
-+#if SPLASH_CMYK
-+ } else if (blendingColorSpace->getMode() == csDeviceCMYK ||
-+ (blendingColorSpace->getMode() == csICCBased &&
-+ blendingColorSpace->getNComps() == 4)) {
-+ colorMode = splashModeCMYK8;
-+#endif
-+ }
-+ }
-
- // create the temporary bitmap
- bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
- bitmapTopDown);
- splash = new Splash(bitmap, vectorAntialias,
- transpGroup->origSplash->getScreen());
-+ splash->setMinLineWidth(globalParams->getMinLineWidth());
-+ //~ Acrobat apparently copies at least the fill and stroke colors, and
-+ //~ maybe other state(?) -- but not the clipping path (and not sure
-+ //~ what else)
-+ //~ [this is likely the same situation as in type3D1()]
-+ splash->setFillPattern(transpGroup->origSplash->getFillPattern()->copy());
-+ splash->setStrokePattern(
-+ transpGroup->origSplash->getStrokePattern()->copy());
- if (isolated) {
-- switch (colorMode) {
-- case splashModeMono1:
-- case splashModeMono8:
-- color[0] = 0;
-- break;
-- case splashModeRGB8:
-- case splashModeBGR8:
-- color[0] = color[1] = color[2] = 0;
-- break;
--#if SPLASH_CMYK
-- case splashModeCMYK8:
-- color[0] = color[1] = color[2] = color[3] = 0;
-- break;
--#endif
-- default:
-- // make gcc happy
-- break;
-+ for (i = 0; i < splashMaxColorComps; ++i) {
-+ color[i] = 0;
- }
- splash->clear(color, 0);
- } else {
-@@ -2546,16 +2967,16 @@
- transpGroup->tBitmap = bitmap;
- state->shiftCTM(-tx, -ty);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-+ ++nestCount;
- }
-
- void SplashOutputDev::endTransparencyGroup(GfxState *state) {
-- double *ctm;
--
- // restore state
-+ --nestCount;
- delete splash;
- bitmap = transpGroupStack->origBitmap;
-+ colorMode = bitmap->getMode();
- splash = transpGroupStack->origSplash;
-- ctm = state->getCTM();
- state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
- }
-@@ -2573,9 +2994,12 @@
-
- // paint the transparency group onto the parent bitmap
- // - the clip path was set in the parent's state)
-- splash->composite(tBitmap, 0, 0, tx, ty,
-- tBitmap->getWidth(), tBitmap->getHeight(),
-- gFalse, !isolated);
-+ if (tx < bitmap->getWidth() && ty < bitmap->getHeight()) {
-+ splash->setOverprintMask(0xffffffff);
-+ splash->composite(tBitmap, 0, 0, tx, ty,
-+ tBitmap->getWidth(), tBitmap->getHeight(),
-+ gFalse, !isolated);
-+ }
-
- // pop the stack
- transpGroup = transpGroupStack;
-@@ -2606,13 +3030,13 @@
- tBitmap = transpGroupStack->tBitmap;
-
- // composite with backdrop color
-- if (!alpha && colorMode != splashModeMono1) {
-+ if (!alpha && tBitmap->getMode() != splashModeMono1) {
- //~ need to correctly handle the case where no blending color
- //~ space is given
- tSplash = new Splash(tBitmap, vectorAntialias,
- transpGroupStack->origSplash->getScreen());
- if (transpGroupStack->blendingColorSpace) {
-- switch (colorMode) {
-+ switch (tBitmap->getMode()) {
- case splashModeMono1:
- // transparency is not supported in mono1 mode
- break;
-@@ -2648,36 +3072,38 @@
- 1, splashModeMono8, gFalse);
- memset(softMask->getDataPtr(), 0,
- softMask->getRowSize() * softMask->getHeight());
-- p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
-- for (y = 0; y < tBitmap->getHeight(); ++y) {
-- for (x = 0; x < tBitmap->getWidth(); ++x) {
-- tBitmap->getPixel(x, y, color);
-- if (alpha) {
-- //~ unimplemented
-- } else {
-- // convert to luminosity
-- switch (colorMode) {
-- case splashModeMono1:
-- case splashModeMono8:
-- lum = color[0] / 255.0;
-- break;
-- case splashModeRGB8:
-- case splashModeBGR8:
-- lum = (0.3 / 255.0) * color[0] +
-- (0.59 / 255.0) * color[1] +
-- (0.11 / 255.0) * color[2];
-- break;
--#if SPLASH_CMYK
-- case splashModeCMYK8:
-- lum = (1 - color[4] / 255.0)
-- - (0.3 / 255.0) * color[0]
-- - (0.59 / 255.0) * color[1]
-- - (0.11 / 255.0) * color[2];
-- if (lum < 0) {
-- lum = 0;
-- }
-- break;
-+ if (tx < softMask->getWidth() && ty < softMask->getHeight()) {
-+ p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx;
-+ for (y = 0; y < tBitmap->getHeight(); ++y) {
-+ for (x = 0; x < tBitmap->getWidth(); ++x) {
-+ if (alpha) {
-+ lum = tBitmap->getAlpha(x, y) / 255.0;
-+ } else {
-+ tBitmap->getPixel(x, y, color);
-+ // convert to luminosity
-+ switch (tBitmap->getMode()) {
-+ case splashModeMono1:
-+ case splashModeMono8:
-+ lum = color[0] / 255.0;
-+ break;
-+ case splashModeRGB8:
-+ case splashModeBGR8:
-+ lum = (0.3 / 255.0) * color[0] +
-+ (0.59 / 255.0) * color[1] +
-+ (0.11 / 255.0) * color[2];
-+ break;
-+#if SPLASH_CMYK
-+ case splashModeCMYK8:
-+ lum = (1 - color[3] / 255.0)
-+ - (0.3 / 255.0) * color[0]
-+ - (0.59 / 255.0) * color[1]
-+ - (0.11 / 255.0) * color[2];
-+ if (lum < 0) {
-+ lum = 0;
-+ }
-+ break;
- #endif
-+ }
- }
- if (transferFunc) {
- transferFunc->transform(&lum, &lum2);
-@@ -2686,8 +3112,8 @@
- }
- p[x] = (int)(lum2 * 255.0 + 0.5);
- }
-+ p += softMask->getRowSize();
- }
-- p += softMask->getRowSize();
- }
- splash->setSoftMask(softMask);
-
-@@ -2743,39 +3169,49 @@
- rgb.r = byteToCol(r);
- rgb.g = byteToCol(g);
- rgb.b = byteToCol(b);
-- gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5);
-- if (gray > gfxColorComp1) {
-- gray = gfxColorComp1;
-- }
-+ switch (colorMode) {
-+ case splashModeMono1:
-+ case splashModeMono8:
-+ gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5);
-+ if (gray > gfxColorComp1) {
-+ gray = gfxColorComp1;
-+ }
-+ splash->setFillPattern(getColor(gray));
-+ break;
-+ case splashModeRGB8:
-+ case splashModeBGR8:
-+ splash->setFillPattern(getColor(&rgb));
-+ break;
- #if SPLASH_CMYK
-- cmyk.c = gfxColorComp1 - rgb.r;
-- cmyk.m = gfxColorComp1 - rgb.g;
-- cmyk.y = gfxColorComp1 - rgb.b;
-- cmyk.k = 0;
-- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
--#else
-- splash->setFillPattern(getColor(gray, &rgb));
-+ case splashModeCMYK8:
-+ cmyk.c = gfxColorComp1 - rgb.r;
-+ cmyk.m = gfxColorComp1 - rgb.g;
-+ cmyk.y = gfxColorComp1 - rgb.b;
-+ cmyk.k = 0;
-+ splash->setFillPattern(getColor(&cmyk));
-+ break;
- #endif
-+ }
- }
-
--SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) {
-- DisplayFontParam *dfp;
-+SplashFont *SplashOutputDev::getFont(GString *name, SplashCoord *textMatA) {
- Ref ref;
- SplashOutFontFileID *id;
-+ GfxFontLoc *fontLoc;
- SplashFontFile *fontFile;
- SplashFont *fontObj;
- FoFiTrueType *ff;
-- Gushort *codeToGID;
-+ int *codeToGID;
- Unicode u;
- SplashCoord textMat[4];
- int cmap, i;
-
-- for (i = 0; i < 16; ++i) {
-- if (!name->cmp(splashOutSubstFonts[i].name)) {
-+ for (i = 0; i < nBuiltinFonts; ++i) {
-+ if (!name->cmp(builtinFonts[i].name)) {
- break;
- }
- }
-- if (i == 16) {
-+ if (i == nBuiltinFonts) {
- return NULL;
- }
- ref.num = i;
-@@ -2788,12 +3224,16 @@
-
- // load the font file
- } else {
-- dfp = globalParams->getDisplayFont(name);
-- if (dfp && dfp->kind == displayFontT1) {
-- fontFile = fontEngine->loadType1Font(id, dfp->t1.fileName->getCString(),
-+ if (!(fontLoc = GfxFont::locateBase14Font(name))) {
-+ return NULL;
-+ }
-+ if (fontLoc->fontType == fontType1) {
-+ fontFile = fontEngine->loadType1Font(id, fontLoc->path->getCString(),
- gFalse, winAnsiEncoding);
-- } else if (dfp && dfp->kind == displayFontTT) {
-- if (!(ff = FoFiTrueType::load(dfp->tt.fileName->getCString()))) {
-+ } else if (fontLoc->fontType == fontTrueType) {
-+ if (!(ff = FoFiTrueType::load(fontLoc->path->getCString()))) {
-+ delete fontLoc;
-+ delete id;
- return NULL;
- }
- for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
-@@ -2805,9 +3245,11 @@
- }
- if (cmap == ff->getNumCmaps()) {
- delete ff;
-+ delete fontLoc;
-+ delete id;
- return NULL;
- }
-- codeToGID = (Gushort *)gmallocn(256, sizeof(Gushort));
-+ codeToGID = (int *)gmallocn(256, sizeof(int));
- for (i = 0; i < 256; ++i) {
- codeToGID[i] = 0;
- if (winAnsiEncoding[i] &&
-@@ -2817,11 +3259,18 @@
- }
- delete ff;
- fontFile = fontEngine->loadTrueTypeFont(id,
-- dfp->tt.fileName->getCString(),
-- gFalse, codeToGID, 256);
-+ fontLoc->path->getCString(),
-+ fontLoc->fontNum,
-+ gFalse, codeToGID, 256, NULL);
- } else {
-+ delete fontLoc;
-+ delete id;
- return NULL;
- }
-+ delete fontLoc;
-+ }
-+ if (!fontFile) {
-+ return NULL;
- }
-
- // create the scaled font
-@@ -2835,11 +3284,7 @@
- }
-
- #if 1 //~tmp: turn off anti-aliasing temporarily
--GBool SplashOutputDev::getVectorAntialias() {
-- return splash->getVectorAntialias();
--}
--
--void SplashOutputDev::setVectorAntialias(GBool vaa) {
-- splash->setVectorAntialias(vaa);
-+void SplashOutputDev::setInShading(GBool sh) {
-+ splash->setInShading(sh);
- }
- #endif
-diff -ru xpdf-3.02/xpdf/SplashOutputDev.h xpdf-3.03/xpdf/SplashOutputDev.h
---- xpdf-3.02/xpdf/SplashOutputDev.h 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/xpdf/SplashOutputDev.h 2011-08-15 23:08:53.000000000 +0200
-@@ -58,15 +58,21 @@
-
- // Does this device use upside-down coordinates?
- // (Upside-down means (0,0) is the top left corner of the page.)
-- virtual GBool upsideDown() { return gTrue; }
-+ virtual GBool upsideDown() { return bitmapTopDown ^ bitmapUpsideDown; }
-
- // Does this device use drawChar() or drawString()?
- virtual GBool useDrawChar() { return gTrue; }
-
-@@ -124,6 +136,10 @@
- virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg);
-+ virtual void setSoftMaskFromImageMask(GfxState *state,
-+ Object *ref, Stream *str,
-+ int width, int height, GBool invert,
-+ GBool inlineImg);
- virtual void drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg);
-@@ -174,6 +190,10 @@
- // caller.
- SplashBitmap *takeBitmap();
-
-+ // Set this flag to true to generate an upside-down bitmap (useful
-+ // for Windows BMP files).
-+ void setBitmapUpsideDown(GBool f) { bitmapUpsideDown = f; }
-+
- // Get the Splash object.
- Splash *getSplash() { return splash; }
-
-@@ -187,26 +207,36 @@
- void setFillColor(int r, int g, int b);
-
- // Get a font object for a Base-14 font, using the Latin-1 encoding.
-- SplashFont *getFont(GString *name, double *textMatA);
-+ SplashFont *getFont(GString *name, SplashCoord *textMatA);
-
- SplashFont *getCurrentFont() { return font; }
-
-+ // If <skipTextA> is true, don't draw horizontal text.
-+ // If <skipRotatedTextA> is true, don't draw rotated (non-horizontal) text.
-+ void setSkipText(GBool skipHorizTextA, GBool skipRotatedTextA)
-+ { skipHorizText = skipHorizTextA; skipRotatedText = skipRotatedTextA; }
-+
-+ int getNestCount() { return nestCount; }
-+
-+
- #if 1 //~tmp: turn off anti-aliasing temporarily
-- virtual GBool getVectorAntialias();
-- virtual void setVectorAntialias(GBool vaa);
-+ virtual void setInShading(GBool sh);
- #endif
-
- private:
-
- void setupScreenParams(double hDPI, double vDPI);
-+ SplashPattern *getColor(GfxGray gray);
-+ SplashPattern *getColor(GfxRGB *rgb);
- #if SPLASH_CMYK
-- SplashPattern *getColor(GfxGray gray, GfxRGB *rgb, GfxCMYK *cmyk);
--#else
-- SplashPattern *getColor(GfxGray gray, GfxRGB *rgb);
-+ SplashPattern *getColor(GfxCMYK *cmyk);
- #endif
-@@ -219,11 +249,14 @@
- SplashColorMode colorMode;
- int bitmapRowPad;
- GBool bitmapTopDown;
-+ GBool bitmapUpsideDown;
- GBool allowAntialias;
- GBool vectorAntialias;
- GBool reverseVideo; // reverse video mode
- SplashColor paperColor; // paper color
- SplashScreenParams screenParams;
-+ GBool skipHorizText;
-+ GBool skipRotatedText;
-
- XRef *xref; // xref table for current document
-
-@@ -235,6 +268,7 @@
- t3FontCache[splashOutT3FontCacheSize];
- int nT3Fonts; // number of valid entries in t3FontCache
- T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack
-+ GBool haveT3Dx; // set after seeing a d0/d1 operator
-
- SplashFont *font; // current font
- GBool needFontUpdate; // set when the font needs to be updated
-@@ -242,6 +276,8 @@
-
- SplashTransparencyGroup * // transparency group stack
- transpGroupStack;
-+
-+ int nestCount;
- };
-
- #endif
diff -ru xpdf-3.02/xpdf/TextOutputDev.cc xpdf-3.03/xpdf/TextOutputDev.cc
--- xpdf-3.02/xpdf/TextOutputDev.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/TextOutputDev.cc 2011-08-15 23:08:53.000000000 +0200
@@ -11108,16 +7534,6 @@ diff -ru xpdf-3.02/xpdf/TextOutputDev.cc xpdf-3.03/xpdf/TextOutputDev.cc
curFontSize != curWord->fontSize) {
endWord();
}
-@@ -2057,15 +2189,46 @@
- }
- }
- charPos += nBytes;
- }
-
-+void TextPage::incCharCount(int nChars) {
-+ charPos += nChars;
-+}
-+
@@ -2109,7 +2272,7 @@
links->append(new TextLink(xMin, yMin, xMax, yMax, link));
}
@@ -11569,10 +7985,6 @@ diff -ru xpdf-3.02/xpdf/TextOutputDev.cc xpdf-3.03/xpdf/TextOutputDev.cc
+ text->addChar(state, x - originX, y - originY, dx, dy, c, nBytes, u, uLen);
+}
+
-+void TextOutputDev::incCharCount(int nChars) {
-+ text->incCharCount(nChars);
-+}
-+
@@ -4057,10 +4295,12 @@
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,
@@ -11599,13 +8011,6 @@ diff -ru xpdf-3.02/xpdf/TextOutputDev.h xpdf-3.03/xpdf/TextOutputDev.h
// Update this block's priMin and priMax values, looking at <blk>.
void updatePriMinMax(TextBlock *blk);
-@@ -429,6 +430,15 @@
- double dx, double dy,
- CharCode c, int nBytes, Unicode *u, int uLen);
-
-+ // Add <nChars> invisible characters.
-+ void incCharCount(int nChars);
-+
@@ -442,7 +452,7 @@
void addLink(int xMin, int yMin, int xMax, int yMax, Link *link);
@@ -11646,17 +8051,6 @@ diff -ru xpdf-3.02/xpdf/TextOutputDev.h xpdf-3.03/xpdf/TextOutputDev.h
// Destructor.
virtual ~TextOutputDev();
-@@ -575,6 +595,10 @@
- // Does this device need non-text content?
- virtual GBool needNonText() { return gFalse; }
-
-+ // Does this device require incCharCount to be called for text on
-+ // non-shown layers?
-+ virtual GBool needCharCount() { return gTrue; }
-+
- //----- initialization and control
-
- // Start a page.
@@ -583,6 +607,9 @@
// End a page.
virtual void endPage();
@@ -11667,11 +8061,6 @@ diff -ru xpdf-3.02/xpdf/TextOutputDev.h xpdf-3.03/xpdf/TextOutputDev.h
//----- update text state
virtual void updateFont(GfxState *state);
-@@ -593,6 +620,9 @@
- double dx, double dy,
- double originX, double originY,
- CharCode c, int nBytes, Unicode *u, int uLen);
-+ virtual void incCharCount(int nChars);
@@ -615,6 +645,7 @@
GBool startAtTop, GBool stopAtBottom,
GBool startAtLast, GBool stopAtLast,