[poppler] fofi/FoFiTrueType.cc fofi/FoFiTrueType.h poppler/PSOutputDev.cc poppler/PSOutputDev.h

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Dec 8 20:46:14 UTC 2016


 fofi/FoFiTrueType.cc   |   13 ++++++++++++-
 fofi/FoFiTrueType.h    |    2 ++
 poppler/PSOutputDev.cc |   26 ++++++++++++++++++++++++++
 poppler/PSOutputDev.h  |    1 +
 4 files changed, 41 insertions(+), 1 deletion(-)

New commits:
commit 2cf901c817fc99e1fa57745c11aa79cdfb4e8c99
Author: William Bader <william at newspapersystems.com>
Date:   Thu Dec 8 21:45:18 2016 +0100

    Fix PS conversion for some files
    
    Bug #63963

diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc
index 4905826..f1a15e0 100644
--- a/fofi/FoFiTrueType.cc
+++ b/fofi/FoFiTrueType.cc
@@ -22,7 +22,7 @@
 // Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2014 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2015 Aleksei Volkov <Aleksei Volkov>
-// Copyright (C) 2015 William Bader <williambader at hotmail.com>
+// Copyright (C) 2015, 2016 William Bader <williambader at hotmail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -727,12 +727,15 @@ void FoFiTrueType::convertToCIDType0(char *psName, int *cidMap, int nCIDs,
 
 void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
 				  GBool needVerticalMetrics,
+				  int *maxValidGlyph,
 				  FoFiOutputFunc outputFunc,
 				  void *outputStream) {
   GooString *buf;
   GooString *sfntsName;
   int maxUsedGlyph, n, i, j;
 
+  *maxValidGlyph = -1;
+
   if (openTypeCFF) {
     return;
   }
@@ -754,6 +757,13 @@ void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
   // that refers to one of the unused glyphs -- this results in PS
   // errors if we simply use maxUsedGlyph+1 for the Type 0 font.  So
   // we compromise by always defining at least 256 glyphs.)
+  // Some fonts have a large nGlyphs but maxUsedGlyph of 0.
+  // These fonts might reference any glyph.
+  // Return the last written glyph number in maxValidGlyph.
+  // PSOutputDev::drawString() can use maxValidGlyph to avoid
+  // referencing zero-length glyphs that we trimmed.
+  // This allows pdftops to avoid writing huge files while still
+  // handling the rare PDF that uses a zero-length glyph.
   if (cidMap) {
     n = nCIDs;
   } else if (nGlyphs > maxUsedGlyph + 256) {
@@ -765,6 +775,7 @@ void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
   } else {
     n = nGlyphs;
   }
+  *maxValidGlyph = n-1;
   for (i = 0; i < n; i += 256) {
     (*outputFunc)(outputStream, "10 dict begin\n", 14);
     (*outputFunc)(outputStream, "/FontName /", 11);
diff --git a/fofi/FoFiTrueType.h b/fofi/FoFiTrueType.h
index b40a44a..a4e28f2 100644
--- a/fofi/FoFiTrueType.h
+++ b/fofi/FoFiTrueType.h
@@ -17,6 +17,7 @@
 // Copyright (C) 2007 Koji Otani <sho at bbr.jp>
 // Copyright (C) 2011, 2012 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2012 Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
+// Copyright (C) 2016 William Bader <williambader at hotmail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -144,6 +145,7 @@ public:
   // <nCIDs> entries.  (Not useful for OpenType CFF fonts.)
   void convertToType0(char *psName, int *cidMap, int nCIDs,
 		      GBool needVerticalMetrics,
+		      int *maxValidGlyph,
 		      FoFiOutputFunc outputFunc, void *outputStream);
 
   // Convert to a Type 0 (but non-CID) composite font, suitable for
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index ea0b043..246244f 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1103,6 +1103,7 @@ PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *doc,
 
   fontIDs = NULL;
   fontNames = new GooHash(gTrue);
+  fontMaxValidGlyph = new GooHash(gTrue);
   t1FontNames = NULL;
   font8Info = NULL;
   font16Enc = NULL;
@@ -1171,6 +1172,7 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
 
   fontIDs = NULL;
   fontNames = new GooHash(gTrue);
+  fontMaxValidGlyph = new GooHash(gTrue);
   t1FontNames = NULL;
   font8Info = NULL;
   font16Enc = NULL;
@@ -1497,6 +1499,7 @@ PSOutputDev::~PSOutputDev() {
     gfree(fontIDs);
   }
   delete fontNames;
+  delete fontMaxValidGlyph;
   if (t1FontNames) {
     for (i = 0; i < t1FontNameLen; ++i) {
       delete t1FontNames[i].psName;
@@ -2610,10 +2613,15 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
 		outputFunc, outputStream);
       } else {
 	// otherwise: use a non-CID composite font
+	int maxValidGlyph = -1;
 	ffTT->convertToType0(psName->getCString(),
 		codeToGID, codeToGIDLen,
 		needVerticalMetrics,
+		&maxValidGlyph,
 		outputFunc, outputStream);
+	if (maxValidGlyph >= 0 && font->getName()) {
+	  fontMaxValidGlyph->replace(font->getName()->copy(), maxValidGlyph);
+	}
       }
       gfree(codeToGID);
     } else {
@@ -2706,11 +2714,16 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
 				outputFunc, outputStream);
       } else {
 	// otherwise: use a non-CID composite font
+	int maxValidGlyph = -1;
 	ffTT->convertToType0(psName->getCString(),
 			     ((GfxCIDFont *)font)->getCIDToGID(),
 			     ((GfxCIDFont *)font)->getCIDToGIDLen(),
 			     needVerticalMetrics,
+			     &maxValidGlyph,
 			     outputFunc, outputStream);
+	if (maxValidGlyph > 0 && font->getName()) {
+	  fontMaxValidGlyph->replace(font->getName()->copy(), maxValidGlyph);
+	}
       }
       delete ffTT;
     }
@@ -5051,6 +5064,8 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
   char buf[8];
   double *dxdy;
   int dxdySize, len, nChars, uLen, n, m, i, j;
+  int maxGlyphInt;
+  CharCode maxGlyph;
 
   // for pdftohtml, output PS without text
   if( displayText == gFalse )
@@ -5070,6 +5085,9 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
   if (!(font = state->getFont())) {
     return;
   }
+  maxGlyphInt = (font->getName()? fontMaxValidGlyph->lookupInt(font->getName()): 0);
+  if (maxGlyphInt < 0) maxGlyphInt = 0;
+  maxGlyph = (CharCode) maxGlyphInt;
   wMode = font->getWMode();
 
   // check for a subtitute 16-bit font
@@ -5144,6 +5162,14 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
 	  dxdy[2 * nChars + 1] = dy;
 	  ++nChars;
 	}
+      } else if (maxGlyph > 0 && code > maxGlyph) {
+	// Ignore this code.
+	// Using it will exceed the number of glyphs in the font and generate
+	// /rangecheck in --xyshow--
+	if (nChars > 0) {
+	  dxdy[2 * (nChars-1) ] += dx;
+	  dxdy[2 * (nChars-1) + 1 ] += dy;
+	}
       } else {
 	if (nChars + 1 > dxdySize) {
 	  dxdySize *= 2;
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index c27c90f..072608a 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -473,6 +473,7 @@ private:
   int fontIDSize;		// size of fontIDs array
   std::set<int> resourceIDs;	// list of object IDs of objects containing Resources we've already set up
   GooHash *fontNames;		// all used font names
+  GooHash *fontMaxValidGlyph;	// max valid glyph of each font
   PST1FontName *t1FontNames;	// font names for Type 1/1C fonts
   int t1FontNameLen;		// number of entries in t1FontNames array
   int t1FontNameSize;		// size of t1FontNames array


More information about the poppler mailing list