diff options
author | Albert Astals Cid <aacid@kde.org> | 2012-02-01 22:56:55 +0100 |
---|---|---|
committer | Albert Astals Cid <aacid@kde.org> | 2012-02-01 22:56:55 +0100 |
commit | dc2471835c32e07f26014f273910156cb1d3ce62 (patch) | |
tree | daeb0e82d4a63b864e32cb94cde2d0a97e7b169d | |
parent | c885d0cb1e470ae19642f9c03b1c668bbeda1ae9 (diff) |
Update after last merge from Thomas
-rw-r--r-- | ALL_DIFF | 3869 |
1 files changed, 0 insertions, 3869 deletions
@@ -12,3260 +12,9 @@ diff -ru xpdf-3.02/doc/pdftotext.1 xpdf-3.03/doc/pdftotext.1 .B \-raw Keep the text in content stream order. This is a hack which often "undoes" column formatting, etc. Use of raw mode is no longer -diff -ru xpdf-3.02/xpdf/Gfx.cc xpdf-3.03/xpdf/Gfx.cc ---- xpdf-3.02/xpdf/Gfx.cc 2007-02-27 23:05:52.000000000 +0100 -+++ xpdf-3.03/xpdf/Gfx.cc 2011-08-15 23:08:53.000000000 +0200 -@@ -18,9 +18,12 @@ - #include <string.h> - #include <math.h> - #include "gmem.h" -+#include "GString.h" -+#include "GList.h" - #include "GlobalParams.h" - #include "CharTypes.h" - #include "Object.h" - #include "PDFDoc.h" - #include "Array.h" - #include "Dict.h" - #include "Stream.h" -@@ -31,7 +34,9 @@ - #include "OutputDev.h" - #include "Page.h" - #include "Annot.h" -+#include "OptionalContent.h" - #include "Error.h" -+#include "PDFDocEncoding.h" - #include "Gfx.h" - - // the MSVC math.h doesn't define this -@@ -562,7 +596,8 @@ - int lastAbortCheck; - - // scan a sequence of objects -- updateLevel = lastAbortCheck = 0; -+ updateLevel = 1; // make sure even empty pages trigger a call to dump() -+ lastAbortCheck = 0; - numArgs = 0; - parser->getObj(&obj); - while (!obj.isEOF()) { -@@ -695,6 +734,7 @@ - - a = -1; - b = numOps; -+ cmp = 0; // make gcc happy - // invariant: opTab[a] < name < opTab[b] - while (b - a > 1) { - m = (a + b) / 2; -@@ -801,6 +841,7 @@ - - void Gfx::opSetExtGState(Object args[], int numArgs) { - Object obj1, obj2, obj3, obj4, obj5; -+ Object args2[2]; - GfxBlendMode mode; - GBool haveFillOP; - Function *funcs[4]; -@@ -808,9 +849,10 @@ - GBool haveBackdropColor; - GfxColorSpace *blendingColorSpace; - GBool alpha, isolated, knockout; -+ double opac; - int i; - - if (!res->lookupGState(args[0].getName(), &obj1)) { - return; - } - if (!obj1.isDict()) { -@@ -824,28 +867,77 @@ - printf("\n"); - } - -+ // parameters that are also set by individual PDF operators -+ if (obj1.dictLookup("LW", &obj2)->isNum()) { -+ opSetLineWidth(&obj2, 1); -+ } -+ obj2.free(); -+ if (obj1.dictLookup("LC", &obj2)->isInt()) { -+ opSetLineCap(&obj2, 1); -+ } -+ obj2.free(); -+ if (obj1.dictLookup("LJ", &obj2)->isInt()) { -+ opSetLineJoin(&obj2, 1); -+ } -+ obj2.free(); -+ if (obj1.dictLookup("ML", &obj2)->isNum()) { -+ opSetMiterLimit(&obj2, 1); -+ } -+ obj2.free(); -+ if (obj1.dictLookup("D", &obj2)->isArray() && -+ obj2.arrayGetLength() == 2) { -+ obj2.arrayGet(0, &args2[0]); -+ obj2.arrayGet(1, &args2[1]); -+ if (args2[0].isArray() && args2[1].isNum()) { -+ opSetDash(args2, 2); -+ } -+ args2[0].free(); -+ args2[1].free(); -+ } -+ obj2.free(); -+#if 0 //~ need to add a new version of GfxResources::lookupFont() that -+ //~ takes an indirect ref instead of a name -+ if (obj1.dictLookup("Font", &obj2)->isArray() && -+ obj2.arrayGetLength() == 2) { -+ obj2.arrayGet(0, &args2[0]); -+ obj2.arrayGet(1, &args2[1]); -+ if (args2[0].isDict() && args2[1].isNum()) { -+ opSetFont(args2, 2); -+ } -+ args2[0].free(); -+ args2[1].free(); -+ } -+ obj2.free(); -+#endif -+ if (obj1.dictLookup("FL", &obj2)->isNum()) { -+ opSetFlat(&obj2, 1); -+ } -+ obj2.free(); -+ - // transparency support: blend mode, fill/stroke opacity - if (!obj1.dictLookup("BM", &obj2)->isNull()) { - if (state->parseBlendMode(&obj2, &mode)) { - state->setBlendMode(mode); - out->updateBlendMode(state); - } else { - error(errSyntaxError, getPos(), "Invalid blend mode in ExtGState"); - } - } - obj2.free(); - if (obj1.dictLookup("ca", &obj2)->isNum()) { -- state->setFillOpacity(obj2.getNum()); -+ opac = obj2.getNum(); -+ state->setFillOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac); - out->updateFillOpacity(state); - } - obj2.free(); - if (obj1.dictLookup("CA", &obj2)->isNum()) { -- state->setStrokeOpacity(obj2.getNum()); -+ opac = obj2.getNum(); -+ state->setStrokeOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac); - out->updateStrokeOpacity(state); - } - obj2.free(); - -- // fill/stroke overprint -+ // fill/stroke overprint, overprint mode - if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { - state->setFillOverprint(obj2.getBool()); - out->updateFillOverprint(state); -@@ -860,6 +952,11 @@ - } - } - obj2.free(); -+ if (obj1.dictLookup("OPM", &obj2)->isInt()) { -+ state->setOverprintMode(obj2.getInt()); -+ out->updateOverprintMode(state); -+ } -+ obj2.free(); - - // stroke adjust - if (obj1.dictLookup("SA", &obj2)->isBool()) { -@@ -915,13 +1012,18 @@ - obj3.free(); - funcs[0] = NULL; - if (!obj2.dictLookup("TR", &obj3)->isNull()) { -- funcs[0] = Function::parse(&obj3); -- if (funcs[0]->getInputSize() != 1 || -- funcs[0]->getOutputSize() != 1) { -- error(getPos(), -- "Invalid transfer function in soft mask in ExtGState"); -- delete funcs[0]; -+ if (obj3.isName("Default") || -+ obj3.isName("Identity")) { - funcs[0] = NULL; -+ } else { -+ funcs[0] = Function::parse(&obj3); -+ if (funcs[0]->getInputSize() != 1 || -+ funcs[0]->getOutputSize() != 1) { -+ error(errSyntaxError, getPos(), -+ "Invalid transfer function in soft mask in ExtGState"); -+ delete funcs[0]; -+ funcs[0] = NULL; -+ } - } - } - obj3.free(); -@@ -1402,14 +1512,16 @@ - - void Gfx::opStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in stroke"); -+ //error(errSyntaxError, getPos(), "No path in stroke"); - return; - } - if (state->isPath()) { -- if (state->getStrokeColorSpace()->getMode() == csPattern) { -- doPatternStroke(); -- } else { -- out->stroke(state); -+ if (ocState) { -+ if (state->getStrokeColorSpace()->getMode() == csPattern) { -+ doPatternStroke(); -+ } else { -+ out->stroke(state); -+ } - } - } - doEndPath(); -@@ -1417,15 +1529,17 @@ - - void Gfx::opCloseStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in closepath/stroke"); -+ //error(errSyntaxError, getPos(), "No path in closepath/stroke"); - return; - } - if (state->isPath()) { - state->closePath(); -- if (state->getStrokeColorSpace()->getMode() == csPattern) { -- doPatternStroke(); -- } else { -- out->stroke(state); -+ if (ocState) { -+ if (state->getStrokeColorSpace()->getMode() == csPattern) { -+ doPatternStroke(); -+ } else { -+ out->stroke(state); -+ } - } - } - doEndPath(); -@@ -1433,14 +1547,16 @@ - - void Gfx::opFill(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in fill"); -+ //error(errSyntaxError, getPos(), "No path in fill"); - return; - } - if (state->isPath()) { -- if (state->getFillColorSpace()->getMode() == csPattern) { -- doPatternFill(gFalse); -- } else { -- out->fill(state); -+ if (ocState) { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternFill(gFalse); -+ } else { -+ out->fill(state); -+ } - } - } - doEndPath(); -@@ -1448,14 +1564,16 @@ - - void Gfx::opEOFill(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in eofill"); -+ //error(errSyntaxError, getPos(), "No path in eofill"); - return; - } - if (state->isPath()) { -- if (state->getFillColorSpace()->getMode() == csPattern) { -- doPatternFill(gTrue); -- } else { -- out->eoFill(state); -+ if (ocState) { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternFill(gTrue); -+ } else { -+ out->eoFill(state); -+ } - } - } - doEndPath(); -@@ -1463,19 +1581,21 @@ - - void Gfx::opFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in fill/stroke"); -+ //error(errSyntaxError, getPos(), "No path in fill/stroke"); - return; - } - if (state->isPath()) { -- if (state->getFillColorSpace()->getMode() == csPattern) { -- doPatternFill(gFalse); -- } else { -- out->fill(state); -- } -- if (state->getStrokeColorSpace()->getMode() == csPattern) { -- doPatternStroke(); -- } else { -- out->stroke(state); -+ if (ocState) { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternFill(gFalse); -+ } else { -+ out->fill(state); -+ } -+ if (state->getStrokeColorSpace()->getMode() == csPattern) { -+ doPatternStroke(); -+ } else { -+ out->stroke(state); -+ } - } - } - doEndPath(); -@@ -1483,20 +1603,22 @@ - - void Gfx::opCloseFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in closepath/fill/stroke"); -+ //error(errSyntaxError, getPos(), "No path in closepath/fill/stroke"); - return; - } - if (state->isPath()) { - state->closePath(); -- if (state->getFillColorSpace()->getMode() == csPattern) { -- doPatternFill(gFalse); -- } else { -- out->fill(state); -- } -- if (state->getStrokeColorSpace()->getMode() == csPattern) { -- doPatternStroke(); -- } else { -- out->stroke(state); -+ if (ocState) { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternFill(gFalse); -+ } else { -+ out->fill(state); -+ } -+ if (state->getStrokeColorSpace()->getMode() == csPattern) { -+ doPatternStroke(); -+ } else { -+ out->stroke(state); -+ } - } - } - doEndPath(); -@@ -1504,19 +1626,21 @@ - - void Gfx::opEOFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in eofill/stroke"); -+ //error(errSyntaxError, getPos(), "No path in eofill/stroke"); - return; - } - if (state->isPath()) { -- if (state->getFillColorSpace()->getMode() == csPattern) { -- doPatternFill(gTrue); -- } else { -- out->eoFill(state); -- } -- if (state->getStrokeColorSpace()->getMode() == csPattern) { -- doPatternStroke(); -- } else { -- out->stroke(state); -+ if (ocState) { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternFill(gTrue); -+ } else { -+ out->eoFill(state); -+ } -+ if (state->getStrokeColorSpace()->getMode() == csPattern) { -+ doPatternStroke(); -+ } else { -+ out->stroke(state); -+ } - } - } - doEndPath(); -@@ -1524,20 +1648,22 @@ - - void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { -- //error(getPos(), "No path in closepath/eofill/stroke"); -+ //error(errSyntaxError, getPos(), "No path in closepath/eofill/stroke"); - return; - } - if (state->isPath()) { - state->closePath(); -- if (state->getFillColorSpace()->getMode() == csPattern) { -- doPatternFill(gTrue); -- } else { -- out->eoFill(state); -- } -- if (state->getStrokeColorSpace()->getMode() == csPattern) { -- doPatternStroke(); -- } else { -- out->stroke(state); -+ if (ocState) { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternFill(gTrue); -+ } else { -+ out->eoFill(state); -+ } -+ if (state->getStrokeColorSpace()->getMode() == csPattern) { -+ doPatternStroke(); -+ } else { -+ out->stroke(state); -+ } - } - } - doEndPath(); - -@@ -3373,7 +3650,7 @@ - GBool maskInvert; - Stream *maskStr; - Object obj1, obj2; -- int i; -+ int i, n; - - // get info from the stream - bits = 0; -@@ -3389,19 +3666,27 @@ - obj1.free(); - dict->lookup("W", &obj1); - } -- if (!obj1.isInt()) -+ if (!obj1.isInt()) { - goto err2; -+ } - width = obj1.getInt(); - obj1.free(); -+ if (width <= 0) { -+ goto err1; -+ } - dict->lookup("Height", &obj1); - if (obj1.isNull()) { - obj1.free(); - dict->lookup("H", &obj1); - } -- if (!obj1.isInt()) -+ if (!obj1.isInt()) { - goto err2; -+ } - height = obj1.getInt(); - obj1.free(); -+ if (height <= 0) { -+ goto err1; -+ } - - // image or mask? - dict->lookup("ImageMask", &obj1); -@@ -3447,16 +3732,30 @@ - } - if (obj1.isArray()) { - obj1.arrayGet(0, &obj2); -- if (obj2.isInt() && obj2.getInt() == 1) -- invert = gTrue; -+ invert = obj2.isNum() && obj2.getNum() == 1; - obj2.free(); - } else if (!obj1.isNull()) { - goto err2; - } - obj1.free(); - -+ // if drawing is disabled, skip over inline image data -+ if (!ocState) { -+ str->reset(); -+ n = height * ((width + 7) / 8); -+ for (i = 0; i < n; ++i) { -+ str->getChar(); -+ } -+ str->close(); -+ - // draw it -- out->drawImageMask(state, ref, str, width, height, invert, inlineImg); -+ } else { -+ if (state->getFillColorSpace()->getMode() == csPattern) { -+ doPatternImageMask(ref, str, width, height, invert, inlineImg); -+ } else { -+ out->drawImageMask(state, ref, str, width, height, invert, inlineImg); -+ } -+ } - - } else { - -@@ -3581,14 +3880,36 @@ - haveSoftMask = gTrue; - } else if (maskObj.isArray()) { - // color key mask -+ haveColorKeyMask = gTrue; - for (i = 0; -- i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps; -- ++i) { -+ i+1 < maskObj.arrayGetLength() && i+1 < 2*gfxColorMaxComps; -+ i += 2) { - maskObj.arrayGet(i, &obj1); -+ if (!obj1.isInt()) { -+ obj1.free(); -+ haveColorKeyMask = gFalse; -+ break; -+ } - maskColors[i] = obj1.getInt(); - obj1.free(); -+ if (maskColors[i] < 0 || maskColors[i] >= (1 << bits)) { -+ haveColorKeyMask = gFalse; -+ break; -+ } -+ maskObj.arrayGet(i+1, &obj1); -+ if (!obj1.isInt()) { -+ obj1.free(); -+ haveColorKeyMask = gFalse; -+ break; -+ } -+ maskColors[i+1] = obj1.getInt(); -+ obj1.free(); -+ if (maskColors[i+1] < 0 || maskColors[i+1] >= (1 << bits) || -+ maskColors[i] > maskColors[i+1]) { -+ haveColorKeyMask = gFalse; -+ break; -+ } - } -- haveColorKeyMask = gTrue; - } else if (maskObj.isStream()) { - // explicit mask - if (inlineImg) { -@@ -3633,9 +3954,7 @@ - } - if (obj1.isArray()) { - obj1.arrayGet(0, &obj2); -- if (obj2.isInt() && obj2.getInt() == 1) { -- maskInvert = gTrue; -- } -+ maskInvert = obj2.isNum() && obj2.getNum() == 1; - obj2.free(); - } else if (!obj1.isNull()) { - goto err2; -@@ -3644,20 +3963,32 @@ - haveExplicitMask = gTrue; - } - -+ // if drawing is disabled, skip over inline image data -+ if (!ocState) { -+ str->reset(); -+ n = height * ((width * colorMap->getNumPixelComps() * -+ colorMap->getBits() + 7) / 8); -+ for (i = 0; i < n; ++i) { -+ str->getChar(); -+ } -+ str->close(); -+ - // draw it -- if (haveSoftMask) { -- out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, -- maskStr, maskWidth, maskHeight, maskColorMap); -- delete maskColorMap; -- } else if (haveExplicitMask) { -- out->drawMaskedImage(state, ref, str, width, height, colorMap, -- maskStr, maskWidth, maskHeight, maskInvert); - } else { -- out->drawImage(state, ref, str, width, height, colorMap, -- haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); -+ if (haveSoftMask) { -+ out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, -+ maskStr, maskWidth, maskHeight, maskColorMap); -+ delete maskColorMap; -+ } else if (haveExplicitMask) { -+ out->drawMaskedImage(state, ref, str, width, height, colorMap, -+ maskStr, maskWidth, maskHeight, maskInvert); -+ } else { -+ out->drawImage(state, ref, str, width, height, colorMap, -+ haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); -+ } - } -- delete colorMap; - -+ delete colorMap; - maskObj.free(); - smaskObj.free(); - } -@@ -3869,6 +4218,9 @@ - Stream *str; - int c1, c2; - -+ // NB: this function is run even if ocState is false -- doImage() is -+ // responsible for skipping over the inline image data -+ - // build dict/stream - str = buildImageStream(); - -@@ -3921,18 +4274,23 @@ - obj.free(); - - // make stream -- str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); -+ if (!(str = parser->getStream())) { -+ error(errSyntaxError, getPos(), "Invalid inline image data"); -+ dict.free(); -+ return NULL; -+ } -+ str = new EmbedStream(str, &dict, gFalse, 0); - str = str->addFilters(&dict); - - return str; - } - - void Gfx::opImageData(Object args[], int numArgs) { - error(errInternal, getPos(), "Got 'ID' operator"); - } - - void Gfx::opEndImage(Object args[], int numArgs) { - error(errInternal, getPos(), "Got 'EI' operator"); - } - - //------------------------------------------------------------------------ -@@ -3967,23 +4325,88 @@ - //------------------------------------------------------------------------ - - void Gfx::opBeginMarkedContent(Object args[], int numArgs) { -+ GfxMarkedContent *mc; -+ Object obj; -+ GBool ocStateNew; -+ GString *s; -+ Unicode *u; -+ int uLen, i; -+ GfxMarkedContentKind mcKind; -+ - if (printCommands) { - printf(" marked content: %s ", args[0].getName()); -- if (numArgs == 2) -- args[2].print(stdout); -+ if (numArgs == 2) { -+ args[1].print(stdout); -+ } - printf("\n"); - fflush(stdout); - } -+ mcKind = gfxMCOther; -+ if (args[0].isName("OC") && numArgs == 2 && args[1].isName() && -+ res->lookupPropertiesNF(args[1].getName(), &obj)) { -+ if (doc->getOptionalContent()->evalOCObject(&obj, &ocStateNew)) { -+ ocState = ocStateNew; -+ } -+ obj.free(); -+ mcKind = gfxMCOptionalContent; - } - - void Gfx::opEndMarkedContent(Object args[], int numArgs) { -+ GfxMarkedContent *mc; -+ GfxMarkedContentKind mcKind; -+ -+ if (markedContentStack->getLength() > 0) { -+ mc = (GfxMarkedContent *) -+ markedContentStack->del(markedContentStack->getLength() - 1); -+ mcKind = mc->kind; -+ delete mc; -+ if (mcKind == gfxMCOptionalContent) { -+ if (markedContentStack->getLength() > 0) { -+ mc = (GfxMarkedContent *) -+ markedContentStack->get(markedContentStack->getLength() - 1); -+ ocState = mc->ocState; -+ } else { -+ ocState = gTrue; -+ } - - - void Gfx::opMarkPoint(Object args[], int numArgs) { - if (printCommands) { - printf(" mark point: %s ", args[0].getName()); - if (numArgs == 2) -- args[2].print(stdout); -+ args[1].print(stdout); - printf("\n"); - fflush(stdout); - } -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 -@@ -16,6 +16,11 @@ - #include <stdlib.h> - #include <string.h> - #include <ctype.h> -+#include <math.h> -+#include <limits.h> -+#if HAVE_STD_SORT -+#include <algorithm> -+#endif - #include "gmem.h" - #include "Error.h" - #include "Object.h" -@@ -25,6 +30,7 @@ - #include "CharCodeToUnicode.h" - #include "FontEncodingTables.h" - #include "BuiltinFontTables.h" -+#include "FoFiIdentifier.h" - #include "FoFiType1.h" - #include "FoFiType1C.h" - #include "FoFiTrueType.h" -@@ -93,15 +107,66 @@ - GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) { - GString *nameA; -+ Ref embFontIDA; -+ GfxFontType typeA; - GfxFont *font; - Object obj1; - -@@ -113,53 +178,235 @@ - } - obj1.free(); - -- // get font type -+ // get embedded font ID and font type -+ typeA = getFontType(xref, fontDict, &embFontIDA); -+ -+ // create the font object - font = NULL; -- fontDict->lookup("Subtype", &obj1); -- if (obj1.isName("Type1") || obj1.isName("MMType1")) { -- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict); -- } else if (obj1.isName("Type1C")) { -- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict); -- } else if (obj1.isName("Type3")) { -- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict); -- } else if (obj1.isName("TrueType")) { -- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict); -- } else if (obj1.isName("Type0")) { -- font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict); -+ if (typeA < fontCIDType0) { -+ font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA, -+ fontDict); - } else { -- error(-1, "Unknown font type: '%s'", -- obj1.isName() ? obj1.getName() : "???"); -- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict); -+ font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA, -+ fontDict); - } -- obj1.free(); - - return font; - } - --GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) { -+GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA, -+ GfxFontType typeA, Ref embFontIDA) { - ok = gFalse; - tag = new GString(tagA); - id = idA; - name = nameA; -+ type = typeA; -+ embFontID = embFontIDA; - embFontName = NULL; -- extFontFile = NULL; - } - - GfxFont::~GfxFont() { - delete tag; - if (name) { - delete name; - } - if (embFontName) { - delete embFontName; - } -- if (extFontFile) { -- delete extFontFile; -+} -+ -+// This function extracts three pieces of information: -+// 1. the "expected" font type, i.e., the font type implied by -+// Font.Subtype, DescendantFont.Subtype, and -+// FontDescriptor.FontFile3.Subtype -+// 2. the embedded font object ID -+// 3. the actual font type - determined by examining the embedded font -+// if there is one, otherwise equal to the expected font type -+// If the expected and actual font types don't match, a warning -+// message is printed. The expected font type is not used for -+// anything else. -+GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { -+ GfxFontType t, expectedType; -+ FoFiIdentifierType fft; -+ Dict *fontDict2; -+ Object subtype, fontDesc, obj1, obj2, obj3, obj4; -+ GBool isType0, err; -+ -+ t = fontUnknownType; -+ embID->num = embID->gen = -1; -+ err = gFalse; -+ -+ fontDict->lookup("Subtype", &subtype); -+ expectedType = fontUnknownType; -+ isType0 = gFalse; -+ if (subtype.isName("Type1") || subtype.isName("MMType1")) { -+ expectedType = fontType1; -+ } else if (subtype.isName("Type1C")) { -+ expectedType = fontType1C; -+ } else if (subtype.isName("Type3")) { -+ expectedType = fontType3; -+ } else if (subtype.isName("TrueType")) { -+ expectedType = fontTrueType; -+ } else if (subtype.isName("Type0")) { -+ isType0 = gTrue; -+ } else { -+ error(errSyntaxWarning, -1, "Unknown font type: '{0:s}'", -+ subtype.isName() ? subtype.getName() : "???"); -+ } -+ subtype.free(); -+ -+ fontDict2 = fontDict; -+ if (fontDict->lookup("DescendantFonts", &obj1)->isArray()) { -+ if (obj1.arrayGetLength() == 0) { -+ error(errSyntaxWarning, -1, "Empty DescendantFonts array in font"); -+ obj2.initNull(); -+ } else if (obj1.arrayGet(0, &obj2)->isDict()) { -+ if (!isType0) { -+ error(errSyntaxWarning, -1, "Non-CID font with DescendantFonts array"); -+ } -+ fontDict2 = obj2.getDict(); -+ fontDict2->lookup("Subtype", &subtype); -+ if (subtype.isName("CIDFontType0")) { -+ if (isType0) { -+ expectedType = fontCIDType0; -+ } -+ } else if (subtype.isName("CIDFontType2")) { -+ if (isType0) { -+ expectedType = fontCIDType2; -+ } -+ } -+ subtype.free(); -+ } -+ } else { -+ obj2.initNull(); -+ } -+ -+ if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) { -+ if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { -+ *embID = obj3.getRef(); -+ if (expectedType != fontType1) { -+ err = gTrue; -+ } -+ } -+ obj3.free(); -+ if (embID->num == -1 && -+ fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { -+ *embID = obj3.getRef(); -+ if (isType0) { -+ expectedType = fontCIDType2; -+ } else if (expectedType != fontTrueType) { -+ err = gTrue; -+ } -+ } -+ obj3.free(); -+ if (embID->num == -1 && -+ fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { -+ *embID = obj3.getRef(); -+ if (obj3.fetch(xref, &obj4)->isStream()) { -+ obj4.streamGetDict()->lookup("Subtype", &subtype); -+ if (subtype.isName("Type1")) { -+ if (expectedType != fontType1) { -+ err = gTrue; -+ expectedType = isType0 ? fontCIDType0 : fontType1; -+ } -+ } else if (subtype.isName("Type1C")) { -+ if (expectedType == fontType1) { -+ expectedType = fontType1C; -+ } else if (expectedType != fontType1C) { -+ err = gTrue; -+ expectedType = isType0 ? fontCIDType0C : fontType1C; -+ } -+ } else if (subtype.isName("TrueType")) { -+ if (expectedType != fontTrueType) { -+ err = gTrue; -+ expectedType = isType0 ? fontCIDType2 : fontTrueType; -+ } -+ } else if (subtype.isName("CIDFontType0C")) { -+ if (expectedType == fontCIDType0) { -+ expectedType = fontCIDType0C; -+ } else { -+ err = gTrue; -+ expectedType = isType0 ? fontCIDType0C : fontType1C; -+ } -+ } else if (subtype.isName("OpenType")) { -+ if (expectedType == fontTrueType) { -+ expectedType = fontTrueTypeOT; -+ } else if (expectedType == fontType1) { -+ expectedType = fontType1COT; -+ } else if (expectedType == fontCIDType0) { -+ expectedType = fontCIDType0COT; -+ } else if (expectedType == fontCIDType2) { -+ expectedType = fontCIDType2OT; -+ } else { -+ err = gTrue; -+ } -+ } else { -+ error(errSyntaxError, -1, "Unknown font type '{0:s}'", -+ subtype.isName() ? subtype.getName() : "???"); -+ } -+ subtype.free(); -+ } -+ obj4.free(); -+ } -+ obj3.free(); -+ } -+ fontDesc.free(); -+ -+ t = fontUnknownType; -+ if (embID->num >= 0) { -+ obj3.initRef(embID->num, embID->gen); -+ obj3.fetch(xref, &obj4); -+ if (obj4.isStream()) { -+ obj4.streamReset(); -+ fft = FoFiIdentifier::identifyStream(&readFromStream, obj4.getStream()); -+ obj4.streamClose(); -+ switch (fft) { -+ case fofiIdType1PFA: -+ case fofiIdType1PFB: -+ t = fontType1; -+ break; -+ case fofiIdCFF8Bit: -+ t = isType0 ? fontCIDType0C : fontType1C; -+ break; -+ case fofiIdCFFCID: -+ t = fontCIDType0C; -+ break; -+ case fofiIdTrueType: -+ case fofiIdTrueTypeCollection: -+ t = isType0 ? fontCIDType2 : fontTrueType; -+ break; -+ case fofiIdOpenTypeCFF8Bit: -+ t = isType0 ? fontCIDType0COT : fontType1COT; -+ break; -+ case fofiIdOpenTypeCFFCID: -+ t = fontCIDType0COT; -+ break; -+ default: -+ error(errSyntaxError, -1, "Embedded font file may be invalid"); -+ break; -+ } -+ } -+ obj4.free(); -+ obj3.free(); -+ } -+ -+ if (t == fontUnknownType) { -+ t = expectedType; - } -+ -+ if (t != expectedType) { -+ err = gTrue; -+ } -+ -+ if (err) { -+ error(errSyntaxWarning, -1, -+ "Mismatch between font type and embedded font file"); -+ } -+ -+ obj2.free(); -+ obj1.free(); -+ -+ return t; - } - - void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { -@@ -170,8 +417,6 @@ - // assume Times-Roman by default (for substitution purposes) - flags = fontSerif; - -- embFontID.num = -1; -- embFontID.gen = -1; - missingWidth = 0; - - if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) { -@@ -189,75 +434,6 @@ - } - obj2.free(); - -- // look for embedded font file -- if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) { -- embFontID = obj2.getRef(); -- if (type != fontType1) { -- error(-1, "Mismatch between font type and embedded font file"); -- type = fontType1; -- } -- } -- obj2.free(); -- if (embFontID.num == -1 && -- obj1.dictLookupNF("FontFile2", &obj2)->isRef()) { -- embFontID = obj2.getRef(); -- if (type != fontTrueType && type != fontCIDType2) { -- error(-1, "Mismatch between font type and embedded font file"); -- type = type == fontCIDType0 ? fontCIDType2 : fontTrueType; -- } -- } -- obj2.free(); -- if (embFontID.num == -1 && -- obj1.dictLookupNF("FontFile3", &obj2)->isRef()) { -- if (obj2.fetch(xref, &obj3)->isStream()) { -- obj3.streamGetDict()->lookup("Subtype", &obj4); -- if (obj4.isName("Type1")) { -- embFontID = obj2.getRef(); -- if (type != fontType1) { -- error(-1, "Mismatch between font type and embedded font file"); -- type = fontType1; -- } -- } else if (obj4.isName("Type1C")) { -- embFontID = obj2.getRef(); -- if (type != fontType1 && type != fontType1C) { -- error(-1, "Mismatch between font type and embedded font file"); -- } -- type = fontType1C; -- } else if (obj4.isName("TrueType")) { -- embFontID = obj2.getRef(); -- if (type != fontTrueType) { -- error(-1, "Mismatch between font type and embedded font file"); -- type = fontTrueType; -- } -- } else if (obj4.isName("CIDFontType0C")) { -- embFontID = obj2.getRef(); -- if (type != fontCIDType0) { -- error(-1, "Mismatch between font type and embedded font file"); -- } -- type = fontCIDType0C; -- } else if (obj4.isName("OpenType")) { -- embFontID = obj2.getRef(); -- if (type == fontTrueType) { -- type = fontTrueTypeOT; -- } else if (type == fontType1) { -- type = fontType1COT; -- } else if (type == fontCIDType0) { -- type = fontCIDType0COT; -- } else if (type == fontCIDType2) { -- type = fontCIDType2OT; -- } else { -- error(-1, "Mismatch between font type and embedded font file"); -- } -- } else { -- error(-1, "Unknown embedded font type '%s'", -- obj4.isName() ? obj4.getName() : "???"); -- } -- obj4.free(); -- } -- obj3.free(); -- } -- obj2.free(); -- - // look for MissingWidth - obj1.dictLookup("MissingWidth", &obj2); - if (obj2.isNum()) { -@@ -269,8 +445,13 @@ - obj1.dictLookup("Ascent", &obj2); - if (obj2.isNum()) { - t = 0.001 * obj2.getNum(); -- // some broken font descriptors set ascent and descent to 0 -- if (t != 0) { -+ // some broken font descriptors specify a negative ascent -+ if (t < 0) { -+ t = -t; -+ } -+ // some broken font descriptors set ascent and descent to 0; -+ // others set it to ridiculous values (e.g., 32768) -+ if (t != 0 && t < 3) { - ascent = t; - } - } -@@ -278,14 +459,14 @@ - obj1.dictLookup("Descent", &obj2); - if (obj2.isNum()) { - t = 0.001 * obj2.getNum(); -+ // some broken font descriptors specify a positive descent -+ if (t > 0) { -+ t = -t; -+ } - // some broken font descriptors set ascent and descent to 0 -- if (t != 0) { -+ if (t != 0 && t > -3) { - descent = t; - } -- // some broken font descriptors specify a positive descent -- if (descent > 0) { -- descent = -descent; -- } - } - obj2.free(); - -@@ -330,37 +511,280 @@ - return ctu; - } - --void GfxFont::findExtFontFile() { -- static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL }; -- static char *ttExts[] = { ".ttf", NULL }; -+GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { -+ GfxFontLoc *fontLoc; -+ SysFontType sysFontType; -+ GString *path, *base14Name, *substName; -+ PSFontParam16 *psFont16; -+ Object refObj, embFontObj; -+ int substIdx, fontNum; -+ GBool embed; - -- if (name) { -- if (type == fontType1) { -- extFontFile = globalParams->findFontFile(name, type1Exts); -- } else if (type == fontTrueType) { -- extFontFile = globalParams->findFontFile(name, ttExts); -+ if (type == fontType3) { -+ return NULL; -+ } -+ -+ //----- embedded font -+ if (embFontID.num >= 0) { -+ embed = gTrue; -+ refObj.initRef(embFontID.num, embFontID.gen); -+ refObj.fetch(xref, &embFontObj); -+ if (!embFontObj.isStream()) { -+ error(errSyntaxError, -1, "Embedded font object is wrong type"); -+ embed = gFalse; -+ } -+ embFontObj.free(); -+ refObj.free(); -+ if (embed) { -+ if (ps) { -+ switch (type) { -+ case fontType1: -+ case fontType1C: -+ case fontType1COT: -+ embed = globalParams->getPSEmbedType1(); -+ break; -+ case fontTrueType: -+ case fontTrueTypeOT: -+ embed = globalParams->getPSEmbedTrueType(); -+ break; -+ case fontCIDType0C: -+ case fontCIDType0COT: -+ embed = globalParams->getPSEmbedCIDPostScript(); -+ break; -+ case fontCIDType2: -+ case fontCIDType2OT: -+ embed = globalParams->getPSEmbedCIDTrueType(); -+ break; -+ default: -+ break; -+ } -+ } -+ if (embed) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocEmbedded; -+ fontLoc->fontType = type; -+ fontLoc->embFontID = embFontID; -+ return fontLoc; -+ } -+ } -+ } -+ -+ //----- PS passthrough -+ if (ps && !isCIDFont() && globalParams->getPSFontPassthrough()) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocResident; -+ fontLoc->fontType = fontType1; -+ fontLoc->path = name->copy(); -+ return fontLoc; -+ } -+ -+ //----- PS resident Base-14 font -+ if (ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocResident; -+ fontLoc->fontType = fontType1; -+ fontLoc->path = new GString(((Gfx8BitFont *)this)->base14->base14Name); -+ return fontLoc; -+ } -+ -+ //----- external font file (fontFile, fontDir) -+ if ((path = globalParams->findFontFile(name))) { -+ if ((fontLoc = getExternalFont(path, isCIDFont()))) { -+ return fontLoc; -+ } -+ } -+ -+ //----- external font file for Base-14 font -+ if (!ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) { -+ base14Name = new GString(((Gfx8BitFont *)this)->base14->base14Name); -+ if ((path = globalParams->findFontFile(base14Name))) { -+ if ((fontLoc = getExternalFont(path, gFalse))) { -+ delete base14Name; -+ return fontLoc; -+ } -+ } -+ delete base14Name; -+ } -+ -+ //----- system font -+ if ((path = globalParams->findSystemFontFile(name, &sysFontType, -+ &fontNum))) { -+ if (isCIDFont()) { -+ if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocExternal; -+ fontLoc->fontType = fontCIDType2; -+ fontLoc->path = path; -+ fontLoc->fontNum = fontNum; -+ return fontLoc; -+ } -+ } else { -+ if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocExternal; -+ fontLoc->fontType = fontTrueType; -+ fontLoc->path = path; -+ return fontLoc; -+ } else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocExternal; -+ fontLoc->fontType = fontType1; -+ fontLoc->path = path; -+ fontLoc->fontNum = fontNum; -+ return fontLoc; -+ } -+ } -+ delete path; -+ } -+ -+ if (!isCIDFont()) { -+ -+ //----- 8-bit PS resident font -+ if (ps) { -+ if ((path = globalParams->getPSResidentFont(name))) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocResident; -+ fontLoc->fontType = fontType1; -+ fontLoc->path = path; -+ return fontLoc; -+ } -+ } -+ -+ //----- 8-bit font substitution -+ if (flags & fontFixedWidth) { -+ substIdx = 0; -+ } else if (flags & fontSerif) { -+ substIdx = 8; -+ } else { -+ substIdx = 4; -+ } -+ if (isBold()) { -+ substIdx += 2; -+ } -+ if (isItalic()) { -+ substIdx += 1; -+ } -+ substName = new GString(base14SubstFonts[substIdx]); -+ if (ps) { -+ error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'", -+ base14SubstFonts[substIdx], name); -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocResident; -+ fontLoc->fontType = fontType1; -+ fontLoc->path = substName; -+ fontLoc->substIdx = substIdx; -+ return fontLoc; -+ } else { -+ path = globalParams->findFontFile(substName); -+ delete substName; -+ if (path) { -+ if ((fontLoc = getExternalFont(path, gFalse))) { -+ error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'", -+ base14SubstFonts[substIdx], name); -+ fontLoc->substIdx = substIdx; -+ return fontLoc; -+ } -+ } -+ } -+ -+ // failed to find a substitute font -+ return NULL; -+ } -+ -+ //----- 16-bit PS resident font -+ if (ps && ((psFont16 = globalParams->getPSResidentFont16( -+ name, -+ ((GfxCIDFont *)this)->getWMode())))) { -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocResident; -+ fontLoc->fontType = fontCIDType0; // this is not used -+ fontLoc->path = psFont16->psFontName->copy(); -+ fontLoc->encoding = psFont16->encoding->copy(); -+ fontLoc->wMode = psFont16->wMode; -+ return fontLoc; -+ } -+ if (ps && ((psFont16 = globalParams->getPSResidentFontCC( -+ ((GfxCIDFont *)this)->getCollection(), -+ ((GfxCIDFont *)this)->getWMode())))) { -+ error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'", -+ psFont16->psFontName, name); -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocResident; -+ fontLoc->fontType = fontCIDType0; // this is not used -+ fontLoc->path = psFont16->psFontName->copy(); -+ fontLoc->encoding = psFont16->encoding->copy(); -+ fontLoc->wMode = psFont16->wMode; -+ return fontLoc; -+ } -+ -+ //----- CID font substitution -+ if ((path = globalParams->findCCFontFile( -+ ((GfxCIDFont *)this)->getCollection()))) { -+ if ((fontLoc = getExternalFont(path, gTrue))) { -+ error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'", -+ fontLoc->path, name); -+ return fontLoc; - } - } -+ -+ // failed to find a substitute font -+ return NULL; - } - --char *GfxFont::readExtFontFile(int *len) { -- FILE *f; -- char *buf; -+GfxFontLoc *GfxFont::locateBase14Font(GString *base14Name) { -+ GString *path; - -- if (!(f = fopen(extFontFile->getCString(), "rb"))) { -- error(-1, "External font file '%s' vanished", extFontFile->getCString()); -+ path = globalParams->findFontFile(base14Name); -+ if (!path) { - return NULL; - } -- fseek(f, 0, SEEK_END); -- *len = (int)ftell(f); -- fseek(f, 0, SEEK_SET); -- buf = (char *)gmalloc(*len); -- if ((int)fread(buf, 1, *len, f) != *len) { -- error(-1, "Error reading external font file '%s'", -- extFontFile->getCString()); -+ return getExternalFont(path, gFalse); -+} -+ -+GfxFontLoc *GfxFont::getExternalFont(GString *path, GBool cid) { -+ FoFiIdentifierType fft; -+ GfxFontType fontType; -+ GfxFontLoc *fontLoc; -+ -+ fft = FoFiIdentifier::identifyFile(path->getCString()); -+ switch (fft) { -+ case fofiIdType1PFA: -+ case fofiIdType1PFB: -+ fontType = fontType1; -+ break; -+ case fofiIdCFF8Bit: -+ fontType = fontType1C; -+ break; -+ case fofiIdCFFCID: -+ fontType = fontCIDType0C; -+ break; -+ case fofiIdTrueType: -+ case fofiIdTrueTypeCollection: -+ fontType = cid ? fontCIDType2 : fontTrueType; -+ break; -+ case fofiIdOpenTypeCFF8Bit: -+ fontType = fontType1COT; -+ break; -+ case fofiIdOpenTypeCFFCID: -+ fontType = fontCIDType0COT; -+ break; -+ case fofiIdUnknown: -+ case fofiIdError: -+ default: -+ fontType = fontUnknownType; -+ break; -+ } -+ if (fontType == fontUnknownType || -+ (cid ? (fontType < fontCIDType0) -+ : (fontType >= fontCIDType0))) { -+ delete path; -+ return NULL; - } -- fclose(f); -- return buf; -+ fontLoc = new GfxFontLoc(); -+ fontLoc->locType = gfxFontLocExternal; -+ fontLoc->fontType = fontType; -+ fontLoc->path = path; -+ return fontLoc; - } - - char *GfxFont::readEmbFontFile(XRef *xref, int *len) { -@@ -386,6 +810,10 @@ - str->reset(); - while ((c = str->getChar()) != EOF) { - if (i == size) { -+ if (size > INT_MAX - 4096) { -+ error(errSyntaxError, -1, "Embedded font file is too large"); -+ break; -+ } - size += 4096; - buf = (char *)grealloc(buf, size); - } -@@ -405,8 +833,8 @@ - //------------------------------------------------------------------------ - - Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, -- GfxFontType typeA, Dict *fontDict): -- GfxFont(tagA, idA, nameA) -+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict): -+ GfxFont(tagA, idA, nameA, typeA, embFontIDA) - { - GString *name2; - BuiltinFont *builtinFont; -@@ -428,11 +856,11 @@ - Object obj1, obj2, obj3; - int n, i, a, b, m; - -- type = typeA; - ctu = NULL; - - // do font name substitution for various aliases of the Base 14 font - // names - base14 = NULL; - if (name) { - name2 = name->copy(); - i = 0; -@@ -499,9 +927,6 @@ - fontBBox[3] = 0.001 * builtinFont->bbox[3]; - } - -- // look for an external font file -- findExtFontFile(); -- - // get font matrix - fontMat[0] = fontMat[3] = 1; - fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0; -@@ -581,54 +1007,45 @@ - baseEnc = winAnsiEncoding; - } - -- // check embedded or external font file for base encoding -+ // check embedded font file for base encoding - // (only for Type 1 fonts - trying to get an encoding out of a - // TrueType font is a losing proposition) - ffT1 = NULL; - ffT1C = NULL; - buf = NULL; -- if (type == fontType1 && (extFontFile || embFontID.num >= 0)) { -- if (extFontFile) { -- ffT1 = FoFiType1::load(extFontFile->getCString()); -- } else { -- buf = readEmbFontFile(xref, &len); -- ffT1 = FoFiType1::make(buf, len); -- } -- if (ffT1) { -- if (ffT1->getName()) { -- if (embFontName) { -- delete embFontName; -+ if (type == fontType1 && embFontID.num >= 0) { -+ if ((buf = readEmbFontFile(xref, &len))) { -+ if ((ffT1 = FoFiType1::make(buf, len))) { -+ if (ffT1->getName()) { -+ if (embFontName) { -+ delete embFontName; -+ } -+ embFontName = new GString(ffT1->getName()); -+ } -+ if (!baseEnc) { -+ baseEnc = (const char **)ffT1->getEncoding(); -+ baseEncFromFontFile = gTrue; - } -- embFontName = new GString(ffT1->getName()); -- } -- if (!baseEnc) { -- baseEnc = (const char **)ffT1->getEncoding(); -- baseEncFromFontFile = gTrue; - } -+ gfree(buf); - } -- } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) { -- if (extFontFile) { -- ffT1C = FoFiType1C::load(extFontFile->getCString()); -- } else { -- buf = readEmbFontFile(xref, &len); -- ffT1C = FoFiType1C::make(buf, len); -- } -- if (ffT1C) { -- if (ffT1C->getName()) { -- if (embFontName) { -- delete embFontName; -+ } else if (type == fontType1C && embFontID.num >= 0) { -+ if ((buf = readEmbFontFile(xref, &len))) { -+ if ((ffT1C = FoFiType1C::make(buf, len))) { -+ if (ffT1C->getName()) { -+ if (embFontName) { -+ delete embFontName; -+ } -+ embFontName = new GString(ffT1C->getName()); -+ } -+ if (!baseEnc) { -+ baseEnc = (const char **)ffT1C->getEncoding(); -+ baseEncFromFontFile = gTrue; - } -- embFontName = new GString(ffT1C->getName()); -- } -- if (!baseEnc) { -- baseEnc = (const char **)ffT1C->getEncoding(); -- baseEncFromFontFile = gTrue; - } -+ gfree(buf); - } - } -- if (buf) { -- gfree(buf); -- } - - // get default base encoding - if (!baseEnc) { -@@ -644,7 +1061,7 @@ - - // copy the base encoding - for (i = 0; i < 256; ++i) { -- enc[i] = baseEnc[i]; -+ enc[i] = (char *)baseEnc[i]; - if ((encFree[i] = baseEncFromFontFile) && enc[i]) { - enc[i] = copyString(baseEnc[i]); - } -@@ -654,11 +1071,10 @@ - // T1C->T1 conversion (since the 'seac' operator depends on having - // the accents in the encoding), so we fill in any gaps from - // StandardEncoding -- if (type == fontType1C && (extFontFile || embFontID.num >= 0) && -- baseEncFromFontFile) { -+ if (type == fontType1C && embFontID.num >= 0 && baseEncFromFontFile) { - for (i = 0; i < 256; ++i) { - if (!enc[i] && standardEncoding[i]) { - enc[i] = (char *)standardEncoding[i]; - encFree[i] = gFalse; - } - } -@@ -734,14 +1151,21 @@ - } - - // pass 2: try to fill in the missing chars, looking for names of -- // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B' -- // are any letters, 'xx' is two hex digits, and 'nn' is 2-4 -- // decimal digits -+ // any of the following forms: -+ // - 'xx' -+ // - 'Axx' -+ // - 'nn' -+ // - 'Ann' -+ // - 'ABnn' -+ // - 'unixxxx' (possibly followed by garbage - some Arabic files -+ // use 'uni0628.medi', etc.) -+ // where 'A' and 'B' are any letters, 'xx' is two hex digits, 'xxxx' -+ // is four hex digits, and 'nn' is 2-4 decimal digits - if (missing && globalParams->getMapNumericCharNames()) { - for (code = 0; code < 256; ++code) { - if ((charName = enc[code]) && !toUnicode[code] && - strcmp(charName, ".notdef")) { - n = strlen(charName); - code2 = -1; - if (hex && n == 3 && isalpha(charName[0]) && - isxdigit(charName[1]) && isxdigit(charName[2])) { -@@ -758,8 +1182,13 @@ - } else if (n >= 4 && n <= 6 && - isdigit(charName[2]) && isdigit(charName[3])) { - code2 = atoi(charName+2); -+ } else if (n >= 7 && charName[0] == 'u' && charName[1] == 'n' && -+ charName[2] == 'i' && -+ isxdigit(charName[3]) && isxdigit(charName[4]) && -+ isxdigit(charName[5]) && isxdigit(charName[6])) { -+ sscanf(charName + 3, "%x", &code2); - } -- if (code2 >= 0 && code2 <= 0xff) { -+ if (code2 >= 0 && code2 <= 0xffff) { - toUnicode[code] = (Unicode)code2; - } - } -@@ -835,7 +1264,7 @@ - obj1.arrayGet(code - firstChar, &obj2); - if (obj2.isNum()) { - widths[code] = obj2.getNum() * mul; -- if (widths[code] != widths[firstChar]) { -+ if (fabs(widths[code] - widths[firstChar]) > 0.00001) { - flags &= ~fontFixedWidth; - } - } -@@ -945,9 +1374,10 @@ - // TrueType font has a Macintosh Roman cmap, use it, and - // reverse map the char names through MacRomanEncoding to - // get char codes. -- // 1b. If the TrueType font has a Microsoft Unicode cmap or a -- // non-Microsoft Unicode cmap, use it, and use the Unicode -- // indexes, not the char codes. -+ // 1b. If the PDF font is not symbolic or the PDF font is not -+ // embedded, and the TrueType font has a Microsoft Unicode -+ // cmap or a non-Microsoft Unicode cmap, use it, and use the -+ // Unicode indexes, not the char codes. - // 1c. If the PDF font is symbolic and the TrueType font has a - // Microsoft Symbol cmap, use it, and use char codes - // directly (possibly with an offset of 0xf000). -@@ -983,7 +1413,8 @@ - if (usesMacRomanEnc && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; -- } else if (unicodeCmap >= 0) { -+ } else if ((!(flags & fontSymbolic) || embFontID.num < 0) && -+ unicodeCmap >= 0) { - cmap = unicodeCmap; - useUnicode = gTrue; - } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) { -@@ -1010,6 +1441,8 @@ - if ((code = globalParams->getMacRomanCharCode(charName))) { - map[i] = ff->mapCodeToGID(cmap, code); - } -+ } else { -+ map[i] = -1; - } - } - -@@ -1020,6 +1453,8 @@ - (u = globalParams->mapNameToUnicode(charName))) || - (n = ctu->mapToUnicode((CharCode)i, &u, 1))) { - map[i] = ff->mapCodeToGID(cmap, u); -+ } else { -+ map[i] = -1; - } - } - -@@ -1035,8 +1470,8 @@ - - // try the TrueType 'post' table to handle any unmapped characters - for (i = 0; i < 256; ++i) { -- if (!map[i] && (charName = enc[i])) { -+ if (map[i] <= 0 && (charName = enc[i])) { - map[i] = ff->mapNameToGID(charName); - } - } - -@@ -1077,12 +1530,11 @@ - GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, -- Dict *fontDict): -- GfxFont(tagA, idA, nameA) -+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict): -+ GfxFont(tagA, idA, nameA, typeA, embFontIDA) - { - Dict *desFontDict; -- GString *collection, *cMapName; - Object desFontDictObj; - Object obj1, obj2, obj3, obj4, obj5, obj6; - CharCodeToUnicode *utu; -@@ -1091,8 +1545,10 @@ - ascent = 0.95; - descent = -0.35; - fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; -+ collection = NULL; - cMap = NULL; - ctu = NULL; -+ ctuUsesCharCode = gTrue; - widths.defWidth = 1.0; - widths.defHeight = -1.0; - widths.defVY = 0.880; -@@ -1104,52 +1560,38 @@ - cidToGIDLen = 0; - - // get the descendant font -- if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) { -- error(-1, "Missing DescendantFonts entry in Type 0 font"); -+ if (!fontDict->lookup("DescendantFonts", &obj1)->isArray() || -+ obj1.arrayGetLength() == 0) { -+ error(errSyntaxError, -1, -+ "Missing or empty DescendantFonts entry in Type 0 font"); - obj1.free(); -+ - goto err1; - } - if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) { -- error(-1, "Bad descendant font in Type 0 font"); -- goto err3; -+ error(errSyntaxError, -1, "Bad descendant font in Type 0 font"); -+ goto err2; - } - obj1.free(); - desFontDict = desFontDictObj.getDict(); - -- // font type -- if (!desFontDict->lookup("Subtype", &obj1)) { -- error(-1, "Missing Subtype entry in Type 0 descendant font"); -- goto err3; -- } -- if (obj1.isName("CIDFontType0")) { -- type = fontCIDType0; -- } else if (obj1.isName("CIDFontType2")) { -- type = fontCIDType2; -- } else { -- error(-1, "Unknown Type 0 descendant font type '%s'", -- obj1.isName() ? obj1.getName() : "???"); -- goto err3; -- } -- obj1.free(); -- - // get info from font descriptor - readFontDescriptor(xref, desFontDict); - -- // look for an external font file -- findExtFontFile(); -- - //----- encoding info ----- - - // char collection - if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) { -- error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font"); -- goto err3; -+ error(errSyntaxError, -1, -+ "Missing CIDSystemInfo dictionary in Type 0 descendant font"); -+ goto err2; - } - obj1.dictLookup("Registry", &obj2); - obj1.dictLookup("Ordering", &obj3); - if (!obj2.isString() || !obj3.isString()) { -- error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); -- goto err4; -+ error(errSyntaxError, -1, -+ "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); -+ goto err3; - } - collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); - obj3.free(); -@@ -1158,19 +1600,18 @@ - - // look for a ToUnicode CMap - if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { -+ ctuUsesCharCode = gFalse; - -- // the "Adobe-Identity" and "Adobe-UCS" collections don't have -- // cidToUnicode files -- if (collection->cmp("Adobe-Identity") && -- collection->cmp("Adobe-UCS")) { -- -- // look for a user-supplied .cidToUnicode file -- if (!(ctu = globalParams->getCIDToUnicode(collection))) { -- error(-1, "Unknown character collection '%s'", -- collection->getCString()); -- // fall-through, assuming the Identity mapping -- this appears -- // to match Adobe's behavior -- } -+ // use an identity mapping for the "Adobe-Identity" and -+ // "Adobe-UCS" collections -+ if (!collection->cmp("Adobe-Identity") || -+ !collection->cmp("Adobe-UCS")) { -+ ctu = CharCodeToUnicode::makeIdentityMapping(); -+ -+ // look for a user-supplied .cidToUnicode file -+ } else if (!(ctu = globalParams->getCIDToUnicode(collection))) { -+ error(errSyntaxError, -1, -+ "Unknown character collection '{0:t}'", collection); - } - } - -@@ -1193,43 +1634,35 @@ - } - - // encoding (i.e., CMap) -- //~ need to handle a CMap stream here -- //~ also need to deal with the UseCMap entry in the stream dict -- if (!fontDict->lookup("Encoding", &obj1)->isName()) { -- error(-1, "Missing or invalid Encoding entry in Type 0 font"); -- delete collection; -- goto err3; -+ if (fontDict->lookup("Encoding", &obj1)->isNull()) { -+ error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font"); -+ goto err2; - } -- cMapName = new GString(obj1.getName()); -- obj1.free(); -- if (!(cMap = globalParams->getCMap(collection, cMapName))) { -- error(-1, "Unknown CMap '%s' for character collection '%s'", -- cMapName->getCString(), collection->getCString()); -- delete collection; -- delete cMapName; -+ if (!(cMap = CMap::parse(NULL, collection, &obj1))) { - goto err2; - } -- delete collection; -- delete cMapName; -+ obj1.free(); - -- // CIDToGIDMap (for embedded TrueType fonts) -- if (type == fontCIDType2) { -+ // CIDToGIDMap -+ // (the PDF spec only allows these for TrueType fonts, but Acrobat -+ // apparently also allows them for OpenType CFF fonts) -+ if (type == fontCIDType2 || type == fontCIDType0COT) { - desFontDict->lookup("CIDToGIDMap", &obj1); - if (obj1.isStream()) { - cidToGIDLen = 0; - i = 64; -@@ -1387,17 +1830,19 @@ - ok = gTrue; - return; - -- err4: -+ err3: - obj3.free(); - obj2.free(); -- err3: -- obj1.free(); - err2: -+ obj1.free(); - desFontDictObj.free(); - err1:; - } - - GfxCIDFont::~GfxCIDFont() { -+ if (collection) { -+ delete collection; -+ } - if (cMap) { - cMap->decRefCnt(); - } -@@ -1425,12 +1871,16 @@ - return 1; - } - - *code = (CharCode)(cid = cMap->getCID(s, len, &c, &n)); - if (ctu) { -- *uLen = ctu->mapToUnicode(cid, u, uSize); -+ *uLen = ctu->mapToUnicode(ctuUsesCharCode ? c : cid, u, uSize); - } else { - *uLen = 0; - } -+ if (!*uLen && uSize >= 1 && globalParams->getMapUnknownCharNames()) { -+ u[0] = *code; -+ *uLen = 1; -+ } - - // horizontal - if (cMap->getWMode() == 0) { -diff -ru xpdf-3.02/xpdf/GfxFont.h xpdf-3.03/xpdf/GfxFont.h ---- xpdf-3.02/xpdf/GfxFont.h 2007-02-27 23:05:52.000000000 +0100 -+++ xpdf-3.03/xpdf/GfxFont.h 2011-08-15 23:08:53.000000000 +0200 -@@ -91,7 +127,8 @@ - // Build a GfxFont object. - static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict); - -- GfxFont(char *tagA, Ref idA, GString *nameA); -+ GfxFont(char *tagA, Ref idA, GString *nameA, -+ GfxFontType typeA, Ref embFontIDA); - - virtual ~GfxFont(); - -@@ -126,10 +160,6 @@ - // NULL if there is no embedded font. - GString *getEmbeddedFontName() { return embFontName; } - -- // Get the name of the external font file. Returns NULL if there -- // is no external font file. -- GString *getExtFontFile() { return extFontFile; } -- - // Get font descriptor flags. - int getFlags() { return flags; } - GBool isFixedWidth() { return flags & fontFixedWidth; } -@@ -151,8 +181,14 @@ - // Return the writing mode (0=horizontal, 1=vertical). - virtual int getWMode() { return 0; } - -- // Read an external or embedded font file into a buffer. -- char *readExtFontFile(int *len); -+ // Locate the font file for this font. If <ps> is true, includes PS -+ // printer-resident fonts. Returns NULL on failure. -+ GfxFontLoc *locateFont(XRef *xref, GBool ps); -+ -+ // Locate a Base-14 font file for a specified font name. -+ static GfxFontLoc *locateBase14Font(GString *base14Name); -+ -+ // Read an embedded font file into a buffer. - char *readEmbFontFile(XRef *xref, int *len); - - // Get the next char from a string <s> of <len> bytes, returning the -@@ -167,22 +203,21 @@ - - protected: - -+ static GfxFontType getFontType(XRef *xref, Dict *fontDict, Ref *embID); - void readFontDescriptor(XRef *xref, Dict *fontDict); - CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits, - CharCodeToUnicode *ctu); -- void findExtFontFile(); -+ static GfxFontLoc *getExternalFont(GString *path, GBool cid); - - GString *tag; // PDF font tag - Ref id; // reference (used as unique ID) - GString *name; // font name - GfxFontType type; // type of font - int flags; // font descriptor flags - GString *embFontName; // name of embedded font - Ref embFontID; // ref to embedded font file stream -- GString *extFontFile; // external font file name -- double fontMat[6]; // font matrix (Type 3 only) -- double fontBBox[4]; // font bounding box (Type 3 only) -+ double fontMat[6]; // font matrix -+ double fontBBox[4]; // font bounding box - double missingWidth; // "default" width - double ascent; // max height above baseline - double descent; // max depth below baseline -@@ -197,7 +232,7 @@ - public: - - Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, -- GfxFontType typeA, Dict *fontDict); -+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict); - - virtual ~Gfx8BitFont(); - -@@ -247,6 +283,8 @@ - double widths[256]; // character widths - Object charProcs; // Type 3 CharProcs dictionary - Object resources; // Type 3 Resources dictionary -+ -+ friend class GfxFont; - }; - - //------------------------------------------------------------------------ -@@ -257,7 +295,7 @@ - public: - - GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, -- Dict *fontDict); -+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict); - - virtual ~GfxCIDFont(); - -@@ -278,15 +316,18 @@ - - private: - -+ GString *collection; // collection name - CMap *cMap; // char code --> CID -- CharCodeToUnicode *ctu; // CID --> Unicode -+ CharCodeToUnicode *ctu; // CID/char code --> Unicode -+ 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/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 -@@ -819,26 +854,27 @@ - obj1.free(); - arr->get(1, &obj1); - if (!obj1.isStream()) { - error(errSyntaxError, -1, "Bad ICCBased color space (stream)"); - obj1.free(); - return NULL; - } - dict = obj1.streamGetDict(); - if (!dict->lookup("N", &obj2)->isInt()) { - error(errSyntaxError, -1, "Bad ICCBased color space (N)"); - obj2.free(); - obj1.free(); - return NULL; - } - nCompsA = obj2.getInt(); - obj2.free(); -- if (nCompsA > gfxColorMaxComps) { -- error(-1, "ICCBased color space with too many (%d > %d) components", -- nCompsA, gfxColorMaxComps); -- nCompsA = gfxColorMaxComps; -+ if (nCompsA > 4) { -+ error(errSyntaxError, -1, -+ "ICCBased color space with too many ({0:d} > 4) components", -+ nCompsA); -+ nCompsA = 4; - } - if (dict->lookup("Alternate", &obj2)->isNull() || -@@ -986,8 +1025,9 @@ - for (i = 0; i <= indexHighA; ++i) { - for (j = 0; j < n; ++j) { - if ((x = obj1.streamGetChar()) == EOF) { -- error(-1, "Bad Indexed color space (lookup table stream too short)"); -- goto err3; -+ error(errSyntaxError, -1, -+ "Bad Indexed color space (lookup table stream too short)"); -+ cs->indexHigh = indexHighA = i - 1; - } - cs->lookup[i*n + j] = (Guchar)x; - } -@@ -995,8 +1035,9 @@ - obj1.streamClose(); - } else if (obj1.isString()) { - if (obj1.getString()->getLength() < (indexHighA + 1) * n) { -- error(-1, "Bad Indexed color space (lookup table string too short)"); -- goto err3; -+ error(errSyntaxError, -1, -+ "Bad Indexed color space (lookup table string too short)"); -+ cs->indexHigh = indexHighA = obj1.getString()->getLength() / n - 1; - } - s = obj1.getString()->getCString(); - for (i = 0; i <= indexHighA; ++i) { -@@ -1254,14 +1354,7 @@ - goto err4; - } - obj1.free(); -- cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA); -- cs->nonMarking = gTrue; -- for (i = 0; i < nCompsA; ++i) { -- cs->names[i] = namesA[i]; -- if (namesA[i]->cmp("None")) { -- cs->nonMarking = gFalse; -- } -- } -+ cs = new GfxDeviceNColorSpace(nCompsA, namesA, altA, funcA); - return cs; - - err4: -@@ -3187,7 +3299,7 @@ - GfxIndexedColorSpace *indexedCS; - GfxSeparationColorSpace *sepCS; - int maxPixel, indexHigh; -- Guchar *lookup2; -+ Guchar *indexedLookup; - Function *sepFunc; - Object obj; - double x[gfxColorMaxComps]; -@@ -3204,6 +3316,7 @@ - // initialize - for (k = 0; k < gfxColorMaxComps; ++k) { - lookup[k] = NULL; -+ lookup2[k] = NULL; - } - - // get decode map -@@ -3236,10 +3353,18 @@ - // Construct a lookup table -- this stores pre-computed decoded - // values for each component, i.e., the result of applying the - // decode mapping to each possible image pixel component value. -- // -+ for (k = 0; k < nComps; ++k) { -+ lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, -+ sizeof(GfxColorComp)); -+ for (i = 0; i <= maxPixel; ++i) { -+ lookup[k][i] = dblToCol(decodeLow[k] + -+ (i * decodeRange[k]) / maxPixel); -+ } -+ } -+ - // Optimization: for Indexed and Separation color spaces (which have -- // only one component), we store color values in the lookup table -- // rather than component values. -+ // only one component), we pre-compute a second lookup table with -+ // color values - colorSpace2 = NULL; - nComps2 = 0; - if (colorSpace->getMode() == csIndexed) { -@@ -3250,20 +3375,22 @@ - colorSpace2 = indexedCS->getBase(); - indexHigh = indexedCS->getIndexHigh(); - nComps2 = colorSpace2->getNComps(); -- lookup2 = indexedCS->getLookup(); -+ indexedLookup = indexedCS->getLookup(); - colorSpace2->getDefaultRanges(x, y, indexHigh); - for (k = 0; k < nComps2; ++k) { -- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, -- sizeof(GfxColorComp)); -- for (i = 0; i <= maxPixel; ++i) { -- j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5); -- if (j < 0) { -- j = 0; -- } else if (j > indexHigh) { -- j = indexHigh; -- } -- lookup[k][i] = -- dblToCol(x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k]); -+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1, -+ sizeof(GfxColorComp)); -+ } -+ for (i = 0; i <= maxPixel; ++i) { -+ j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5); -+ if (j < 0) { -+ j = 0; -+ } else if (j > indexHigh) { -+ j = indexHigh; -+ } -+ for (k = 0; k < nComps2; ++k) { -+ lookup2[k][i] = -+ dblToCol(x[k] + (indexedLookup[j*nComps2 + k] / 255.0) * y[k]); - } - } - } else if (colorSpace->getMode() == csSeparation) { -@@ -3272,21 +3399,14 @@ - nComps2 = colorSpace2->getNComps(); - sepFunc = sepCS->getFunc(); - for (k = 0; k < nComps2; ++k) { -- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, -- sizeof(GfxColorComp)); -- for (i = 0; i <= maxPixel; ++i) { -- x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel; -- sepFunc->transform(x, y); -- lookup[k][i] = dblToCol(y[k]); -- } -+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1, -+ sizeof(GfxColorComp)); - } -- } else { -- for (k = 0; k < nComps; ++k) { -- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, -- sizeof(GfxColorComp)); -- for (i = 0; i <= maxPixel; ++i) { -- lookup[k][i] = dblToCol(decodeLow[k] + -- (i * decodeRange[k]) / maxPixel); -+ for (i = 0; i <= maxPixel; ++i) { -+ x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel; -+ sepFunc->transform(x, y); -+ for (k = 0; k < nComps2; ++k) { -+ lookup2[k][i] = dblToCol(y[k]); - } - } - } -@@ -3309,24 +3429,24 @@ - colorSpace2 = NULL; - for (k = 0; k < gfxColorMaxComps; ++k) { - lookup[k] = NULL; -+ lookup2[k] = NULL; - } - n = 1 << bits; -+ for (k = 0; k < nComps; ++k) { -+ lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); -+ memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); -+ } - if (colorSpace->getMode() == csIndexed) { - colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); - for (k = 0; k < nComps2; ++k) { -- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); -- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); -+ lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); -+ memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); - } - } else if (colorSpace->getMode() == csSeparation) { - colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt(); - for (k = 0; k < nComps2; ++k) { -- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); -- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); -- } -- } else { -- for (k = 0; k < nComps; ++k) { -- lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); -- memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); -+ lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); -+ memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); - } - } - for (i = 0; i < nComps; ++i) { -@@ -3342,6 +3462,7 @@ - delete colorSpace; - for (i = 0; i < gfxColorMaxComps; ++i) { - gfree(lookup[i]); -+ gfree(lookup2[i]); - } - } - -@@ -3351,7 +3472,7 @@ - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { -- color.c[i] = lookup[i][x[0]]; -+ color.c[i] = lookup2[i][x[0]]; - } - colorSpace2->getGray(&color, gray); - } else { -@@ -3368,7 +3489,7 @@ - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { -- color.c[i] = lookup[i][x[0]]; -+ color.c[i] = lookup2[i][x[0]]; - } - colorSpace2->getRGB(&color, rgb); - } else { -@@ -3385,7 +3506,7 @@ - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { -- color.c[i] = lookup[i][x[0]]; -+ color.c[i] = lookup2[i][x[0]]; - } - colorSpace2->getCMYK(&color, cmyk); - } else { -@@ -3405,6 +3527,88 @@ - } - } - -+void GfxImageColorMap::getGrayByteLine(Guchar *in, Guchar *out, int n) { -+ GfxColor color; -+ GfxGray gray; -+ int i, j; -+ -+ if (colorSpace2) { -+ for (j = 0; j < n; ++j) { -+ for (i = 0; i < nComps2; ++i) { -+ color.c[i] = lookup2[i][in[j]]; -+ } -+ colorSpace2->getGray(&color, &gray); -+ out[j] = colToByte(gray); -+ } -+ } else { -+ for (j = 0; j < n; ++j) { -+ for (i = 0; i < nComps; ++i) { -+ color.c[i] = lookup[i][in[j * nComps + i]]; -+ } -+ colorSpace->getGray(&color, &gray); -+ out[j] = colToByte(gray); -+ } -+ } -+} -+ -+void GfxImageColorMap::getRGBByteLine(Guchar *in, Guchar *out, int n) { -+ GfxColor color; -+ GfxRGB rgb; -+ int i, j; -+ -+ if (colorSpace2) { -+ for (j = 0; j < n; ++j) { -+ for (i = 0; i < nComps2; ++i) { -+ color.c[i] = lookup2[i][in[j]]; -+ } -+ colorSpace2->getRGB(&color, &rgb); -+ out[j*3] = colToByte(rgb.r); -+ out[j*3 + 1] = colToByte(rgb.g); -+ out[j*3 + 2] = colToByte(rgb.b); -+ } -+ } else { -+ for (j = 0; j < n; ++j) { -+ for (i = 0; i < nComps; ++i) { -+ color.c[i] = lookup[i][in[j * nComps + i]]; -+ } -+ colorSpace->getRGB(&color, &rgb); -+ out[j*3] = colToByte(rgb.r); -+ out[j*3 + 1] = colToByte(rgb.g); -+ out[j*3 + 2] = colToByte(rgb.b); -+ } -+ } -+} -+ -+void GfxImageColorMap::getCMYKByteLine(Guchar *in, Guchar *out, int n) { -+ GfxColor color; -+ GfxCMYK cmyk; -+ int i, j; -+ -+ if (colorSpace2) { -+ for (j = 0; j < n; ++j) { -+ for (i = 0; i < nComps2; ++i) { -+ color.c[i] = lookup2[i][in[j]]; -+ } -+ colorSpace2->getCMYK(&color, &cmyk); -+ out[j*4] = colToByte(cmyk.c); -+ out[j*4 + 1] = colToByte(cmyk.m); -+ out[j*4 + 2] = colToByte(cmyk.y); -+ out[j*4 + 3] = colToByte(cmyk.k); -+ } -+ } else { -+ for (j = 0; j < n; ++j) { -+ for (i = 0; i < nComps; ++i) { -+ color.c[i] = lookup[i][in[j * nComps + i]]; -+ } -+ colorSpace->getCMYK(&color, &cmyk); -+ out[j*4] = colToByte(cmyk.c); -+ out[j*4 + 1] = colToByte(cmyk.m); -+ out[j*4 + 2] = colToByte(cmyk.y); -+ out[j*4 + 3] = colToByte(cmyk.k); -+ } -+ } -+} -+ - //------------------------------------------------------------------------ - // GfxSubpath and GfxPath - //------------------------------------------------------------------------ -@@ -3526,13 +3730,18 @@ - } - - void GfxPath::lineTo(double x, double y) { -- if (justMoved) { -+ if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) { - if (n >= size) { - size *= 2; - subpaths = (GfxSubpath **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } -- subpaths[n] = new GfxSubpath(firstX, firstY); -+ if (justMoved) { -+ subpaths[n] = new GfxSubpath(firstX, firstY); -+ } else { -+ subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(), -+ subpaths[n-1]->getLastY()); -+ } - ++n; - justMoved = gFalse; - } -@@ -3541,13 +3750,18 @@ - - void GfxPath::curveTo(double x1, double y1, double x2, double y2, - double x3, double y3) { -- if (justMoved) { -+ if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) { - if (n >= size) { - size *= 2; - subpaths = (GfxSubpath **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } -- subpaths[n] = new GfxSubpath(firstX, firstY); -+ if (justMoved) { -+ subpaths[n] = new GfxSubpath(firstX, firstY); -+ } else { -+ subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(), -+ subpaths[n-1]->getLastY()); -+ } - ++n; - justMoved = gFalse; - } -@@ -3719,13 +3934,10 @@ - // this gets set to NULL by restore() - delete path; - } -- if (saved) { -- delete saved; -- } - } - -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 -@@ -878,6 +894,11 @@ - void getCMYK(Guchar *x, GfxCMYK *cmyk); - void getColor(Guchar *x, GfxColor *color); - -+ // Convert a line of <n> pixels to 8-bit colors. -+ void getGrayByteLine(Guchar *in, Guchar *out, int n); -+ void getRGBByteLine(Guchar *in, Guchar *out, int n); -+ void getCMYKByteLine(Guchar *in, Guchar *out, int n); -+ - private: - - GfxImageColorMap(GfxImageColorMap *colorMap); -@@ -889,6 +910,8 @@ - int nComps2; // number of components in colorSpace2 - GfxColorComp * // lookup table - lookup[gfxColorMaxComps]; -+ GfxColorComp * // optimized case lookup table -+ lookup2[gfxColorMaxComps]; - double // minimum values for each component - decodeLow[gfxColorMaxComps]; - double // max - min value for each component 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 -@@ -124,215 +124,138 @@ - GlobalParams *globalParams = NULL; - - //------------------------------------------------------------------------ --// DisplayFontParam -+// PSFontParam16 - //------------------------------------------------------------------------ - --DisplayFontParam::DisplayFontParam(GString *nameA, -- DisplayFontParamKind kindA) { -+PSFontParam16::PSFontParam16(GString *nameA, int wModeA, -+ GString *psFontNameA, GString *encodingA) { - name = nameA; -- kind = kindA; -- switch (kind) { -- case displayFontT1: -- t1.fileName = NULL; -- break; -- case displayFontTT: -- tt.fileName = NULL; -- break; -- } -+ wMode = wModeA; -+ psFontName = psFontNameA; -+ encoding = encodingA; - } - --DisplayFontParam::~DisplayFontParam() { -+PSFontParam16::~PSFontParam16() { - delete name; -- switch (kind) { -- case displayFontT1: -- if (t1.fileName) { -- delete t1.fileName; -- } -- break; -- case displayFontTT: -- if (tt.fileName) { -- delete tt.fileName; -- } -- break; -- } -+ delete psFontName; -+ delete encoding; - } - --#ifdef WIN32 -- - //------------------------------------------------------------------------ --// WinFontInfo -+// SysFontInfo - //------------------------------------------------------------------------ - --class WinFontInfo: public DisplayFontParam { -+class SysFontInfo { - public: - -- GBool bold, italic; -+ GString *name; -+ GBool bold; -+ GBool italic; -+ GString *path; -+ SysFontType type; -+ int fontNum; // for TrueType collections - -- static WinFontInfo *make(GString *nameA, GBool boldA, GBool italicA, -- HKEY regKey, char *winFontDir); -- WinFontInfo(GString *nameA, GBool boldA, GBool italicA, -- GString *fileNameA); -- virtual ~WinFontInfo(); -- GBool equals(WinFontInfo *fi); -+ SysFontInfo(GString *nameA, GBool boldA, GBool italicA, -+ GString *pathA, SysFontType typeA, int fontNumA); -+ ~SysFontInfo(); -+ GBool match(SysFontInfo *fi); -+ GBool match(GString *nameA, GBool boldA, GBool italicA); - }; - --WinFontInfo *WinFontInfo::make(GString *nameA, GBool boldA, GBool italicA, -- HKEY regKey, char *winFontDir) { -- GString *regName; -- GString *fileNameA; -- char buf[MAX_PATH]; -- DWORD n; -- char c; -- int i; -- -- //----- find the font file -- fileNameA = NULL; -- regName = nameA->copy(); -- if (boldA) { -- regName->append(" Bold"); -- } -- if (italicA) { -- regName->append(" Italic"); -- } -- regName->append(" (TrueType)"); -- n = sizeof(buf); -- if (RegQueryValueEx(regKey, regName->getCString(), NULL, NULL, -- (LPBYTE)buf, &n) == ERROR_SUCCESS) { -- fileNameA = new GString(winFontDir); -- fileNameA->append('\\')->append(buf); -- } -- delete regName; -- if (!fileNameA) { -- delete nameA; -- return NULL; -- } -- -- //----- normalize the font name -- i = 0; -- while (i < nameA->getLength()) { -- c = nameA->getChar(i); -- if (c == ' ' || c == ',' || c == '-') { -- nameA->del(i); -- } else { -- ++i; -- } -- } -- -- return new WinFontInfo(nameA, boldA, italicA, fileNameA); --} -- --WinFontInfo::WinFontInfo(GString *nameA, GBool boldA, GBool italicA, -- GString *fileNameA): -- DisplayFontParam(nameA, displayFontTT) --{ -+SysFontInfo::SysFontInfo(GString *nameA, GBool boldA, GBool italicA, -+ GString *pathA, SysFontType typeA, int fontNumA) { -+ name = nameA; - bold = boldA; - italic = italicA; -- tt.fileName = fileNameA; -+ path = pathA; -+ type = typeA; -+ fontNum = fontNumA; -+} -+ -+SysFontInfo::~SysFontInfo() { -+ delete name; -+ delete path; - } - --WinFontInfo::~WinFontInfo() { -+GBool SysFontInfo::match(SysFontInfo *fi) { -+ return !strcasecmp(name->getCString(), fi->name->getCString()) && -+ bold == fi->bold && italic == fi->italic; - } - --GBool WinFontInfo::equals(WinFontInfo *fi) { -- return !name->cmp(fi->name) && bold == fi->bold && italic == fi->italic; -+GBool SysFontInfo::match(GString *nameA, GBool boldA, GBool italicA) { -+ return !strcasecmp(name->getCString(), nameA->getCString()) && -+ bold == boldA && italic == italicA; - } - - //------------------------------------------------------------------------ --// WinFontList -+// SysFontList - //------------------------------------------------------------------------ - --class WinFontList { -+class SysFontList { - public: - -- WinFontList(char *winFontDirA); -- ~WinFontList(); -- WinFontInfo *find(GString *font); -+ SysFontList(); -+ ~SysFontList(); -+ SysFontInfo *find(GString *name); -+ -+#ifdef WIN32 -+ void scanWindowsFonts(char *winFontDir); -+#endif - - private: - -- void add(WinFontInfo *fi); -- static int CALLBACK enumFunc1(CONST LOGFONT *font, -- CONST TEXTMETRIC *metrics, -- DWORD type, LPARAM data); -- static int CALLBACK enumFunc2(CONST LOGFONT *font, -- CONST TEXTMETRIC *metrics, -- DWORD type, LPARAM data); -- -- GList *fonts; // [WinFontInfo] -- HDC dc; // (only used during enumeration) -- HKEY regKey; // (only used during enumeration) -- char *winFontDir; // (only used during enumeration) --}; -+#ifdef WIN32 -+ SysFontInfo *makeWindowsFont(char *name, int fontNum, -+ char *path); -+#endif - --WinFontList::WinFontList(char *winFontDirA) { -- OSVERSIONINFO version; -- char *path; -+ GList *fonts; // [SysFontInfo] -+}; - -+SysFontList::SysFontList() { - fonts = new GList(); -- dc = GetDC(NULL); -- winFontDir = winFontDirA; -- version.dwOSVersionInfoSize = sizeof(version); -- GetVersionEx(&version); -- if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { -- path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\"; -- } else { -- path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\"; -- } -- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, -- KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, -- ®Key) == ERROR_SUCCESS) { -- EnumFonts(dc, NULL, &WinFontList::enumFunc1, (LPARAM)this); -- RegCloseKey(regKey); -- } -- ReleaseDC(NULL, dc); - } - --WinFontList::~WinFontList() { -- deleteGList(fonts, WinFontInfo); -+SysFontList::~SysFontList() { -+ deleteGList(fonts, SysFontInfo); - } - --void WinFontList::add(WinFontInfo *fi) { -- int i; -- -- for (i = 0; i < fonts->getLength(); ++i) { -- if (((WinFontInfo *)fonts->get(i))->equals(fi)) { -- delete fi; -- return; -- } -- } -- fonts->append(fi); --} -- --WinFontInfo *WinFontList::find(GString *font) { -- GString *name; -+SysFontInfo *SysFontList::find(GString *name) { -+ GString *name2; - GBool bold, italic; -- WinFontInfo *fi; -+ SysFontInfo *fi; - char c; - int n, i; - -- name = font->copy(); -+ name2 = name->copy(); - - // remove space, comma, dash chars - i = 0; -- while (i < name->getLength()) { -- c = name->getChar(i); -+ while (i < name2->getLength()) { -+ c = name2->getChar(i); - if (c == ' ' || c == ',' || c == '-') { -- name->del(i); -+ name2->del(i); - } else { - ++i; - } - } -- n = name->getLength(); -+ n = name2->getLength(); - - // remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.) -- if (!strcmp(name->getCString() + n - 2, "MT")) { -- name->del(n - 2, 2); -+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) { -+ name2->del(n - 2, 2); - n -= 2; - } - -+ // look for "Regular" -+ if (n > 7 && !strcmp(name2->getCString() + n - 7, "Regular")) { -+ name2->del(n - 7, 7); -+ n -= 7; -+ } -+ - // look for "Italic" -- if (!strcmp(name->getCString() + n - 6, "Italic")) { -- name->del(n - 6, 6); -+ if (n > 6 && !strcmp(name2->getCString() + n - 6, "Italic")) { -+ name2->del(n - 6, 6); - italic = gTrue; - n -= 6; - } else { -@@ -340,8 +263,8 @@ - } - - // look for "Bold" -- if (!strcmp(name->getCString() + n - 4, "Bold")) { -- name->del(n - 4, 4); -+ if (n > 4 && !strcmp(name2->getCString() + n - 4, "Bold")) { -+ name2->del(n - 4, 4); - bold = gTrue; - n -= 4; - } else { -@@ -349,84 +272,183 @@ - } - - // remove trailing "MT" (FooMT-Bold, etc.) -- if (!strcmp(name->getCString() + n - 2, "MT")) { -- name->del(n - 2, 2); -+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) { -+ name2->del(n - 2, 2); - n -= 2; - } - - // remove trailing "PS" -- if (!strcmp(name->getCString() + n - 2, "PS")) { -- name->del(n - 2, 2); -+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "PS")) { -+ name2->del(n - 2, 2); - n -= 2; - } - -+ // remove trailing "IdentityH" -+ if (n > 9 && !strcmp(name2->getCString() + n - 9, "IdentityH")) { -+ name2->del(n - 9, 9); -+ n -= 9; -+ } -+ - // search for the font - fi = NULL; - for (i = 0; i < fonts->getLength(); ++i) { -- fi = (WinFontInfo *)fonts->get(i); -- if (!fi->name->cmp(name) && fi->bold == bold && fi->italic == italic) { -+ fi = (SysFontInfo *)fonts->get(i); -+ if (fi->match(name2, bold, italic)) { - break; - } - fi = NULL; - } -+ if (!fi && bold) { -+ // try ignoring the bold flag -+ for (i = 0; i < fonts->getLength(); ++i) { -+ fi = (SysFontInfo *)fonts->get(i); -+ if (fi->match(name2, gFalse, italic)) { -+ break; -+ } -+ fi = NULL; -+ } -+ } -+ if (!fi && (bold || italic)) { -+ // try ignoring the bold and italic flags -+ for (i = 0; i < fonts->getLength(); ++i) { -+ fi = (SysFontInfo *)fonts->get(i); -+ if (fi->match(name2, gFalse, gFalse)) { -+ break; -+ } -+ fi = NULL; -+ } -+ } - -- delete name; -+ delete name2; - return fi; - } - --int CALLBACK WinFontList::enumFunc1(CONST LOGFONT *font, -- CONST TEXTMETRIC *metrics, -- DWORD type, LPARAM data) { -- WinFontList *fl = (WinFontList *)data; -- -- EnumFonts(fl->dc, font->lfFaceName, &WinFontList::enumFunc2, (LPARAM)fl); -- return 1; --} -- --int CALLBACK WinFontList::enumFunc2(CONST LOGFONT *font, -- CONST TEXTMETRIC *metrics, -- DWORD type, LPARAM data) { -- WinFontList *fl = (WinFontList *)data; -- WinFontInfo *fi; -- -- if (type & TRUETYPE_FONTTYPE) { -- if ((fi = WinFontInfo::make(new GString(font->lfFaceName), -- font->lfWeight >= 600, -- font->lfItalic ? gTrue : gFalse, -- fl->regKey, fl->winFontDir))) { -- fl->add(fi); -+#ifdef WIN32 -+void SysFontList::scanWindowsFonts(char *winFontDir) { -+ OSVERSIONINFO version; -+ char *path; -+ DWORD idx, valNameLen, dataLen, type; -+ HKEY regKey; -+ char valName[1024], data[1024]; -+ int n, fontNum; -+ char *p0, *p1; -+ GString *fontPath; -+ -+ version.dwOSVersionInfoSize = sizeof(version); -+ GetVersionEx(&version); -+ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { -+ path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\"; -+ } else { -+ path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\"; -+ } -+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, -+ KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, -+ ®Key) == ERROR_SUCCESS) { -+ idx = 0; -+ while (1) { -+ valNameLen = sizeof(valName) - 1; -+ dataLen = sizeof(data) - 1; -+ if (RegEnumValue(regKey, idx, valName, &valNameLen, NULL, -+ &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) { -+ break; -+ } -+ if (type == REG_SZ && -+ valNameLen > 0 && valNameLen < sizeof(valName) && -+ dataLen > 0 && dataLen < sizeof(data)) { -+ valName[valNameLen] = '\0'; -+ data[dataLen] = '\0'; -+ n = strlen(data); -+ if (!strcasecmp(data + n - 4, ".ttf") || -+ !strcasecmp(data + n - 4, ".ttc")) { -+ fontPath = new GString(data); -+ if (!(dataLen >= 3 && data[1] == ':' && data[2] == '\\')) { -+ fontPath->insert(0, '\\'); -+ fontPath->insert(0, winFontDir); -+ } -+ p0 = valName; -+ fontNum = 0; -+ while (*p0) { -+ p1 = strstr(p0, " & "); -+ if (p1) { -+ *p1 = '\0'; -+ p1 = p1 + 3; -+ } else { -+ p1 = p0 + strlen(p0); -+ } -+ fonts->append(makeWindowsFont(p0, fontNum, -+ fontPath->getCString())); -+ p0 = p1; -+ ++fontNum; -+ } -+ delete fontPath; -+ } -+ } -+ ++idx; - } -+ RegCloseKey(regKey); - } -- return 1; - } - --#endif // WIN32 -+SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum, -+ char *path) { -+ int n; -+ GBool bold, italic; -+ GString *s; -+ char c; -+ int i; -+ SysFontType type; - --//------------------------------------------------------------------------ --// PSFontParam --//------------------------------------------------------------------------ -+ n = strlen(name); -+ bold = italic = gFalse; - --PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA, -- GString *psFontNameA, GString *encodingA) { -- pdfFontName = pdfFontNameA; -- wMode = wModeA; -- psFontName = psFontNameA; -- encoding = encodingA; --} -+ // remove trailing ' (TrueType)' -+ if (n > 11 && !strncmp(name + n - 11, " (TrueType)", 11)) { -+ n -= 11; -+ } - --PSFontParam::~PSFontParam() { -- delete pdfFontName; -- delete psFontName; -- if (encoding) { -- delete encoding; -+ // remove trailing ' Italic' -+ if (n > 7 && !strncmp(name + n - 7, " Italic", 7)) { -+ n -= 7; -+ italic = gTrue; -+ } -+ -+ // remove trailing ' Bold' -+ if (n > 5 && !strncmp(name + n - 5, " Bold", 5)) { -+ n -= 5; -+ bold = gTrue; - } -+ -+ // remove trailing ' Regular' -+ if (n > 5 && !strncmp(name + n - 8, " Regular", 8)) { -+ n -= 8; -+ } -+ -+ //----- normalize the font name -+ s = new GString(name, n); -+ i = 0; -+ while (i < s->getLength()) { -+ c = s->getChar(i); -+ if (c == ' ' || c == ',' || c == '-') { -+ s->del(i); -+ } else { -+ ++i; -+ } -+ } -+ -+ if (!strcasecmp(path + strlen(path) - 4, ".ttc")) { -+ type = sysFontTTC; -+ } else { -+ type = sysFontTTF; -+ } -+ return new SysFontInfo(s, bold, italic, new GString(path), type, fontNum); - } -+#endif - - //------------------------------------------------------------------------ - // KeyBinding - //------------------------------------------------------------------------ - --KeyBinding::KeyBinding(int codeA, int modsA, int contextA, char *cmd0) { -+KeyBinding::KeyBinding(int codeA, int modsA, int contextA, const char *cmd0) { - code = codeA; - mods = modsA; - context = contextA; -@@ -637,9 +657,10 @@ - unicodeMaps = new GHash(gTrue); - cMapDirs = new GHash(gTrue); - toUnicodeDirs = new GList(); -- displayFonts = new GHash(); -- displayCIDFonts = new GHash(); -- displayNamedCIDFonts = new GHash(); -+ fontFiles = new GHash(gTrue); -+ fontDirs = new GList(); -+ ccFontFiles = new GHash(gTrue); -+ sysFonts = new SysFontList(); - #if HAVE_PAPER_H - char *paperName; - const struct paper *paperType; -@@ -668,16 +689,21 @@ - psDuplex = gFalse; - psLevel = psLevel2; - psFile = NULL; -- psFonts = new GHash(); -- psNamedFonts16 = new GList(); -- psFonts16 = new GList(); -+ psResidentFonts = new GHash(gTrue); -+ psResidentFonts16 = new GList(); -+ psResidentFontsCC = new GList(); - psEmbedType1 = gTrue; - psEmbedTrueType = gTrue; - psEmbedCIDPostScript = gTrue; - psEmbedCIDTrueType = gTrue; -+ psFontPassthrough = gFalse; - psPreload = gFalse; - psOPI = gFalse; - psASCIIHex = gFalse; -+ psUncompressPreloadedImages = gFalse; -+ psRasterResolution = 300; -+ psRasterMono = gFalse; -+ psAlwaysRasterize = gFalse; - textEncoding = new GString("Latin1"); - #if defined(WIN32) - textEOL = eolDOS; -@@ -688,13 +714,14 @@ - #endif - textPageBreaks = gTrue; - textKeepTinyChars = gFalse; -- fontDirs = new GList(); - initialZoom = new GString("125"); - continuousView = gFalse; - enableT1lib = gTrue; - enableFreeType = gTrue; -+ disableFreeTypeHinting = gFalse; - antialias = gTrue; - vectorAntialias = gTrue; -+ antialiasPrinting = gFalse; - strokeAdjust = gTrue; - screenType = screenUnset; - screenSize = -1; -@@ -702,6 +729,10 @@ - screenGamma = 1.0; - screenBlackThreshold = 0.0; - screenWhiteThreshold = 1.0; -+ minLineWidth = 0.0; -+ overprintPreview = gFalse; - urlCommand = NULL; - movieCommand = NULL; - mapNumericCharNames = gTrue; -@@ -716,10 +747,6 @@ - unicodeMapCache = new UnicodeMapCache(); - cMapCache = new CMapCache(); - --#ifdef WIN32 -- winFontList = NULL; --#endif -- - #ifdef ENABLE_PLUGINS - plugins = new GList(); - securityHandlers = new GList(); -@@ -764,7 +791,7 @@ - } - } - if (!f) { --#if defined(WIN32) && !defined(__CYGWIN32__) -+#ifdef WIN32 - char buf[512]; - i = GetModuleFileName(NULL, buf, sizeof(buf)); - if (i <= 0 || i >= sizeof(buf)) { -@@ -1762,23 +1833,21 @@ - deleteGHash(residentUnicodeMaps, UnicodeMap); - deleteGHash(unicodeMaps, GString); - deleteGList(toUnicodeDirs, GString); -- deleteGHash(displayFonts, DisplayFontParam); -- deleteGHash(displayCIDFonts, DisplayFontParam); -- deleteGHash(displayNamedCIDFonts, DisplayFontParam); --#ifdef WIN32 -- if (winFontList) { -- delete winFontList; -- } --#endif -+ deleteGHash(fontFiles, GString); -+ deleteGList(fontDirs, GString); -+ deleteGHash(ccFontFiles, GString); -+ delete sysFonts; - if (psFile) { - delete psFile; - } -- deleteGHash(psFonts, PSFontParam); -- deleteGList(psNamedFonts16, PSFontParam); -- deleteGList(psFonts16, PSFontParam); -+ deleteGHash(psResidentFonts, GString); -+ deleteGList(psResidentFonts16, PSFontParam16); -+ deleteGList(psResidentFontsCC, PSFontParam16); - delete textEncoding; -- deleteGList(fontDirs, GString); - delete initialZoom; -@@ -1829,8 +1898,6 @@ - char winFontDir[MAX_PATH]; - #endif - FILE *f; -- DisplayFontParamKind kind; -- DisplayFontParam *dfp; - int i, j; - - #ifdef WIN32 -@@ -1850,16 +1917,13 @@ - } - #endif - for (i = 0; displayFontTab[i].name; ++i) { -- fontName = new GString(displayFontTab[i].name); -- if (getDisplayFont(fontName)) { -- delete fontName; -+ if (fontFiles->lookup(displayFontTab[i].name)) { - continue; - } -+ fontName = new GString(displayFontTab[i].name); - fileName = NULL; -- kind = displayFontT1; // make gcc happy - if (dir) { - fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName); -- kind = displayFontT1; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { -@@ -1871,7 +1935,6 @@ - if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) { - fileName = appendToPath(new GString(winFontDir), - displayFontTab[i].ttFileName); -- kind = displayFontTT; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { -@@ -1886,7 +1949,6 @@ - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].ttFileName); -- kind = displayFontTT; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { -@@ -1895,11 +1957,10 @@ - } - } - } --#else -+#else // WIN32 - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].t1FileName); -- kind = displayFontT1; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { -@@ -1907,20 +1968,19 @@ - fileName = NULL; - } - } --#endif -+#endif // WIN32 - if (!fileName) { -- error(-1, "No display font for '%s'", displayFontTab[i].name); -+ error(errConfig, -1, "No display font for '{0:s}'", -+ displayFontTab[i].name); - delete fontName; - continue; - } -- dfp = new DisplayFontParam(fontName, kind); -- dfp->t1.fileName = fileName; -- globalParams->addDisplayFont(dfp); -+ addFontFile(fontName, fileName); - } - - #ifdef WIN32 - if (winFontDir[0]) { -- winFontList = new WinFontList(winFontDir); -+ sysFonts->scanWindowsFonts(winFontDir); - } - #endif - } -@@ -2020,31 +2080,72 @@ - return NULL; - } - --DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) { -- DisplayFontParam *dfp; -+GString *GlobalParams::findFontFile(GString *fontName) { -+ static const char *exts[] = { ".pfa", ".pfb", ".ttf", ".ttc" }; -+ GString *path, *dir; -+#ifdef WIN32 -+ GString *fontNameU; -+#endif -+ const char *ext; -+ FILE *f; -+ int i, j; - - lockGlobalParams; -- dfp = (DisplayFontParam *)displayFonts->lookup(fontName); --#ifdef WIN32 -- if (!dfp && winFontList) { -- dfp = winFontList->find(fontName); -+ if ((path = (GString *)fontFiles->lookup(fontName))) { -+ path = path->copy(); -+ unlockGlobalParams; -+ return path; - } -+ for (i = 0; i < fontDirs->getLength(); ++i) { -+ dir = (GString *)fontDirs->get(i); -+ for (j = 0; j < (int)(sizeof(exts) / sizeof(exts[0])); ++j) { -+ ext = exts[j]; -+#ifdef WIN32 -+ fontNameU = fileNameToUTF8(fontName->getCString()); -+ path = appendToPath(dir->copy(), fontNameU->getCString()); -+ delete fontNameU; -+#else -+ path = appendToPath(dir->copy(), fontName->getCString()); - #endif -+ path->append(ext); -+ if ((f = openFile(path->getCString(), "rb"))) { -+ fclose(f); -+ unlockGlobalParams; -+ return path; -+ } -+ delete path; -+ } -+ } -+ unlockGlobalParams; -+ return NULL; -+} -+ -+GString *GlobalParams::findSystemFontFile(GString *fontName, -+ SysFontType *type, -+ int *fontNum) { -+ SysFontInfo *fi; -+ GString *path; -+ -+ path = NULL; -+ lockGlobalParams; -+ if ((fi = sysFonts->find(fontName))) { -+ path = fi->path->copy(); -+ *type = fi->type; -+ *fontNum = fi->fontNum; -+ } - unlockGlobalParams; -- return dfp; -+ return path; - } - --DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName, -- GString *collection) { -- DisplayFontParam *dfp; -+GString *GlobalParams::findCCFontFile(GString *collection) { -+ GString *path; - - lockGlobalParams; -- if (!fontName || -- !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) { -- dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection); -+ if ((path = (GString *)ccFontFiles->lookup(collection))) { -+ path = path->copy(); - } - unlockGlobalParams; -- return dfp; -+ return path; - } - - GString *GlobalParams::getPSFile() { -@@ -2137,41 +2238,62 @@ - return level; - } - --PSFontParam *GlobalParams::getPSFont(GString *fontName) { -- PSFontParam *p; -+GString *GlobalParams::getPSResidentFont(GString *fontName) { -+ GString *psName; - - lockGlobalParams; -- p = (PSFontParam *)psFonts->lookup(fontName); -+ psName = (GString *)psResidentFonts->lookup(fontName); - unlockGlobalParams; -- return p; -+ return psName; - } - --PSFontParam *GlobalParams::getPSFont16(GString *fontName, -- GString *collection, int wMode) { -- PSFontParam *p; -+GList *GlobalParams::getPSResidentFonts() { -+ GList *names; -+ GHashIter *iter; -+ GString *name; -+ GString *psName; -+ -+ names = new GList(); -+ lockGlobalParams; -+ psResidentFonts->startIter(&iter); -+ while (psResidentFonts->getNext(&iter, &name, (void **)&psName)) { -+ names->append(psName->copy()); -+ } -+ unlockGlobalParams; -+ return names; -+} -+ -+PSFontParam16 *GlobalParams::getPSResidentFont16(GString *fontName, -+ int wMode) { -+ PSFontParam16 *p; - int i; - - lockGlobalParams; - p = NULL; -- if (fontName) { -- for (i = 0; i < psNamedFonts16->getLength(); ++i) { -- p = (PSFontParam *)psNamedFonts16->get(i); -- if (!p->pdfFontName->cmp(fontName) && -- p->wMode == wMode) { -- break; -- } -- p = NULL; -+ for (i = 0; i < psResidentFonts16->getLength(); ++i) { -+ p = (PSFontParam16 *)psResidentFonts16->get(i); -+ if (!(p->name->cmp(fontName)) && p->wMode == wMode) { -+ break; - } -+ p = NULL; - } -- if (!p && collection) { -- for (i = 0; i < psFonts16->getLength(); ++i) { -- p = (PSFontParam *)psFonts16->get(i); -- if (!p->pdfFontName->cmp(collection) && -- p->wMode == wMode) { -- break; -- } -- p = NULL; -+ unlockGlobalParams; -+ return p; -+} -+ -+PSFontParam16 *GlobalParams::getPSResidentFontCC(GString *collection, -+ int wMode) { -+ PSFontParam16 *p; -+ int i; -+ -+ lockGlobalParams; -+ p = NULL; -+ for (i = 0; i < psResidentFontsCC->getLength(); ++i) { -+ p = (PSFontParam16 *)psResidentFontsCC->get(i); -+ if (!(p->name->cmp(collection)) && p->wMode == wMode) { -+ break; - } -+ p = NULL; - } - unlockGlobalParams; - return p; -@@ -2213,6 +2335,15 @@ - return e; - } - -+GBool GlobalParams::getPSFontPassthrough() { -+ GBool e; -+ -+ lockGlobalParams; -+ e = psFontPassthrough; -+ unlockGlobalParams; -+ return e; -+} -+ - GBool GlobalParams::getPSPreload() { - GBool preload; - @@ -2240,6 +2371,42 @@ return ah; } @@ -3309,37 +58,6 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc GString *GlobalParams::getTextEncodingName() { GString *s; -@@ -2276,30 +2443,6 @@ - return tiny; - } - --GString *GlobalParams::findFontFile(GString *fontName, char **exts) { -- GString *dir, *fileName; -- char **ext; -- FILE *f; -- int i; -- -- lockGlobalParams; -- for (i = 0; i < fontDirs->getLength(); ++i) { -- dir = (GString *)fontDirs->get(i); -- for (ext = exts; *ext; ++ext) { -- fileName = appendToPath(dir->copy(), fontName->getCString()); -- fileName->append(*ext); -- if ((f = fopen(fileName->getCString(), "rb"))) { -- fclose(f); -- unlockGlobalParams; -- return fileName; -- } -- delete fileName; -- } -- } -- unlockGlobalParams; -- return NULL; --} -- - GString *GlobalParams::getInitialZoom() { - GString *s; - @@ -2355,6 +2507,15 @@ return f; } @@ -3356,129 +74,9 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc GBool GlobalParams::getStrokeAdjust() { GBool f; -@@ -2552,14 +2731,9 @@ - // functions to set parameters - //------------------------------------------------------------------------ - --void GlobalParams::addDisplayFont(DisplayFontParam *param) { -- DisplayFontParam *old; -- -+void GlobalParams::addFontFile(GString *fontName, GString *path) { - lockGlobalParams; -- if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) { -- delete old; -- } -- displayFonts->add(param->name, param); -+ fontFiles->add(fontName, path); - unlockGlobalParams; - } - -@@ -2684,6 +2858,12 @@ - unlockGlobalParams; - } - -+void GlobalParams::setPSFontPassthrough(GBool passthrough) { -+ lockGlobalParams; -+ psFontPassthrough = passthrough; -+ unlockGlobalParams; -+} -+ - void GlobalParams::setPSPreload(GBool preload) { - lockGlobalParams; - psPreload = preload; diff -ru xpdf-3.02/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h --- xpdf-3.02/xpdf/GlobalParams.h 2007-02-27 23:05:52.000000000 +0100 +++ xpdf-3.03/xpdf/GlobalParams.h 2011-08-15 23:08:53.000000000 +0200 -@@ -35,9 +35,7 @@ - class CMapCache; - struct XpdfSecurityHandler; - class GlobalParams; --#ifdef WIN32 --class WinFontList; --#endif -+class SysFontList; - - //------------------------------------------------------------------------ - -@@ -46,51 +44,27 @@ - - //------------------------------------------------------------------------ - --enum DisplayFontParamKind { -- displayFontT1, -- displayFontTT --}; -- --struct DisplayFontParamT1 { -- GString *fileName; --}; -- --struct DisplayFontParamTT { -- GString *fileName; --}; -- --class DisplayFontParam { --public: -- -- GString *name; // font name for 8-bit fonts and named -- // CID fonts; collection name for -- // generic CID fonts -- DisplayFontParamKind kind; -- union { -- DisplayFontParamT1 t1; -- DisplayFontParamTT tt; -- }; -- -- DisplayFontParam(GString *nameA, DisplayFontParamKind kindA); -- virtual ~DisplayFontParam(); -+enum SysFontType { -+ sysFontPFA, -+ sysFontPFB, -+ sysFontTTF, -+ sysFontTTC - }; - - //------------------------------------------------------------------------ - --class PSFontParam { -+class PSFontParam16 { - public: - -- GString *pdfFontName; // PDF font name for 8-bit fonts and -- // named 16-bit fonts; char collection -- // name for generic 16-bit fonts -- int wMode; // writing mode (0=horiz, 1=vert) for -- // 16-bit fonts -+ GString *name; // PDF font name for psResidentFont16; -+ // char collection name for psResidentFontCC -+ int wMode; // writing mode (0=horiz, 1=vert) - GString *psFontName; // PostScript font name -- GString *encoding; // encoding, for 16-bit fonts only -+ GString *encoding; // encoding - -- PSFontParam(GString *pdfFontNameA, int wModeA, -- GString *psFontNameA, GString *encodingA); -- ~PSFontParam(); -+ PSFontParam16(GString *nameA, int wModeA, -+ GString *psFontNameA, GString *encodingA); -+ ~PSFontParam16(); - }; - - //------------------------------------------------------------------------ -@@ -212,9 +191,11 @@ - UnicodeMap *getResidentUnicodeMap(GString *encodingName); - FILE *getUnicodeMapFile(GString *encodingName); - FILE *findCMapFile(GString *collection, GString *cMapName); - FILE *findToUnicodeFile(GString *name); -- DisplayFontParam *getDisplayFont(GString *fontName); -- DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); -+ GString *findFontFile(GString *fontName); -+ GString *findSystemFontFile(GString *fontName, SysFontType *type, -+ int *fontNum); -+ GString *findCCFontFile(GString *collection); - GString *getPSFile(); - int getPSPaperWidth(); - int getPSPaperHeight(); @@ -225,26 +206,34 @@ GBool getPSShrinkLarger(); GBool getPSCenter(); @@ -3526,45 +124,6 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h GString *getURLCommand() { return urlCommand; } GString *getMovieCommand() { return movieCommand; } GBool getMapNumericCharNames(); -@@ -268,7 +261,7 @@ - - //----- functions to set parameters - -- void addDisplayFont(DisplayFontParam *param); -+ void addFontFile(GString *fontName, GString *path); - void setPSFile(char *file); - GBool setPSPaperSize(char *size); - void setPSPaperWidth(int width); -@@ -284,6 +277,7 @@ - void setPSEmbedTrueType(GBool embed); - void setPSEmbedCIDPostScript(GBool embed); - void setPSEmbedCIDTrueType(GBool embed); -+ void setPSFontPassthrough(GBool passthrough); - void setPSPreload(GBool preload); - void setPSOPI(GBool opi); - void setPSASCIIHex(GBool hex); -@@ -380,15 +374,12 @@ - GHash *cMapDirs; // list of CMap dirs, indexed by collection - // name [GList[GString]] - GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString] -- GHash *displayFonts; // display font info, indexed by font name -- // [DisplayFontParam] --#ifdef WIN32 -- WinFontList *winFontList; // system TrueType fonts --#endif -- GHash *displayCIDFonts; // display CID font info, indexed by -- // collection [DisplayFontParam] -- GHash *displayNamedCIDFonts; // display CID font info, indexed by -- // font name [DisplayFontParam] -+ GHash *fontFiles; // font files: font name mapped to path -+ // [GString] -+ GList *fontDirs; // list of font dirs [GString] -+ GHash *ccFontFiles; // character collection font files: -+ // collection name mapped to path [GString] -+ SysFontList *sysFonts; // system fonts - GString *psFile; // PostScript file or command (for xpdf) - int psPaperWidth; // paper size, in PostScript points, for - int psPaperHeight; // PostScript output @@ -402,31 +393,44 @@ GBool psCenter; // center pages on the paper GBool psDuplex; // enable duplexing in PostScript? @@ -3616,31 +175,6 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h int screenSize; // screen matrix size 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 ---- xpdf-3.02/xpdf/OutputDev.cc 2007-02-27 23:05:52.000000000 +0100 -+++ xpdf-3.03/xpdf/OutputDev.cc 2011-08-15 23:08:53.000000000 +0200 -@@ -65,6 +65,7 @@ - updateStrokeOpacity(state); - updateFillOverprint(state); - updateStrokeOverprint(state); -+ updateOverprintMode(state); - updateTransfer(state); - updateFont(state); - } -@@ -89,6 +90,13 @@ - } - } - -+void OutputDev::setSoftMaskFromImageMask(GfxState *state, -+ Object *ref, Stream *str, -+ int width, int height, GBool invert, -+ GBool inlineImg) { -+ drawImageMask(state, ref, str, width, height, invert, inlineImg); -+} -+ - 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/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 @@ -4350,75 +884,6 @@ diff -ru xpdf-3.02/xpdf/PSOutputDev.cc xpdf-3.03/xpdf/PSOutputDev.cc "/pr { 2 index 2 index 3 2 roll putinterval 4 add } def", "/pdfImClip {", " gsave", -@@ -607,7 +644,7 @@ - " func n array astore", - "} def", - "/axialSH {", -- " dup 0 eq {", -+ " dup 2 lt {", - " true", - " } {", - " dup 8 eq {", -@@ -753,25 +790,12 @@ - double mWidth; // width of 'm' character - }; - --static char *psFonts[] = { -- "Courier", -- "Courier-Bold", -- "Courier-Oblique", -- "Courier-BoldOblique", -- "Helvetica", -- "Helvetica-Bold", -- "Helvetica-Oblique", -- "Helvetica-BoldOblique", -- "Symbol", -- "Times-Roman", -- "Times-Bold", -- "Times-Italic", -- "Times-BoldItalic", -- "ZapfDingbats", -- NULL --}; -- --static PSSubstFont psSubstFonts[] = { -+// NB: must be in same order as base14SubstFonts in GfxFont.cc -+static PSSubstFont psBase14SubstFonts[14] = { -+ {"Courier", 0.600}, -+ {"Courier-Oblique", 0.600}, -+ {"Courier-Bold", 0.600}, -+ {"Courier-BoldOblique", 0.600}, - {"Helvetica", 0.833}, - {"Helvetica-Oblique", 0.833}, - {"Helvetica-Bold", 0.889}, -@@ -780,22 +804,28 @@ - {"Times-Italic", 0.722}, - {"Times-Bold", 0.833}, - {"Times-BoldItalic", 0.778}, -- {"Courier", 0.600}, -- {"Courier-Oblique", 0.600}, -- {"Courier-Bold", 0.600}, -- {"Courier-BoldOblique", 0.600} -+ // the last two are never used for substitution -+ {"Symbol", 0}, -+ {"ZapfDingbats", 0} -+}; -+ -+// Mapping from Type 1/1C font file to PS font name. -+struct PST1FontName { -+ Ref fontFileID; -+ GString *psName; // PostScript font name used for this -+ // embedded font file - }; - - // Encoding info for substitute 16-bit font - struct PSFont16Enc { - Ref fontID; -- GString *enc; -+ GString *enc; // NULL means font wasn't correctly substituted - }; - - //------------------------------------------------------------------------ @@ -845,6 +875,13 @@ }; @@ -4790,340 +1255,6 @@ diff -ru xpdf-3.02/xpdf/PSOutputDev.cc xpdf-3.03/xpdf/PSOutputDev.cc } void PSOutputDev::writePageTrailer() { -@@ -1558,18 +1681,15 @@ - } - - void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { -- Ref fontFileID; -- GString *name; -- PSFontParam *fontParam; -+ GfxFontLoc *fontLoc; - GString *psName; -- char buf[16]; - GBool subst; -+ char buf[16]; - UnicodeMap *uMap; - char *charName; - double xs, ys; - int code; - double w1, w2; -- double *fm; - int i, j; - - // check if font is already set up -@@ -1587,119 +1707,120 @@ - } - fontIDs[fontIDLen++] = *font->getID(); - -+ psName = NULL; - xs = ys = 1; - subst = gFalse; - -- // check for resident 8-bit font -- if (font->getName() && -- (fontParam = globalParams->getPSFont(font->getName()))) { -- psName = new GString(fontParam->psFontName->getCString()); -- -- // check for embedded Type 1 font -- } else if (globalParams->getPSEmbedType1() && -- font->getType() == fontType1 && -- font->getEmbeddedFontID(&fontFileID)) { -- psName = filterPSName(font->getEmbeddedFontName()); -- setupEmbeddedType1Font(&fontFileID, psName); -- -- // check for embedded Type 1C font -- } else if (globalParams->getPSEmbedType1() && -- font->getType() == fontType1C && -- font->getEmbeddedFontID(&fontFileID)) { -- // use the PDF font name because the embedded font name might -- // not include the subset prefix -- psName = filterPSName(font->getOrigName()); -- setupEmbeddedType1CFont(font, &fontFileID, psName); -- -- // check for embedded OpenType - Type 1C font -- } else if (globalParams->getPSEmbedType1() && -- font->getType() == fontType1COT && -- font->getEmbeddedFontID(&fontFileID)) { -- // use the PDF font name because the embedded font name might -- // not include the subset prefix -- psName = filterPSName(font->getOrigName()); -- setupEmbeddedOpenTypeT1CFont(font, &fontFileID, psName); -- -- // check for external Type 1 font file -- } else if (globalParams->getPSEmbedType1() && -- font->getType() == fontType1 && -- font->getExtFontFile()) { -- // this assumes that the PS font name matches the PDF font name -- psName = font->getName()->copy(); -- setupExternalType1Font(font->getExtFontFile(), psName); -- -- // check for embedded TrueType font -- } else if (globalParams->getPSEmbedTrueType() && -- (font->getType() == fontTrueType || -- font->getType() == fontTrueTypeOT) && -- font->getEmbeddedFontID(&fontFileID)) { -- psName = filterPSName(font->getEmbeddedFontName()); -- setupEmbeddedTrueTypeFont(font, &fontFileID, psName); -- -- // check for external TrueType font file -- } else if (globalParams->getPSEmbedTrueType() && -- font->getType() == fontTrueType && -- font->getExtFontFile()) { -- psName = filterPSName(font->getName()); -- setupExternalTrueTypeFont(font, psName); -- -- // check for embedded CID PostScript font -- } else if (globalParams->getPSEmbedCIDPostScript() && -- font->getType() == fontCIDType0C && -- font->getEmbeddedFontID(&fontFileID)) { -- psName = filterPSName(font->getEmbeddedFontName()); -- setupEmbeddedCIDType0Font(font, &fontFileID, psName); -- -- // check for embedded CID TrueType font -- } else if (globalParams->getPSEmbedCIDTrueType() && -- (font->getType() == fontCIDType2 || -- font->getType() == fontCIDType2OT) && -- font->getEmbeddedFontID(&fontFileID)) { -- psName = filterPSName(font->getEmbeddedFontName()); -- //~ should check to see if font actually uses vertical mode -- setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue); -- -- // check for embedded OpenType - CID CFF font -- } else if (globalParams->getPSEmbedCIDPostScript() && -- font->getType() == fontCIDType0COT && -- font->getEmbeddedFontID(&fontFileID)) { -- psName = filterPSName(font->getEmbeddedFontName()); -- setupEmbeddedOpenTypeCFFFont(font, &fontFileID, psName); -- -- // check for Type 3 font -- } else if (font->getType() == fontType3) { -+ if (font->getType() == fontType3) { - psName = GString::format("T3_{0:d}_{1:d}", - font->getID()->num, font->getID()->gen); - setupType3Font(font, psName, parentResDict); -- -- // do 8-bit font substitution -- } else if (!font->isCIDFont()) { -- subst = gTrue; -- name = font->getName(); -- psName = NULL; -- if (name) { -- for (i = 0; psFonts[i]; ++i) { -- if (name->cmp(psFonts[i]) == 0) { -- psName = new GString(psFonts[i]); -- break; -+ } else { -+ fontLoc = font->locateFont(xref, gTrue); -+ switch (fontLoc->locType) { -+ case gfxFontLocEmbedded: -+ switch (fontLoc->fontType) { -+ case fontType1: -+ // this assumes that the PS font name matches the PDF font name -+ psName = font->getEmbeddedFontName()->copy(); -+ setupEmbeddedType1Font(&fontLoc->embFontID, psName); -+ break; -+ case fontType1C: -+ psName = makePSFontName(font, &fontLoc->embFontID); -+ setupEmbeddedType1CFont(font, &fontLoc->embFontID, psName); -+ break; -+ case fontType1COT: -+ psName = makePSFontName(font, &fontLoc->embFontID); -+ setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID, psName); -+ break; -+ case fontTrueType: -+ case fontTrueTypeOT: -+ psName = makePSFontName(font, font->getID()); -+ setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID, psName); -+ break; -+ case fontCIDType0C: -+ psName = makePSFontName(font, &fontLoc->embFontID); -+ setupEmbeddedCIDType0Font(font, &fontLoc->embFontID, psName); -+ break; -+ case fontCIDType2: -+ case fontCIDType2OT: -+ psName = makePSFontName(font, font->getID()); -+ //~ should check to see if font actually uses vertical mode -+ setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, psName, gTrue); -+ break; -+ case fontCIDType0COT: -+ psName = makePSFontName(font, &fontLoc->embFontID); -+ setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID, psName); -+ break; -+ default: -+ break; -+ } -+ break; -+ case gfxFontLocExternal: -+ //~ add cases for external 16-bit fonts -+ switch (fontLoc->fontType) { -+ case fontType1: -+ if (font->getName()) { -+ // this assumes that the PS font name matches the PDF font name -+ psName = font->getName()->copy(); -+ } else { -+ //~ this won't work -- the PS font name won't match -+ psName = makePSFontName(font, font->getID()); - } -+ setupExternalType1Font(fontLoc->path, psName); -+ break; -+ case fontTrueType: -+ case fontTrueTypeOT: -+ psName = makePSFontName(font, font->getID()); -+ setupExternalTrueTypeFont(font, fontLoc->path, psName); -+ break; -+ case fontCIDType2: -+ case fontCIDType2OT: -+ psName = makePSFontName(font, font->getID()); -+ //~ should check to see if font actually uses vertical mode -+ setupExternalCIDTrueTypeFont(font, fontLoc->path, psName, gTrue); -+ break; -+ default: -+ break; - } -+ break; -+ case gfxFontLocResident: -+ psName = fontLoc->path->copy(); -+ break; - } -+ - if (!psName) { -- if (font->isFixedWidth()) { -- i = 8; -- } else if (font->isSerif()) { -- i = 4; -+ if (font->isCIDFont()) { -+ error(errSyntaxError, -1, -+ "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)", -+ font->getName() ? font->getName()->getCString() -+ : "(unnamed)", -+ ((GfxCIDFont *)font)->getCollection() -+ ? ((GfxCIDFont *)font)->getCollection()->getCString() -+ : "(unknown)"); -+ if (font16EncLen >= font16EncSize) { -+ font16EncSize += 16; -+ font16Enc = (PSFont16Enc *)greallocn(font16Enc, -+ font16EncSize, -+ sizeof(PSFont16Enc)); -+ } -+ font16Enc[font16EncLen].fontID = *font->getID(); -+ font16Enc[font16EncLen].enc = NULL; -+ ++font16EncLen; - } else { -- i = 0; -- } -- if (font->isBold()) { -- i += 2; -- } -- if (font->isItalic()) { -- i += 1; -+ error(errSyntaxError, -1, -+ "Couldn't find a font to substitute for '{0:s}'", -+ font->getName() ? font->getName()->getCString() -+ : "(unnamed)"); - } -- psName = new GString(psSubstFonts[i].psName); -+ delete fontLoc; -+ return; -+ } -+ -+ // scale substituted 8-bit fonts -+ if (fontLoc->locType == gfxFontLocResident && -+ fontLoc->substIdx >= 0) { -+ subst = gTrue; - for (code = 0; code < 256; ++code) { - if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) && - charName[0] == 'm' && charName[1] == '\0') { -@@ -1711,56 +1832,37 @@ - } else { - w1 = 0; - } -- w2 = psSubstFonts[i].mWidth; -+ w2 = psBase14SubstFonts[fontLoc->substIdx].mWidth; - xs = w1 / w2; - if (xs < 0.1) { - xs = 1; - } -- if (font->getType() == fontType3) { -- // This is a hack which makes it possible to substitute for some -- // Type 3 fonts. The problem is that it's impossible to know what -- // the base coordinate system used in the font is without actually -- // rendering the font. -- ys = xs; -- fm = font->getFontMatrix(); -- if (fm[0] != 0) { -- ys *= fm[3] / fm[0]; -- } -- } else { -- ys = 1; -- } - } - -- // do 16-bit font substitution -- } else if ((fontParam = globalParams-> -- getPSFont16(font->getName(), -- ((GfxCIDFont *)font)->getCollection(), -- font->getWMode()))) { -- subst = gTrue; -- psName = fontParam->psFontName->copy(); -- if (font16EncLen >= font16EncSize) { -- font16EncSize += 16; -- font16Enc = (PSFont16Enc *)greallocn(font16Enc, -- font16EncSize, sizeof(PSFont16Enc)); -- } -- font16Enc[font16EncLen].fontID = *font->getID(); -- font16Enc[font16EncLen].enc = fontParam->encoding->copy(); -- if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) { -- uMap->decRefCnt(); -+ // handle encodings for substituted CID fonts -+ if (fontLoc->locType == gfxFontLocResident && -+ fontLoc->fontType >= fontCIDType0) { -+ subst = gTrue; -+ if (font16EncLen >= font16EncSize) { -+ font16EncSize += 16; -+ font16Enc = (PSFont16Enc *)greallocn(font16Enc, -+ font16EncSize, -+ sizeof(PSFont16Enc)); -+ } -+ font16Enc[font16EncLen].fontID = *font->getID(); -+ if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding))) { -+ font16Enc[font16EncLen].enc = fontLoc->encoding->copy(); -+ uMap->decRefCnt(); -+ } else { -+ error(errSyntaxError, -1, -+ "Couldn't find Unicode map for 16-bit font encoding '{0:t}'", -+ fontLoc->encoding); -+ font16Enc[font16EncLen].enc = NULL; -+ } - ++font16EncLen; -- } else { -- error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'", -- font16Enc[font16EncLen].enc->getCString()); - } - -- // give up - can't do anything with this font -- } else { -- error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)", -- font->getName() ? font->getName()->getCString() : "(unnamed)", -- ((GfxCIDFont *)font)->getCollection() -- ? ((GfxCIDFont *)font)->getCollection()->getCString() -- : "(unknown)"); -- return; -+ delete fontLoc; - } - - // generate PostScript code to set up the font -@@ -1787,11 +1889,6 @@ - charName = buf; - } else { - charName = ((Gfx8BitFont *)font)->getCharName(i+j); -- // this is a kludge for broken PDF files that encode char 32 -- // as .notdef -- if (i+j == 32 && charName && !strcmp(charName, ".notdef")) { -- charName = "space"; -- } - } - writePS("/"); - writePSName(charName ? charName : (char *)".notdef"); @@ -1821,36 +1918,30 @@ int i; |