[poppler] poppler/fofi: FoFiTrueType.cc, 1.3, 1.4 FoFiTrueType.h, 1.1.1.1, 1.2 FoFiType1.cc, 1.4, 1.5 FoFiType1C.cc, 1.2, 1.3 FoFiType1C.h, 1.1.1.1, 1.2

Albert Astals Cid aacid at freedesktop.org
Wed Sep 14 14:20:38 PDT 2005


Update of /cvs/poppler/poppler/fofi
In directory gabe:/tmp/cvs-serv19965/fofi

Modified Files:
	FoFiTrueType.cc FoFiTrueType.h FoFiType1.cc FoFiType1C.cc 
	FoFiType1C.h 
Log Message:
Merge all the fofi/ changes from xpdf 3.01, there is only one api change that affects PSOutputDev (also has been updated the part that uses this api not the whole file). All our fixes in that dir are included in the upgrade.


Index: FoFiTrueType.cc
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiTrueType.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- FoFiTrueType.cc	28 Aug 2005 09:43:18 -0000	1.3
+++ FoFiTrueType.cc	14 Sep 2005 21:20:36 -0000	1.4
@@ -78,6 +78,10 @@
 
 //------------------------------------------------------------------------
 
+#define ttcfTag 0x74746366
+
+//------------------------------------------------------------------------
+
 struct TrueTypeTable {
   Guint tag;
   Guint checksum;
@@ -103,6 +107,7 @@
 
 #define cmapTag 0x636d6170
 #define glyfTag 0x676c7966
+#define headTag 0x68656164
 #define locaTag 0x6c6f6361
 #define nameTag 0x6e616d65
 #define postTag 0x706f7374
@@ -154,9 +159,11 @@
   { "vhea", gFalse },
   { "vmtx", gFalse }
 };
-#define t42HeadTable 3
-#define t42LocaTable 6
-#define t42GlyfTable 2
+#define t42HeadTable  3
+#define t42LocaTable  6
+#define t42GlyfTable  2
+#define t42VheaTable  9
+#define t42VmtxTable 10
 
 //------------------------------------------------------------------------
 
@@ -277,7 +284,9 @@
 FoFiTrueType::~FoFiTrueType() {
   gfree(tables);
   gfree(cmaps);
-  delete nameToGID;
+  if (nameToGID) {
+    delete nameToGID;
+  }
 }
 
 int FoFiTrueType::getNumCmaps() {
@@ -433,7 +442,7 @@
   // write the guts of the dictionary
   cvtEncoding(encoding, outputFunc, outputStream);
   cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
-  cvtSfnts(outputFunc, outputStream, NULL);
+  cvtSfnts(outputFunc, outputStream, NULL, gFalse);
 
   // end the dictionary and define the font
   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
@@ -441,6 +450,7 @@
 
 void FoFiTrueType::convertToCIDType2(char *psName,
 				     Gushort *cidMap, int nCIDs,
+				     GBool needVerticalMetrics,
 				     FoFiOutputFunc outputFunc,
 				     void *outputStream) {
   char buf[512];
@@ -541,7 +551,7 @@
   (*outputFunc)(outputStream, "  end readonly def\n", 19);
 
   // write the guts of the dictionary
-  cvtSfnts(outputFunc, outputStream, NULL);
+  cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics);
 
   // end the dictionary and define the font
   (*outputFunc)(outputStream,
@@ -550,6 +560,7 @@
 }
 
 void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
+				  GBool needVerticalMetrics,
 				  FoFiOutputFunc outputFunc,
 				  void *outputStream) {
   char buf[512];
@@ -558,7 +569,7 @@
 
   // write the Type 42 sfnts array
   sfntsName = (new GooString(psName))->append("_sfnts");
-  cvtSfnts(outputFunc, outputStream, sfntsName);
+  cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
   delete sfntsName;
 
   // write the descendant Type 42 fonts
@@ -621,18 +632,28 @@
 }
 
 void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
-			    void *outputStream) {
-  static char cmapTab[20] = {
+			    void *outputStream, char *name,
+			    Gushort *codeToGID) {
+  // this substitute cmap table maps char codes 0000-ffff directly to
+  // glyphs 0000-ffff
+  static char cmapTab[36] = {
     0, 0,			// table version number
     0, 1,			// number of encoding tables
     0, 1,			// platform ID
     0, 0,			// encoding ID
     0, 0, 0, 12,		// offset of subtable
-    0, 0,			// subtable format
-    0, 1,			// subtable length
-    0, 1,			// subtable version
-    0,				// map char 0 -> glyph 0
-    0				// pad to multiple of four bytes
+    0, 4,			// subtable format
+    0, 24,			// subtable length
+    0, 0,			// subtable version
+    0, 2,			// segment count * 2
+    0, 2,			// 2 * 2 ^ floor(log2(segCount))
+    0, 0,			// floor(log2(segCount))
+    0, 0,			// 2*segCount - 2*2^floor(log2(segCount))
+    (char)0xff, (char)0xff,	// endCount[0]
+    0, 0,			// reserved
+    0, 0,			// startCount[0]
+    0, 0,			// idDelta[0]
+    0, 0			// pad to a mulitple of four bytes
   };
   static char nameTab[8] = {
     0, 0,			// format
@@ -655,9 +676,11 @@
   int nZeroLengthTables;
   TrueTypeLoca *locaTable;
   TrueTypeTable *newTables;
-  int nNewTables, cmapIdx, cmapLen, glyfLen;
+  char *newNameTab, *newCmapTab;
+  int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
+  Guint locaChecksum, glyfChecksum, fileChecksum;
   char *tableDir;
-  char locaBuf[4];
+  char locaBuf[4], checksumBuf[4];
   GBool ok;
   Guint t;
   int pos, i, j, k, n;
@@ -711,7 +734,7 @@
 
   // if nothing is broken, just write the TTF file as is
   if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
-      !badCmapLen && nZeroLengthTables == 0) {
+      !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) {
     (*outputFunc)(outputStream, (char *)file, len);
     goto done1;
   }
@@ -743,12 +766,139 @@
     glyfLen = pos;
   }
 
+  // compute checksums for the loca and glyf tables
+  locaChecksum = glyfChecksum = 0;
+  if (unsortedLoca) {
+    if (locaFmt) {
+      for (j = 0; j <= nGlyphs; ++j) {
+	locaChecksum += locaTable[j].newOffset;
+      }
+    } else {
+      for (j = 0; j <= nGlyphs; j += 2) {
+	locaChecksum += locaTable[j].newOffset << 16;
+	if (j + 1 <= nGlyphs) {
+	  locaChecksum += locaTable[j+1].newOffset;
+	}
+      }
+    }
+    pos = tables[seekTable("glyf")].offset;
+    for (j = 0; j < nGlyphs; ++j) {
+      n = locaTable[j].len;
+      if (n > 0) {
+	k = locaTable[j].origOffset;
+	if (checkRegion(pos + k, n)) {
+	  glyfChecksum += computeTableChecksum(file + pos + k, n);
+	}
+      }
+    }
+  }
+
+  // construct the new name table
+  if (name) {
+    n = strlen(name);
+    newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3;
+    newNameTab = (char *)gmalloc(newNameLen);
+    memset(newNameTab, 0, newNameLen);
+    newNameTab[0] = 0;		// format selector
+    newNameTab[1] = 0;
+    newNameTab[2] = 0;		// number of name records
+    newNameTab[3] = 4;
+    newNameTab[4] = 0;		// offset to start of string storage
+    newNameTab[5] = 6 + 4*12;
+    next = 0;
+    for (i = 0; i < 4; ++i) {
+      newNameTab[6 + i*12 + 0] = 0;	// platform ID = Microsoft
+      newNameTab[6 + i*12 + 1] = 3;
+      newNameTab[6 + i*12 + 2] = 0;	// encoding ID = Unicode
+      newNameTab[6 + i*12 + 3] = 1;
+      newNameTab[6 + i*12 + 4] = 0x04;	// language ID = American English
+      newNameTab[6 + i*12 + 5] = 0x09;
+      newNameTab[6 + i*12 + 6] = 0;	// name ID
+      newNameTab[6 + i*12 + 7] = i + 1;
+      newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length
+      newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff);
+      newNameTab[6 + i*12 + 10] = next >> 8;		    // string offset
+      newNameTab[6 + i*12 + 11] = next & 0xff;
+      if (i+1 == 2) {
+	memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14);
+	next += 14;
+      } else {
+	for (j = 0; j < n; ++j) {
+	  newNameTab[6 + 4*12 + next + 2*j] = 0;
+	  newNameTab[6 + 4*12 + next + 2*j + 1] = name[j];
+	}
+	next += 2*n;
+      }
+    }
+  } else {
+    newNameLen = 0;
+    newNameTab = NULL;
+  }
+
+  // construct the new cmap table
+  if (codeToGID) {
+    newCmapLen = 44 + 256 * 2;
+    newCmapTab = (char *)gmalloc(newCmapLen);
+    newCmapTab[0] = 0;		// table version number = 0
+    newCmapTab[1] = 0;
+    newCmapTab[2] = 0;		// number of encoding tables = 1
+    newCmapTab[3] = 1;
+    newCmapTab[4] = 0;		// platform ID = Microsoft
+    newCmapTab[5] = 3;
+    newCmapTab[6] = 0;		// encoding ID = Unicode
+    newCmapTab[7] = 1;
+    newCmapTab[8] = 0;		// offset of subtable
+    newCmapTab[9] = 0;
+    newCmapTab[10] = 0;
+    newCmapTab[11] = 12;
+    newCmapTab[12] = 0;		// subtable format = 4
+    newCmapTab[13] = 4;
+    newCmapTab[14] = 0x02;	// subtable length
+    newCmapTab[15] = 0x20;
+    newCmapTab[16] = 0;		// subtable version = 0
+    newCmapTab[17] = 0;
+    newCmapTab[18] = 0;		// segment count * 2
+    newCmapTab[19] = 4;
+    newCmapTab[20] = 0;		// 2 * 2 ^ floor(log2(segCount))
+    newCmapTab[21] = 4;
+    newCmapTab[22] = 0;		// floor(log2(segCount))
+    newCmapTab[23] = 1;
+    newCmapTab[24] = 0;		// 2*segCount - 2*2^floor(log2(segCount))
+    newCmapTab[25] = 0;
+    newCmapTab[26] = 0x00;	// endCount[0]
+    newCmapTab[27] = (char)0xff;
+    newCmapTab[28] = (char)0xff; // endCount[1]
+    newCmapTab[29] = (char)0xff;
+    newCmapTab[30] = 0;		// reserved
+    newCmapTab[31] = 0;
+    newCmapTab[32] = 0x00;	// startCount[0]
+    newCmapTab[33] = 0x00;
+    newCmapTab[34] = (char)0xff; // startCount[1]
+    newCmapTab[35] = (char)0xff;
+    newCmapTab[36] = 0;		// idDelta[0]
+    newCmapTab[37] = 0;
+    newCmapTab[38] = 0;		// idDelta[1]
+    newCmapTab[39] = 1;
+    newCmapTab[40] = 0;		// idRangeOffset[0]
+    newCmapTab[41] = 4;
+    newCmapTab[42] = 0;		// idRangeOffset[1]
+    newCmapTab[43] = 0;
+    for (i = 0; i < 256; ++i) {
+      newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
+      newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
+    }
+  } else {
+    newCmapLen = 0;
+    newCmapTab = NULL;
+  }
+
   // construct the new table directory:
   // - keep all original tables with non-zero length
   // - fix the cmap table's length, if necessary
   // - add missing tables
   // - sort the table by tag
   // - compute new table positions, including 4-byte alignment
+  // - (re)compute table checksums
   nNewTables = nTables - nZeroLengthTables +
                (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
                (missingPost ? 1 : 0);
@@ -758,31 +908,64 @@
     if (tables[i].len > 0) {
       newTables[j] = tables[i];
       newTables[j].origOffset = tables[i].offset;
-      if (newTables[j].tag == cmapTag && badCmapLen) {
+      if (checkRegion(tables[i].offset, newTables[i].len)) {
+	newTables[j].checksum =
+	    computeTableChecksum(file + tables[i].offset, tables[i].len);
+	if (tables[i].tag == headTag) {
+	  // don't include the file checksum
+	  newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok);
+	}
+      }
+      if (newTables[j].tag == cmapTag && codeToGID) {
+	newTables[j].len = newCmapLen;
+	newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
+						     newCmapLen);
+      } else if (newTables[j].tag == cmapTag && badCmapLen) {
 	newTables[j].len = cmapLen;
       } else if (newTables[j].tag == locaTag && unsortedLoca) {
 	newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+	newTables[j].checksum = locaChecksum;
       } else if (newTables[j].tag == glyfTag && unsortedLoca) {
 	newTables[j].len = glyfLen;
+	newTables[j].checksum = glyfChecksum;
+      } else if (newTables[j].tag == nameTag && name) {
+	newTables[j].len = newNameLen;
+	newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
+						     newNameLen);
       }
       ++j;
     }
   }
   if (missingCmap) {
     newTables[j].tag = cmapTag;
-    newTables[j].checksum = 0; //~ should compute the checksum
-    newTables[j].len = sizeof(cmapTab);
+    if (codeToGID) {
+      newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
+						   newCmapLen);
+      newTables[j].len = newCmapLen;
+    } else {
+      newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
+						   sizeof(cmapTab));
+      newTables[j].len = sizeof(cmapTab);
+    }
     ++j;
   }
   if (missingName) {
     newTables[j].tag = nameTag;
-    newTables[j].checksum = 0; //~ should compute the checksum
-    newTables[j].len = sizeof(nameTab);
+    if (name) {
+      newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
+						   newNameLen);
+      newTables[j].len = newNameLen;
+    } else {
+      newTables[j].checksum = computeTableChecksum((Guchar *)nameTab,
+						   sizeof(nameTab));
+      newTables[j].len = sizeof(nameTab);
+    }
     ++j;
   }
   if (missingPost) {
     newTables[j].tag = postTag;
-    newTables[j].checksum = 0; //~ should compute the checksum
+    newTables[j].checksum = computeTableChecksum((Guchar *)postTab,
+						 sizeof(postTab));
     newTables[j].len = sizeof(postTab);
     ++j;
   }
@@ -836,10 +1019,38 @@
   }
   (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
 
+  // compute the file checksum
+  fileChecksum = computeTableChecksum((Guchar *)tableDir,
+				      12 + nNewTables * 16);
+  for (i = 0; i < nNewTables; ++i) {
+    fileChecksum += newTables[i].checksum;
+  }
+  fileChecksum = 0xb1b0afba - fileChecksum;
+
   // write the tables
   for (i = 0; i < nNewTables; ++i) {
-    if (newTables[i].tag == cmapTag && missingCmap) {
+    if (newTables[i].tag == headTag) {
+      if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
+	(*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8);
+	checksumBuf[0] = fileChecksum >> 24;
+	checksumBuf[1] = fileChecksum >> 16;
+	checksumBuf[2] = fileChecksum >> 8;
+	checksumBuf[3] = fileChecksum;
+	(*outputFunc)(outputStream, checksumBuf, 4);
+	(*outputFunc)(outputStream,
+		      (char *)file + newTables[i].origOffset + 12,
+		      newTables[i].len - 12);
+      } else {
+	for (j = 0; j < newTables[i].len; ++j) {
+	  (*outputFunc)(outputStream, "\0", 1);
+	}
+      }
+    } else if (newTables[i].tag == cmapTag && codeToGID) {
+      (*outputFunc)(outputStream, newCmapTab, newTables[i].len);
+    } else if (newTables[i].tag == cmapTag && missingCmap) {
       (*outputFunc)(outputStream, cmapTab, newTables[i].len);
+    } else if (newTables[i].tag == nameTag && name) {
+      (*outputFunc)(outputStream, newNameTab, newTables[i].len);
     } else if (newTables[i].tag == nameTag && missingName) {
       (*outputFunc)(outputStream, nameTab, newTables[i].len);
     } else if (newTables[i].tag == postTag && missingPost) {
@@ -891,6 +1102,8 @@
     }
   }
 
+  gfree(newCmapTab);
+  gfree(newNameTab);
   gfree(tableDir);
   gfree(newTables);
  done1:
@@ -975,7 +1188,8 @@
 }
 
 void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
-			    void *outputStream, GooString *name) {
+			    void *outputStream, GooString *name,
+			    GBool needVerticalMetrics) {
   Guchar headData[54];
   TrueTypeLoca *locaTable;
   Guchar *locaData;
@@ -985,6 +1199,28 @@
   Guint checksum;
   int nNewTables;
   int length, pos, glyfPos, i, j, k;
+  Guchar vheaTab[36] = {
+    0, 1, 0, 0,			// table version number
+    0, 0,			// ascent
+    0, 0,			// descent
+    0, 0,			// reserved
+    0, 0,			// max advance height
+    0, 0,			// min top side bearing
+    0, 0,			// min bottom side bearing
+    0, 0,			// y max extent
+    0, 0,			// caret slope rise
+    0, 1,			// caret slope run
+    0, 0,			// caret offset
+    0, 0,			// reserved
+    0, 0,			// reserved
+    0, 0,			// reserved
+    0, 0,			// reserved
+    0, 0,			// metric data format
+    0, 1			// number of advance heights in vmtx table
+  };
+  Guchar *vmtxTab;
+  GBool needVhea, needVmtx;
+  int advance;
 
   // construct the 'head' table, zero out the font checksum
   i = seekTable("head");
@@ -1054,6 +1290,22 @@
       ++nNewTables;
     }
   }
+  vmtxTab = NULL; // make gcc happy
+  advance = 0; // make gcc happy
+  if (needVerticalMetrics) {
+    needVhea = seekTable("vhea") < 0;
+    needVmtx = seekTable("vmtx") < 0;
+    if (needVhea || needVmtx) {
+      i = seekTable("head");
+      advance = getU16BE(tables[i].offset + 18, &ok); // units per em
+      if (needVhea) {
+	++nNewTables;
+      }
+      if (needVmtx) {
+	++nNewTables;
+      }
+    }
+  }
 
   // construct the new table headers, including table checksums
   // (pad each table out to a multiple of 4 bytes)
@@ -1089,6 +1341,21 @@
 	if (checkRegion(tables[j].offset, length)) {
 	  checksum = computeTableChecksum(file + tables[j].offset, length);
 	}
+      } else if (needVerticalMetrics && i == t42VheaTable) {
+	vheaTab[10] = advance / 256;    // max advance height
+	vheaTab[11] = advance % 256;
+	length = sizeof(vheaTab);
+	checksum = computeTableChecksum(vheaTab, length);
+      } else if (needVerticalMetrics && i == t42VmtxTable) {
+	length = 4 + (nGlyphs - 1) * 4;
+	vmtxTab = (Guchar *)gmalloc(length);
+	vmtxTab[0] = advance / 256;
+	vmtxTab[1] = advance % 256;
+	for (j = 2; j < length; j += 2) {
+	  vmtxTab[j] = 0;
+	  vmtxTab[j+1] = 0;
+	}
+	checksum = computeTableChecksum(vmtxTab, length);
       } else if (t42Tables[i].required) {
 	//~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
 	//~       t42Tables[i].tag);
@@ -1194,6 +1461,11 @@
 	    checkRegion(tables[j].offset, tables[j].len)) {
 	  dumpString(file + tables[j].offset, tables[j].len,
 		     outputFunc, outputStream);
+	} else if (needVerticalMetrics && i == t42VheaTable) {
+	  dumpString(vheaTab, length, outputFunc, outputStream);
+	} else if (needVerticalMetrics && i == t42VmtxTable) {
+	  dumpString(vmtxTab, length, outputFunc, outputStream);
+	  gfree(vmtxTab);
 	}
       }
     }
@@ -1264,17 +1536,32 @@
 }
 
 void FoFiTrueType::parse() {
+  Guint topTag;
   int pos, i, j;
 
   parsedOk = gTrue;
 
+  // look for a collection (TTC)
+  topTag = getU32BE(0, &parsedOk);
+  if (!parsedOk) {
+    return;
+  }
+  if (topTag == ttcfTag) {
+    pos = getU32BE(12, &parsedOk);
+    if (!parsedOk) {
+      return;
+    }
+  } else {
+    pos = 0;
+  }
+
   // read the table directory
-  nTables = getU16BE(4, &parsedOk);
+  nTables = getU16BE(pos + 4, &parsedOk);
   if (!parsedOk) {
     return;
   }
   tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
-  pos = 12;
+  pos += 12;
   for (i = 0; i < nTables; ++i) {
     tables[i].tag = getU32BE(pos, &parsedOk);
     tables[i].checksum = getU32BE(pos + 4, &parsedOk);
@@ -1344,25 +1631,45 @@
     return;
   }
 
-  // read the post table
-  readPostTable();
+  // make sure the loca table is sane (correct length and entries are
+  // in bounds)
+  i = seekTable("loca");
+  if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
+    parsedOk = gFalse;
+    return;
+  }
+  for (j = 0; j <= nGlyphs; ++j) {
+    if (locaFmt) {
+      pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
+    } else {
+      pos = getU16BE(tables[i].offset + j*2, &parsedOk);
+    }
+    if (pos < 0 || pos > len) {
+      parsedOk = gFalse;
+    }
+  }
   if (!parsedOk) {
     return;
   }
+
+  // read the post table
+  readPostTable();
 }
 
 void FoFiTrueType::readPostTable() {
   GooString *name;
   int tablePos, postFmt, stringIdx, stringPos;
+  GBool ok;
   int i, j, n, m;
 
+  ok = gTrue;
   if ((i = seekTable("post")) < 0) {
     return;
   }
   tablePos = tables[i].offset;
-  postFmt = getU32BE(tablePos, &parsedOk);
-  if (!parsedOk) {
-    return;
+  postFmt = getU32BE(tablePos, &ok);
+  if (!ok) {
+    goto err;
   }
   if (postFmt == 0x00010000) {
     nameToGID = new GooHash(gTrue);
@@ -1371,9 +1678,9 @@
     }
   } else if (postFmt == 0x00020000) {
     nameToGID = new GooHash(gTrue);
-    n = getU16BE(tablePos + 32, &parsedOk);
-    if (!parsedOk) {
-      return;
+    n = getU16BE(tablePos + 32, &ok);
+    if (!ok) {
+      goto err;
     }
     if (n > nGlyphs) {
       n = nGlyphs;
@@ -1381,7 +1688,7 @@
     stringIdx = 0;
     stringPos = tablePos + 34 + 2*n;
     for (i = 0; i < n; ++i) {
-      j = getU16BE(tablePos + 34 + 2*i, &parsedOk);
+      j = getU16BE(tablePos + 34 + 2*i, &ok);
       if (j < 258) {
 	nameToGID->removeInt(macGlyphNames[j]);
 	nameToGID->add(new GooString(macGlyphNames[j]), i);
@@ -1390,15 +1697,14 @@
 	if (j != stringIdx) {
 	  for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
 	       stringIdx < j;
-	       ++stringIdx, stringPos += 1 + getU8(stringPos, &parsedOk)) ;
-	  if (!parsedOk) {
-	    return;
+	       ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
+	  if (!ok) {
+	    goto err;
 	  }
 	}
-	m = getU8(stringPos, &parsedOk);
-	if (!parsedOk || !checkRegion(stringPos + 1, m)) {
-	  parsedOk = gFalse;
-	  return;
+	m = getU8(stringPos, &ok);
+	if (!ok || !checkRegion(stringPos + 1, m)) {
+	  goto err;
 	}
 	name = new GooString((char *)&file[stringPos + 1], m);
 	nameToGID->removeInt(name);
@@ -1410,9 +1716,9 @@
   } else if (postFmt == 0x00028000) {
     nameToGID = new GooHash(gTrue);
     for (i = 0; i < nGlyphs; ++i) {
-      j = getU8(tablePos + 32 + i, &parsedOk);
-      if (!parsedOk) {
-	return;
+      j = getU8(tablePos + 32 + i, &ok);
+      if (!ok) {
+	goto err;
       }
       if (j < 258) {
 	nameToGID->removeInt(macGlyphNames[j]);
@@ -1420,6 +1726,14 @@
       }
     }
   }
+
+  return;
+
+ err:
+  if (nameToGID) {
+    delete nameToGID;
+    nameToGID = NULL;
+  }
 }
 
 int FoFiTrueType::seekTable(char *tag) {

Index: FoFiTrueType.h
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiTrueType.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- FoFiTrueType.h	3 Mar 2005 19:45:58 -0000	1.1.1.1
+++ FoFiTrueType.h	14 Sep 2005 21:20:36 -0000	1.2
@@ -16,6 +16,7 @@
 #include "goo/gtypes.h"
 #include "FoFiBase.h"
 
+class GooString;
 class GooHash;
 struct TrueTypeTable;
 struct TrueTypeCmap;
@@ -81,6 +82,7 @@
   // font).  The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
   // entries.
   void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
+			 GBool needVerticalMetrics,
 			 FoFiOutputFunc outputFunc, void *outputStream);
 
   // Convert to a Type 0 (but non-CID) composite font, suitable for
@@ -89,12 +91,16 @@
   // table in the font).  The <cidMap> array maps CIDs to GIDs; it has
   // <nCIDs> entries.
   void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
+		      GBool needVerticalMetrics,
 		      FoFiOutputFunc outputFunc, void *outputStream);
 
   // Write a clean TTF file, filling in missing tables and correcting
-  // various other errors.  If the font is complete and correct, it
-  // will be written unmodified.
-  void writeTTF(FoFiOutputFunc outputFunc, void *outputStream);
+  // various other errors.  If <name> is non-NULL, the font is renamed
+  // to <name>.  If <codeToGID> is non-NULL, the font is re-encoded,
+  // using a Windows Unicode cmap.  If <name> is NULL and the font is
+  // complete and correct, it will be written unmodified.
+  void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
+		char *name = NULL, Gushort *codeToGID = NULL);
 
 private:
 
@@ -107,7 +113,8 @@
 		      FoFiOutputFunc outputFunc,
 		      void *outputStream);
   void cvtSfnts(FoFiOutputFunc outputFunc,
-		void *outputStream, GooString *name);
+		void *outputStream, GooString *name,
+		GBool needVerticalMetrics);
   void dumpString(Guchar *s, int length,
 		  FoFiOutputFunc outputFunc,
 		  void *outputStream);

Index: FoFiType1.cc
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiType1.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- FoFiType1.cc	27 Aug 2005 08:43:43 -0000	1.4
+++ FoFiType1.cc	14 Sep 2005 21:20:36 -0000	1.5
@@ -108,6 +108,9 @@
     for (line = getNextLine(line);
 	 line && strncmp(line, "readonly def", 12);
 	 line = getNextLine(line)) ;
+    if (line) {
+      line = getNextLine(line);
+    }
   }
   if (line) {
     (*outputFunc)(outputStream, line, ((char *)file + len) - line);
@@ -160,9 +163,9 @@
       for (j = 0; j < 256; ++j) {
 	encoding[j] = NULL;
       }
-      line = getNextLine(line);
-      for (j = 0; j < 300 && line; ++j) {
-	line1 = getNextLine(line);
+      for (j = 0, line = getNextLine(line);
+	   j < 300 && line && (line1 = getNextLine(line));
+	   ++j, line = line1) {
 	if ((n = line1 - line) > 255) {
 	  n = 255;
 	}
@@ -186,22 +189,18 @@
 	      }
 	    }
 	  }
-	} 
-
-	// Any line that begins with "def" or contains " def"
-	// terminates the encoding array.
-	if (!strcmp (p, "def") || strstr (buf, " def"))
-	  break;
-
-	line = line1;
+	} else {
+	  if (strtok(buf, " \t") &&
+	      (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
+	    break;
+	  }
+	}
       }
       //~ check for getinterval/putinterval junk
 
     } else {
       line = getNextLine(line);
     }
-
-    ++i;
   }
 
   parsed = gTrue;

Index: FoFiType1C.cc
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiType1C.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- FoFiType1C.cc	27 Aug 2005 08:43:43 -0000	1.2
+++ FoFiType1C.cc	14 Sep 2005 21:20:36 -0000	1.3
@@ -476,10 +476,18 @@
   sprintf(buf, "  /Supplement %d def\n", topDict.supplement);
   (*outputFunc)(outputStream, buf, strlen(buf));
   (*outputFunc)(outputStream, "end def\n", 8);
-  sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
-	  topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
-	  topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
-  (*outputFunc)(outputStream, buf, strlen(buf));
+  if (topDict.hasFontMatrix) {
+    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+	    topDict.fontMatrix[0], topDict.fontMatrix[1],
+	    topDict.fontMatrix[2], topDict.fontMatrix[3],
+	    topDict.fontMatrix[4], topDict.fontMatrix[5]);
+    (*outputFunc)(outputStream, buf, strlen(buf));
+  } else if (privateDicts[0].hasFontMatrix) {
+    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+  } else {
+    (*outputFunc)(outputStream,
+		  "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
+  }
   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
 	  topDict.fontBBox[0], topDict.fontBBox[1],
 	  topDict.fontBBox[2], topDict.fontBBox[3]);
@@ -509,7 +517,18 @@
     sprintf(buf, "dup %d 10 dict begin\n", i);
     (*outputFunc)(outputStream, buf, strlen(buf));
     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+    if (privateDicts[i].hasFontMatrix) {
+      sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+	      privateDicts[i].fontMatrix[0],
+	      privateDicts[i].fontMatrix[1],
+	      privateDicts[i].fontMatrix[2],
+	      privateDicts[i].fontMatrix[3],
+	      privateDicts[i].fontMatrix[4],
+	      privateDicts[i].fontMatrix[5]);
+      (*outputFunc)(outputStream, buf, strlen(buf));
+    } else {
+      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+    }
     sprintf(buf, "/PaintType %d def\n", topDict.paintType);
     (*outputFunc)(outputStream, buf, strlen(buf));
     (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
@@ -699,11 +718,21 @@
     sprintf(buf, "_%02x def\n", i >> 8);
     (*outputFunc)(outputStream, buf, strlen(buf));
     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
-    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
-	    topDict.fontMatrix[0], topDict.fontMatrix[1],
-	    topDict.fontMatrix[2], topDict.fontMatrix[3],
-	    topDict.fontMatrix[4], topDict.fontMatrix[5]);
-    (*outputFunc)(outputStream, buf, strlen(buf));
+    if (privateDicts[fd].hasFontMatrix) {
+      sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+	      privateDicts[fd].fontMatrix[0],
+	      privateDicts[fd].fontMatrix[1],
+	      privateDicts[fd].fontMatrix[2],
+	      privateDicts[fd].fontMatrix[3],
+	      privateDicts[fd].fontMatrix[4],
+	      privateDicts[fd].fontMatrix[5]);
+      (*outputFunc)(outputStream, buf, strlen(buf));
+    } else if (topDict.hasFontMatrix) {
+      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+    } else {
+      (*outputFunc)(outputStream,
+		    "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
+    }
     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
 	    topDict.fontBBox[0], topDict.fontBBox[1],
 	    topDict.fontBBox[2], topDict.fontBBox[3]);
@@ -887,7 +916,15 @@
   (*outputFunc)(outputStream, psName, strlen(psName));
   (*outputFunc)(outputStream, " def\n", 5);
   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
-  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+  if (topDict.hasFontMatrix) {
+    sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+	    topDict.fontMatrix[0], topDict.fontMatrix[1],
+	    topDict.fontMatrix[2], topDict.fontMatrix[3],
+	    topDict.fontMatrix[4], topDict.fontMatrix[5]);
+    (*outputFunc)(outputStream, buf, strlen(buf));
+  } else {
+    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+  }
   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
   (*outputFunc)(outputStream, "/Encoding [\n", 12);
   for (i = 0; i < nCIDs; i += 256) {
@@ -947,6 +984,7 @@
     nOps = 0;
     nHints = 0;
     firstOp = gTrue;
+    openPath = gFalse;
   }
 
   pos = offset;
@@ -970,6 +1008,7 @@
 	d = 0;
 	dFP = gFalse;
 	for (k = 0; k < nOps; k += 2) {
+	  // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
 	  if (ops[k+1].num < 0) {
 	    d += ops[k].num + ops[k+1].num;
 	    dFP |= ops[k].isFP | ops[k+1].isFP;
@@ -999,6 +1038,7 @@
 	d = 0;
 	dFP = gFalse;
 	for (k = 0; k < nOps; k += 2) {
+	  // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
 	  if (ops[k+1].num < 0) {
 	    d += ops[k].num + ops[k+1].num;
 	    dFP |= ops[k].isFP | ops[k+1].isFP;
@@ -1022,6 +1062,10 @@
 	  cvtGlyphWidth(nOps == 2, charBuf, pDict);
 	  firstOp = gFalse;
 	}
+	if (openPath) {
+	  charBuf->append((char)9);
+	  openPath = gFalse;
+	}
 	if (nOps != 1) {
 	  //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
 	}
@@ -1039,6 +1083,7 @@
 	  charBuf->append((char)5);
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0006:		// hlineto
 	if (nOps < 1) {
@@ -1049,6 +1094,7 @@
 	  charBuf->append((char)((k & 1) ? 7 : 6));
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0007:		// vlineto
 	if (nOps < 1) {
@@ -1059,6 +1105,7 @@
 	  charBuf->append((char)((k & 1) ? 6 : 7));
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0008:		// rrcurveto
 	if (nOps < 6 || nOps % 6 != 0) {
@@ -1074,6 +1121,7 @@
 	  charBuf->append((char)8);
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x000a:		// callsubr
 	if (nOps >= 1) {
@@ -1099,6 +1147,10 @@
 	  cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
 	  firstOp = gFalse;
 	}
+	if (openPath) {
+	  charBuf->append((char)9);
+	  openPath = gFalse;
+	}
 	if (nOps == 4) {
 	  cvtNum(0, gFalse, charBuf);
 	  cvtNum(ops[0].num, ops[0].isFP, charBuf);
@@ -1174,6 +1226,10 @@
 	  cvtGlyphWidth(nOps == 3, charBuf, pDict);
 	  firstOp = gFalse;
 	}
+	if (openPath) {
+	  charBuf->append((char)9);
+	  openPath = gFalse;
+	}
 	if (nOps != 2) {
 	  //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
 	}
@@ -1187,6 +1243,10 @@
 	  cvtGlyphWidth(nOps == 2, charBuf, pDict);
 	  firstOp = gFalse;
 	}
+	if (openPath) {
+	  charBuf->append((char)9);
+	  openPath = gFalse;
+	}
 	if (nOps != 1) {
 	  //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
 	}
@@ -1223,6 +1283,7 @@
 	cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
 	charBuf->append((char)5);
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0019:		// rlinecurve
 	if (nOps < 8 || (nOps - 6) % 2 != 0) {
@@ -1241,6 +1302,7 @@
 	cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
 	charBuf->append((char)8);
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x001a:		// vvcurveto
 	if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
@@ -1268,6 +1330,7 @@
 	  charBuf->append((char)8);
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x001b:		// hhcurveto
 	if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
@@ -1295,6 +1358,7 @@
 	  charBuf->append((char)8);
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x001d:		// callgsubr
 	if (nOps >= 1) {
@@ -1348,6 +1412,7 @@
 	  charBuf->append((char)8);
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x001f:		// hvcurveto
 	if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
@@ -1387,6 +1452,7 @@
 	  charBuf->append((char)8);
 	}
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0c00:		// dotsection (should be Type 1 only?)
 	// ignored
@@ -1436,6 +1502,7 @@
 	cvtNum(0, gFalse, charBuf);
 	charBuf->append((char)8);
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0c23:		// flex
 	if (nOps != 13) {
@@ -1456,6 +1523,7 @@
 	cvtNum(ops[11].num, ops[11].isFP, charBuf);
 	charBuf->append((char)8);
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0c24:		// hflex1
 	if (nOps != 9) {
@@ -1477,6 +1545,7 @@
 	       ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
 	charBuf->append((char)8);
 	nOps = 0;
+	openPath = gTrue;
 	break;
       case 0x0c25:		// flex1
 	if (nOps != 11) {
@@ -1506,6 +1575,7 @@
 	}
 	charBuf->append((char)8);
 	nOps = 0;
+	openPath = gTrue;
 	break;
       default:
 	//~ error(-1, "Illegal Type 2 charstring op: %04x",
@@ -1773,6 +1843,7 @@
   topDict.fontMatrix[3] = 0.001;
   topDict.fontMatrix[4] = 0;
   topDict.fontMatrix[5] = 0;
+  topDict.hasFontMatrix = gFalse;
   topDict.uniqueID = 0;
   topDict.fontBBox[0] = 0;
   topDict.fontBBox[1] = 0;
@@ -1821,7 +1892,8 @@
 	           topDict.fontMatrix[2] = ops[2].num;
 	           topDict.fontMatrix[3] = ops[3].num;
 	           topDict.fontMatrix[4] = ops[4].num;
-	           topDict.fontMatrix[5] = ops[5].num; break;
+	           topDict.fontMatrix[5] = ops[5].num;
+		   topDict.hasFontMatrix = gTrue; break;
       case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
       case 0x0005: topDict.fontBBox[0] = ops[0].num;
 	           topDict.fontBBox[1] = ops[1].num;
@@ -1845,10 +1917,14 @@
 }
 
 // Read a CID font dict (FD) - this pulls out the private dict
-// pointer, and reads the private dict.
+// pointer, and reads the private dict.  It also pulls the FontMatrix
+// (if any) out of the FD.
 void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
   int pos, pSize, pOffset;
+  double fontMatrix[6];
+  GBool hasFontMatrix;
 
+  hasFontMatrix = gFalse;
   pSize = pOffset = 0;
   pos = offset;
   nOps = 0;
@@ -1866,17 +1942,35 @@
 	pSize = (int)ops[0].num;
 	pOffset = (int)ops[1].num;
 	break;
+      } else if (ops[nOps - 1].op == 0x0c07) {
+	fontMatrix[0] = ops[0].num;
+	fontMatrix[1] = ops[1].num;
+	fontMatrix[2] = ops[2].num;
+	fontMatrix[3] = ops[3].num;
+	fontMatrix[4] = ops[4].num;
+	fontMatrix[5] = ops[5].num;
+	hasFontMatrix = gTrue;
       }
       nOps = 0;
     }
   }
   readPrivateDict(pOffset, pSize, pDict);
+  if (hasFontMatrix) {
+    pDict->fontMatrix[0] = fontMatrix[0];
+    pDict->fontMatrix[1] = fontMatrix[1];
+    pDict->fontMatrix[2] = fontMatrix[2];
+    pDict->fontMatrix[3] = fontMatrix[3];
+    pDict->fontMatrix[4] = fontMatrix[4];
+    pDict->fontMatrix[5] = fontMatrix[5];
+    pDict->hasFontMatrix = gTrue;
+  }
 }
 
 void FoFiType1C::readPrivateDict(int offset, int length,
 				 Type1CPrivateDict *pDict) {
   int pos;
 
+  pDict->hasFontMatrix = gFalse;
   pDict->nBlueValues = 0;
   pDict->nOtherBlues = 0;
   pDict->nFamilyBlues = 0;
@@ -1895,9 +1989,9 @@
   pDict->initialRandomSeed = 0;
   pDict->subrsOffset = 0;
   pDict->defaultWidthX = 0;
-  pDict->defaultWidthXFP = 0;
+  pDict->defaultWidthXFP = gFalse;
   pDict->nominalWidthX = 0;
-  pDict->nominalWidthXFP = 0;
+  pDict->nominalWidthXFP = gFalse;
 
   // no dictionary
   if (offset == 0 || length == 0) {
@@ -1976,9 +2070,11 @@
 	break;
       case 0x0014:
 	pDict->defaultWidthX = ops[0].num;
+	pDict->defaultWidthXFP = ops[0].isFP;
 	break;
       case 0x0015:
 	pDict->nominalWidthX = ops[0].num;
+	pDict->nominalWidthXFP = ops[0].isFP;
 	break;
       }
       nOps = 0;
@@ -2321,9 +2417,9 @@
   idx->pos = pos;
   idx->len = getU16BE(pos, ok);
   if (idx->len == 0) {
-    // empty indexes are legal
+    // empty indexes are legal and contain just the length field
     idx->offSize = 0;
-    idx->startPos = idx->endPos = 0;
+    idx->startPos = idx->endPos = pos + 2;
   } else {
     idx->offSize = getU8(pos + 2, ok);
     if (idx->offSize < 1 || idx->offSize > 4) {
@@ -2353,7 +2449,7 @@
 				   idx->offSize, ok);
   pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
 				   idx->offSize, ok);
-  if (pos0 < idx->startPos || pos0 >= idx->endPos ||
+  if (pos0 < idx->startPos || pos0 > idx->endPos ||
       pos1 <= idx->startPos || pos1 > idx->endPos ||
       pos1 < pos0) {
     *ok = gFalse;
@@ -2371,7 +2467,7 @@
   } else {
     sid -= 391;
     getIndexVal(&stringIdx, sid, &val, ok);
-    if (ok) {
+    if (*ok) {
       if ((n = val.len) > 255) {
 	n = 255;
       }

Index: FoFiType1C.h
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiType1C.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- FoFiType1C.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ FoFiType1C.h	14 Sep 2005 21:20:36 -0000	1.2
@@ -49,6 +49,9 @@
   int paintType;
   int charstringType;
   double fontMatrix[6];
+  GBool hasFontMatrix;		// CID fonts are allowed to put their
+				//   FontMatrix in the FD instead of the
+				//   top dict
   int uniqueID;
   double fontBBox[4];
   double strokeWidth;
@@ -71,6 +74,8 @@
 #define type1CMaxStemSnap   12
 
 struct Type1CPrivateDict {
+  double fontMatrix[6];
+  GBool hasFontMatrix;
   int blueValues[type1CMaxBlueValues];
   int nBlueValues;
   int otherBlues[type1CMaxOtherBlues];
@@ -219,6 +224,7 @@
   int nOps;			// number of operands
   int nHints;			// number of hints for the current glyph
   GBool firstOp;		// true if we haven't hit the first op yet
+  GBool openPath;		// true if there is an unclosed path
 };
 
 #endif



More information about the poppler mailing list