[poppler] 3 commits - poppler/Gfx.cc poppler/GlobalParams.cc poppler/GlobalParams.h poppler/GlobalParamsWin.cc poppler/PSOutputDev.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Mar 4 11:34:15 PST 2012


 poppler/Gfx.cc             |    4 
 poppler/GlobalParams.cc    |    5 +
 poppler/GlobalParams.h     |    2 
 poppler/GlobalParamsWin.cc |  106 +++++++++++++++++++++--
 poppler/PSOutputDev.cc     |  203 ++++++++++++++++++++-------------------------
 5 files changed, 199 insertions(+), 121 deletions(-)

New commits:
commit 35c960d198d2efa97d15e962662114c5c31b8d20
Author: Even Rouault <even.rouault at mines-paris.org>
Date:   Sun Mar 4 20:32:42 2012 +0100

    Do not crash on malformed files with 0 bits in the color map of an image

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 31994ac..2cc8e28 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -34,6 +34,7 @@
 // Copyright (C) 2010 Nils Höglund <nils.hoglund at gmail.com>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Axel Strübing <axel.struebing at freenet.de>
+// Copyright (C) 2012 Even Rouault <even.rouault at mines-paris.org>
 //
 // 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
@@ -4381,6 +4382,9 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
       obj1.free();
       dict->lookup("D", &obj1);
     }
+    if (bits == 0) {
+      goto err2;
+    }
     colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
     obj1.free();
     if (!colorMap->isOk()) {
commit dae29c6c201cd69cbf4f008de865cc19a36f29b3
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Sun Mar 4 15:22:02 2012 +0100

    CJK substitute implementation on WIndows platforms.
    
    When You install ghostscript on WIndows You're able to switch on CJK
    support. This will create a  cidfmap file in the gs-lib directory. The
    ps file which creates it (mkcidfm.ps) runs over the windows font
    directory and tries to create a suitable substitution table for missing
    CJK fonts. The cidfmap file is more or less PDF like, so it's quite easy
    to parse it with our parser and create a substitution table in
    GlobalParamsWin and use that table. But I expect it in the poppler data
    dir instead of searching for ghostscript installation. If it is not
    there, it always returns the default CID font of point 2.
    You can either copy it from the gs lib directory or create it with the
    ghostscript tool calling
    
    gswin32c -q -dBATCH -sFONTDIR=<windows font directory>
    -sCIDFMAP=<popper data dir>/cidfmap mkcidfm.ps

diff --git a/poppler/GlobalParams.cc b/poppler/GlobalParams.cc
index 77a053d..73a9855 100644
--- a/poppler/GlobalParams.cc
+++ b/poppler/GlobalParams.cc
@@ -32,6 +32,7 @@
 // Copyright (C) 2011 Koji Otani <sho at bbr.jp>
 // Copyright (C) 2012 Yi Yang <ahyangyi at gmail.com>
 // Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 //
 // 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
@@ -552,6 +553,7 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
 #ifdef _WIN32
   // baseDir will be set by a call to setBaseDir
   baseDir = new GooString();
+  substFiles = new GooHash(gTrue);
 #else
   baseDir = appendToPath(getHomeDir(), ".xpdf");
 #endif
@@ -788,6 +790,9 @@ GlobalParams::~GlobalParams() {
   deleteGooHash(fontFiles, GooString);
   deleteGooList(fontDirs, GooString);
   deleteGooHash(ccFontFiles, GooString);
+#ifdef _WIN32
+  deleteGooHash(substFiles, GooString);
+#endif
   delete sysFonts;
   if (psFile) {
     delete psFile;
diff --git a/poppler/GlobalParams.h b/poppler/GlobalParams.h
index d72793d..be1d4b6 100644
--- a/poppler/GlobalParams.h
+++ b/poppler/GlobalParams.h
@@ -24,6 +24,7 @@
 // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2011 Pino Toscano <pino at kde.org>
 // Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 //
 // 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
@@ -289,6 +290,7 @@ private:
   GooList *toUnicodeDirs;		// list of ToUnicode CMap dirs [GooString]
 #ifdef _WIN32
   GBool baseFontsInitialized;
+  GooHash *substFiles;	// windows font substitutes (for CID fonts)
 #endif
   GooHash *fontFiles;		// font files: font name mapped to path
 				//   [GString]
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index c62e2cd..dd8768a 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -2,6 +2,7 @@
    but mostly based on xpdf code.
    
    // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
+   // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 
 TODO: instead of a fixed mapping defined in displayFontTab, it could
 scan the whole fonts directory, parse TTF files and build font
@@ -40,6 +41,11 @@ description for all fonts available in Windows. That's how MuPDF works.
 #include "FontEncodingTables.h"
 #include "GlobalParams.h"
 #include "GfxFont.h"
+#include <sys/stat.h>
+#include "Object.h"
+#include "Stream.h"
+#include "Lexer.h"
+#include "Parser.h"
 
 #if MULTITHREADED
 #  define lockGlobalParams            gLockMutex(&mutex)
@@ -58,6 +64,7 @@ description for all fonts available in Windows. That's how MuPDF works.
 #endif
 
 #define DEFAULT_SUBSTITUTE_FONT "Helvetica"
+#define DEFAULT_CID_FONT "MS-Mincho"
 
 static struct {
     const char *name;
@@ -147,7 +154,8 @@ static struct {
     {"Georgia-Bold", NULL, "georgiab.ttf"},
     {"Georgia-Italic", NULL, "georgiai.ttf"},
     {"Georgia-BoldItalic", NULL, "georgiaz.ttf"},
-
+    // default CID font:
+    {"MS-Mincho", NULL, "msmincho.ttf"},
     {NULL}
 };
 
@@ -346,6 +354,12 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
 
 void GlobalParams::setupBaseFonts(char * dir)
 {
+    const char *dataRoot = popplerDataDir ? popplerDataDir : POPPLER_DATADIR;
+    GooString *fileName = NULL;
+    struct stat buf;
+    FILE *file;
+    int size = 0;
+
     if (baseFontsInitialized)
         return;
     baseFontsInitialized = true;
@@ -381,20 +395,85 @@ void GlobalParams::setupBaseFonts(char * dir)
     if (winFontDir[0]) {
       sysFonts->scanWindowsFonts(new GooString(winFontDir));
     }
+
+    fileName = new GooString(dataRoot);
+    fileName->append("/cidfmap");
+    if (stat(fileName->getCString(), &buf) == 0) {
+      size = buf.st_size;
+    }
+    // try to open file
+#ifdef VMS
+    file = fopen(fileName->getCString(), "rb", "ctx=stm");
+#else
+    file = fopen(fileName->getCString(), "rb");
+#endif
+
+    if (file != NULL) {
+      Parser *parser;
+      Object obj1, obj2;
+
+      obj1.initNull();
+      parser = new Parser(NULL,
+	      new Lexer(NULL,
+	      new FileStream(file, 0, gFalse, size, &obj1)),
+	      gTrue);
+      obj1.free();
+      parser->getObj(&obj1);
+      while (!obj1.isEOF()) {
+	parser->getObj(&obj2);
+	if (obj1.isName()) {
+	  // Substitutions
+	  if (obj2.isDict()) {
+	    Object obj3;
+	    obj2.getDict()->lookup("Path", &obj3);
+	    if (obj3.isString())
+	      addFontFile(new GooString(obj1.getName()), obj3.getString()->copy());
+	    obj3.free();
+	  // Aliases
+	  } else if (obj2.isName()) {
+	    substFiles->add(new GooString(obj1.getName()), new GooString(obj2.getName()));
+	  }
+	}
+	obj2.free();
+	obj1.free();
+	parser->getObj(&obj1);
+	// skip trailing ';'
+	while (obj1.isCmd(";")) {
+	  obj1.free();
+	  parser->getObj(&obj1);
+	}
+      }
+      fclose(file);
+      delete parser;
+    }
 }
 
-static char *findSubstituteName(const char *origName)
+static char *findSubstituteName(GfxFont *font, GooHash *substFiles, const char *origName)
 {
     assert(origName);
     if (!origName) return NULL;
+    GooString *name2 = new GooString(origName);
+    int n = strlen(origName);
+    // remove trailing "-Identity-H"
+    if (n > 11 && !strcmp(name2->getCString() + n - 11, "-Identity-H")) {
+      name2->del(n - 11, 11);
+      n -= 11;
+    }
+    GooString *substName = (GooString *)substFiles->lookup(name2);
+    if (substName != NULL) {
+      delete name2;
+      return substName->getCString();
+    }
+
     /* TODO: try to at least guess bold/italic/bolditalic from the name */
-    return DEFAULT_SUBSTITUTE_FONT;
+    delete name2;
+    return (font->isCIDFont()) ? DEFAULT_CID_FONT: DEFAULT_SUBSTITUTE_FONT;
 }
 
 /* Windows implementation of external font matching code */
 GooString *GlobalParams::findSystemFontFile(GfxFont *font,
 					  SysFontType *type,
-					  int *fontNum, GooString * /*substituteFontName*/) {
+					  int *fontNum, GooString *substituteFontName) {
   SysFontInfo *fi;
   GooString *path = NULL;
   GooString *fontName = font->getName();
@@ -406,14 +485,21 @@ GooString *GlobalParams::findSystemFontFile(GfxFont *font,
     *type = fi->type;
     *fontNum = fi->fontNum;
   } else {
-    GooString *substFontName = new GooString(findSubstituteName(fontName->getCString()));
+    GooString *substFontName = new GooString(findSubstituteName(font, substFiles, fontName->getCString()));
+    GooString *path2 = NULL;
     error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{1:t}'", fontName, substFontName);
-    if ((fi = sysFonts->find(substFontName, gFalse))) {
-      path = fi->path->copy();
-      *type = fi->type;
-      *fontNum = fi->fontNum;
+    if ((path2 = (GooString *)fontFiles->lookup(substFontName))) {
+      path = new GooString(path2);
+      if (substituteFontName)
+	substituteFontName->Set(path->getCString());
+      if (!strcasecmp(path->getCString() + path->getLength() - 4, ".ttc")) {
+	*type = sysFontTTC;
+      } else {
+	*type = sysFontTTF;
+      }
+      *fontNum = 0;
     }
-  }      
+  }
   unlockGlobalParams;
   return path;
 }
commit 32e47ee03840cc8f21c00497025864d77edb75f5
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Sun Mar 4 15:21:13 2012 +0100

    Improve CJK suport in PSOutputDev
    
    1. Adapt bug fix for bug 11413 to the postscript device
    2. A small bug fix when locateFont doesn't find a suitable font and
    returns a null pointer
    
    to 1.:
    Adapting the implementation of the bug fix for splash and cairo to the
    postscript device was quite easy. But my first proofs of the output with
    ghostscript 8.71 shows some regressions where the CJK chars have a
    smaller height than the default square of the font. But the "48" in the
    output of bug-poppler11413.pdf which is set in a "normal" font but
    rotated was at the right position. Then I stepped to ghostscript 9.04,
    and now the CJK chars were shown correctly, but the 48 was positioned
    wrong. But because of these different tests I think that it is still a
    problem in ghostscript when using a mix of CJK fonts and "normal" fonts.
    BTW, also Acrobat X distiller has problems with the position of the "48"!
    
    to 2.:
    On my first tests with PDF which uses non embedded CJK fonts on Windows
    I got crashes. Reason for it was that GlobalParamWin returns Helvetica,
    which is not a CID font, but locateFont accepts here only CID fonts and
    therefore returns a NULL pointer. I first fixed that and then decided to
    return as default MS Mincho if a CID font is expected.

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index d8e3ac3..5187900 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1815,76 +1815,78 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
     setupType3Font(font, psName, parentResDict);
   } 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()) {
+    if (fontLoc != NULL) {
+      switch (fontLoc->locType) {
+      case gfxFontLocEmbedded:
+	switch (fontLoc->fontType) {
+	case fontType1:
 	  // 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 = 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;
 	}
-	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);
+      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;
-      default:
+      case gfxFontLocResident:
+	psName = fontLoc->path->copy();
 	break;
       }
-      break;
-    case gfxFontLocResident:
-      psName = fontLoc->path->copy();
-      break;
     }
 
     if (!psName) {
@@ -2363,9 +2365,6 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
   FoFiTrueType *ffTT;
   int *codeToGID;
   int codeToGIDLen;
-  CharCodeToUnicode *ctu;
-  Unicode *uBuf;
-  int cmap, code;
 
   // beginning comment
   writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2379,54 +2378,36 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
 
     // check for embedding permission
     if (ffTT->getEmbeddingRights() >= 1) {
-
-      // create a CID-to-GID mapping, via Unicode
-      if ((ctu = ((GfxCIDFont *)font)->getToUnicode())) {
-	// look for a Unicode cmap
-	for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) {
-	  if ((ffTT->getCmapPlatform(cmap) == 3 &&
-	       ffTT->getCmapEncoding(cmap) == 1) ||
-	      ffTT->getCmapPlatform(cmap) == 0) {
-	    break;
-	  }
+      codeToGID = NULL;
+      codeToGIDLen = 0;
+      if (((GfxCIDFont *)font)->getCIDToGID()) {
+	codeToGIDLen = ((GfxCIDFont *)font)->getCIDToGIDLen();
+	if (codeToGIDLen) {
+		codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int));
+		memcpy(codeToGID, ((GfxCIDFont *)font)->getCIDToGID(),
+			codeToGIDLen * sizeof(int));
 	}
-	if (cmap < ffTT->getNumCmaps()) {
-	  // map CID -> Unicode -> GID
-	  codeToGIDLen = ctu->getLength();
-	  codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int));
-	  for (code = 0; code < codeToGIDLen; ++code) {
-	    int n = ctu->mapToUnicode(code, &uBuf);
-	    if (n > 0) {
-	      codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]);
-	    } else {
-	      codeToGID[code] = 0;
-	    }
-	  }
-          if (ffTT->isOpenTypeCFF()) {
-	    ffTT->convertToCIDType0(psName->getCString(),
-				 codeToGID, codeToGIDLen,
-				 outputFunc, outputStream);
-          } else if (globalParams->getPSLevel() >= psLevel3) {
-	    // Level 3: use a CID font
-	    ffTT->convertToCIDType2(psName->getCString(),
-				    codeToGID, codeToGIDLen,
-				    needVerticalMetrics,
-				    outputFunc, outputStream);
-	  } else {
-	    // otherwise: use a non-CID composite font
-	    ffTT->convertToType0(psName->getCString(),
-				 codeToGID, codeToGIDLen,
-				 needVerticalMetrics,
-				 outputFunc, outputStream);
-	  }
-	  gfree(codeToGID);
-	}
-	ctu->decRefCnt();
       } else {
-	error(errSyntaxError, -1,
-	      "Couldn't find a mapping to Unicode for font '{0:s}'",
-	      font->getName() ? font->getName()->getCString() : "(unnamed)");
+	codeToGID = ((GfxCIDFont *)font)->getCodeToGIDMap(ffTT, &codeToGIDLen);
+      }
+      if (ffTT->isOpenTypeCFF()) {
+	ffTT->convertToCIDType0(psName->getCString(),
+		codeToGID, codeToGIDLen,
+		outputFunc, outputStream);
+      } else if (globalParams->getPSLevel() >= psLevel3) {
+	// Level 3: use a CID font
+	ffTT->convertToCIDType2(psName->getCString(),
+		codeToGID, codeToGIDLen,
+		needVerticalMetrics,
+		outputFunc, outputStream);
+      } else {
+	// otherwise: use a non-CID composite font
+	ffTT->convertToType0(psName->getCString(),
+		codeToGID, codeToGIDLen,
+		needVerticalMetrics,
+		outputFunc, outputStream);
       }
+      gfree(codeToGID);
     } else {
       error(errSyntaxError, -1,
 	    "TrueType font '%s' does not allow embedding",


More information about the poppler mailing list