[poppler] poppler/fofi: FoFiTrueType.cc, 1.5, 1.6 FoFiTrueType.h,
1.3, 1.4 FoFiType1.cc, 1.5, 1.6 FoFiType1C.cc, 1.3,
1.4 FoFiType1C.h, 1.3, 1.4
Albert Astals Cid
aacid at kemper.freedesktop.org
Wed Apr 25 12:59:12 PDT 2007
- Previous message: [poppler] poppler: ChangeLog,1.497,1.498 configure.ac,1.71,1.72
- Next message: [poppler] poppler/glib: poppler-action.cc, 1.10,
1.11 poppler-document.cc, 1.41, 1.42 poppler-page.cc, 1.54, 1.55
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvs/poppler/poppler/fofi
In directory kemper:/tmp/cvs-serv1447/fofi
Modified Files:
FoFiTrueType.cc FoFiTrueType.h FoFiType1.cc FoFiType1C.cc
FoFiType1C.h
Log Message:
Merge xpdf302branch in HEAD as noone vetoed it.
Testing more than welcome
Index: FoFiTrueType.cc
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiTrueType.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- FoFiTrueType.cc 2 Feb 2006 22:50:01 -0000 1.5
+++ FoFiTrueType.cc 25 Apr 2007 19:59:10 -0000 1.6
@@ -18,6 +18,7 @@
#include "goo/gmem.h"
#include "goo/GooString.h"
#include "goo/GooHash.h"
+#include "FoFiType1C.h"
#include "FoFiTrueType.h"
//
@@ -108,8 +109,11 @@
#define cmapTag 0x636d6170
#define glyfTag 0x676c7966
#define headTag 0x68656164
+#define hheaTag 0x68686561
+#define hmtxTag 0x686d7478
#define locaTag 0x6c6f6361
#define nameTag 0x6e616d65
+#define os2Tag 0x4f532f32
#define postTag 0x706f7374
static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
@@ -392,6 +396,28 @@
return nameToGID->lookupInt(name);
}
+Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
+ FoFiType1C *ff;
+ Gushort *map;
+ int i;
+
+ *nCIDs = 0;
+ if (!openTypeCFF) {
+ return NULL;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return NULL;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return NULL;
+ }
+ map = ff->getCIDToGIDMap(nCIDs);
+ delete ff;
+ return map;
+}
+
int FoFiTrueType::getEmbeddingRights() {
int i, fsType;
GBool ok;
@@ -420,13 +446,19 @@
Gushort *codeToGID,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[512];
+ GooString *buf;
GBool ok;
+ if (openTypeCFF) {
+ return;
+ }
+
// write the header
ok = gTrue;
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
+ (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
// begin the font dictionary
(*outputFunc)(outputStream, "10 dict begin\n", 14);
@@ -435,9 +467,10 @@
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
// write the guts of the dictionary
@@ -449,20 +482,47 @@
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}
+void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
+ GBool ascii, FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ FoFiType1C *ff;
+ int i;
+
+ if (!openTypeCFF) {
+ return;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return;
+ }
+ ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
+ delete ff;
+}
+
void FoFiTrueType::convertToCIDType2(char *psName,
Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[512];
+ GooString *buf;
Gushort cid;
GBool ok;
int i, j, k;
+ if (openTypeCFF) {
+ return;
+ }
+
// write the header
ok = gTrue;
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
+ (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
// begin the font dictionary
(*outputFunc)(outputStream, "20 dict begin\n", 14);
@@ -478,8 +538,9 @@
(*outputFunc)(outputStream, " end def\n", 10);
(*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
if (cidMap) {
- sprintf(buf, "/CIDCount %d def\n", nCIDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
if (nCIDs > 32767) {
(*outputFunc)(outputStream, "/CIDMap [", 9);
for (i = 0; i < nCIDs; i += 32768 - 16) {
@@ -488,8 +549,10 @@
(*outputFunc)(outputStream, " ", 2);
for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
cid = cidMap[i+j+k];
- sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("{0:02x}{1:02x}",
+ (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "\n", 1);
}
@@ -503,8 +566,10 @@
(*outputFunc)(outputStream, " ", 2);
for (j = 0; j < 16 && i+j < nCIDs; ++j) {
cid = cidMap[i+j];
- sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("{0:02x}{1:02x}",
+ (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "\n", 1);
}
@@ -512,27 +577,34 @@
}
} else {
// direct mapping - just fill the string(s) with s[i]=i
- sprintf(buf, "/CIDCount %d def\n", nGlyphs);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/CIDCount {0:d} def\n", nGlyphs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
if (nGlyphs > 32767) {
(*outputFunc)(outputStream, "/CIDMap [\n", 10);
for (i = 0; i < nGlyphs; i += 32767) {
j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
- sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
- " 255 and put\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format(" {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GooString::format(" 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
+ i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GooString::format(" 1 index exch dup 2 mul 1 add exch {0:d} add"
+ " 255 and put\n", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, " } for\n", 8);
}
(*outputFunc)(outputStream, "] def\n", 6);
} else {
- sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/CIDMap {0:d} string\n", 2 * nGlyphs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GooString::format(" 0 1 {0:d} {{\n", nGlyphs - 1);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream,
" 2 copy dup 2 mul exch -8 bitshift put\n", 42);
(*outputFunc)(outputStream,
@@ -542,9 +614,10 @@
}
}
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
(*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
(*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
@@ -560,14 +633,39 @@
56);
}
+void FoFiTrueType::convertToCIDType0(char *psName,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ FoFiType1C *ff;
+ int i;
+
+ if (!openTypeCFF) {
+ return;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return;
+ }
+ ff->convertToCIDType0(psName, outputFunc, outputStream);
+ delete ff;
+}
+
void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[512];
+ GooString *buf;
GooString *sfntsName;
int n, i, j;
+ if (openTypeCFF) {
+ return;
+ }
+
// write the Type 42 sfnts array
sfntsName = (new GooString(psName))->append("_sfnts");
cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
@@ -579,28 +677,33 @@
(*outputFunc)(outputStream, "10 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
(*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x def\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("_{0:02x} def\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
(*outputFunc)(outputStream, "/sfnts ", 7);
(*outputFunc)(outputStream, psName, strlen(psName));
(*outputFunc)(outputStream, "_sfnts def\n", 11);
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
for (j = 0; j < 256 && i+j < n; ++j) {
- sprintf(buf, "dup %d /c%02x put\n", j, j);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "readonly def\n", 13);
(*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
(*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
for (j = 0; j < 256 && i+j < n; ++j) {
- sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("/c{0:02x} {1:d} def\n",
+ j, cidMap ? cidMap[i+j] : i+j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "end readonly def\n", 17);
(*outputFunc)(outputStream,
@@ -617,21 +720,44 @@
(*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
(*outputFunc)(outputStream, "/Encoding [\n", 12);
for (i = 0; i < n; i += 256) {
- sprintf(buf, "%d\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("{0:d}\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
(*outputFunc)(outputStream, "/FDepVector [\n", 14);
for (i = 0; i < n; i += 256) {
(*outputFunc)(outputStream, "/", 1);
(*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x findfont\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("_{0:02x} findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}
+void FoFiTrueType::convertToType0(char *psName,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ FoFiType1C *ff;
+ int i;
+
+ if (!openTypeCFF) {
+ return;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return;
+ }
+ ff->convertToType0(psName, outputFunc, outputStream);
+ delete ff;
+}
+
void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
void *outputStream, char *name,
Gushort *codeToGID) {
@@ -673,12 +799,50 @@
0, 0, 0, 0, // min Type 1 memory
0, 0, 0, 0 // max Type 1 memory
};
- GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
+ static char os2Tab[86] = {
+ 0, 1, // version
+ 0, 1, // xAvgCharWidth
+ 0, 0, // usWeightClass
+ 0, 0, // usWidthClass
+ 0, 0, // fsType
+ 0, 0, // ySubscriptXSize
+ 0, 0, // ySubscriptYSize
+ 0, 0, // ySubscriptXOffset
+ 0, 0, // ySubscriptYOffset
+ 0, 0, // ySuperscriptXSize
+ 0, 0, // ySuperscriptYSize
+ 0, 0, // ySuperscriptXOffset
+ 0, 0, // ySuperscriptYOffset
+ 0, 0, // yStrikeoutSize
+ 0, 0, // yStrikeoutPosition
+ 0, 0, // sFamilyClass
+ 0, 0, 0, 0, 0, // panose
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, // ulUnicodeRange1
+ 0, 0, 0, 0, // ulUnicodeRange2
+ 0, 0, 0, 0, // ulUnicodeRange3
+ 0, 0, 0, 0, // ulUnicodeRange4
+ 0, 0, 0, 0, // achVendID
+ 0, 0, // fsSelection
+ 0, 0, // usFirstCharIndex
+ 0, 0, // usLastCharIndex
+ 0, 0, // sTypoAscender
+ 0, 0, // sTypoDescender
+ 0, 0, // sTypoLineGap
+ 0, 0, // usWinAscent
+ 0, 0, // usWinDescent
+ 0, 0, 0, 0, // ulCodePageRange1
+ 0, 0, 0, 0 // ulCodePageRange2
+ };
+ GBool missingCmap, missingName, missingPost, missingOS2;
+ GBool unsortedLoca, badCmapLen, abbrevHMTX;
int nZeroLengthTables;
+ int nHMetrics, advWidth, lsb;
TrueTypeLoca *locaTable;
TrueTypeTable *newTables;
- char *newNameTab, *newCmapTab;
+ char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab;
int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
+ int newHHEALen, newHMTXLen;
Guint locaChecksum, glyfChecksum, fileChecksum;
char *tableDir;
char locaBuf[4], checksumBuf[4];
@@ -686,10 +850,20 @@
Guint t;
int pos, i, j, k, n;
+ if (openTypeCFF) {
+ return;
+ }
+
// check for missing tables
+ // (Note: if the OS/2 table is missing, the Microsoft PCL5 driver
+ // will embed a PCL TrueType font with the pitch field set to zero,
+ // which apparently causes divide-by-zero errors. As far as I can
+ // tell, the only important field in the OS/2 table is
+ // xAvgCharWidth.)
missingCmap = (cmapIdx = seekTable("cmap")) < 0;
missingName = seekTable("name") < 0;
missingPost = seekTable("post") < 0;
+ missingOS2 = seekTable("OS/2") < 0;
// read the loca table, check to see if it's sorted
locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
@@ -706,6 +880,19 @@
if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
unsortedLoca = gTrue;
}
+ // glyph descriptions must be at least 12 bytes long (nContours,
+ // xMin, yMin, xMax, yMax, instructionLength - two bytes each);
+ // invalid glyph descriptions (even if they're never used) make
+ // Windows choke, so we work around that problem here (ideally,
+ // this would parse the glyph descriptions in the glyf table and
+ // remove any that were invalid, but this quick test is a decent
+ // start)
+ if (i > 0 &&
+ locaTable[i].origOffset - locaTable[i-1].origOffset > 0 &&
+ locaTable[i].origOffset - locaTable[i-1].origOffset < 12) {
+ locaTable[i-1].origOffset = locaTable[i].origOffset;
+ unsortedLoca = gTrue;
+ }
locaTable[i].idx = i;
}
@@ -733,9 +920,17 @@
}
}
+ // check for an abbreviated hmtx table (this is completely legal,
+ // but confuses the Microsoft PCL5 printer driver, which generates
+ // embedded fonts with the pitch field set to zero)
+ i = seekTable("hhea");
+ nHMetrics = getU16BE(tables[i].offset + 34, &ok);
+ abbrevHMTX = nHMetrics < nGlyphs;
+
// if nothing is broken, just write the TTF file as is
- if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
- !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) {
+ if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
+ !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
+ !name && !codeToGID) {
(*outputFunc)(outputStream, (char *)file, len);
goto done1;
}
@@ -893,6 +1088,44 @@
newCmapTab = NULL;
}
+ // generate the new hmtx table and the updated hhea table
+ if (abbrevHMTX) {
+ i = seekTable("hhea");
+ pos = tables[i].offset;
+ newHHEALen = 36;
+ newHHEATab = (char *)gmalloc(newHHEALen);
+ for (i = 0; i < newHHEALen; ++i) {
+ newHHEATab[i] = getU8(pos++, &ok);
+ }
+ newHHEATab[34] = nGlyphs >> 8;
+ newHHEATab[35] = nGlyphs & 0xff;
+ i = seekTable("hmtx");
+ pos = tables[i].offset;
+ newHMTXLen = 4 * nGlyphs;
+ newHMTXTab = (char *)gmalloc(newHMTXLen);
+ advWidth = 0;
+ for (i = 0; i < nHMetrics; ++i) {
+ advWidth = getU16BE(pos, &ok);
+ lsb = getU16BE(pos + 2, &ok);
+ pos += 4;
+ newHMTXTab[4*i ] = advWidth >> 8;
+ newHMTXTab[4*i + 1] = advWidth & 0xff;
+ newHMTXTab[4*i + 2] = lsb >> 8;
+ newHMTXTab[4*i + 3] = lsb & 0xff;
+ }
+ for (; i < nGlyphs; ++i) {
+ lsb = getU16BE(pos, &ok);
+ pos += 2;
+ newHMTXTab[4*i ] = advWidth >> 8;
+ newHMTXTab[4*i + 1] = advWidth & 0xff;
+ newHMTXTab[4*i + 2] = lsb >> 8;
+ newHMTXTab[4*i + 3] = lsb & 0xff;
+ }
+ } else {
+ newHHEATab = newHMTXTab = NULL;
+ newHHEALen = newHMTXLen = 0; // make gcc happy
+ }
+
// construct the new table directory:
// - keep all original tables with non-zero length
// - fix the cmap table's length, if necessary
@@ -902,7 +1135,7 @@
// - (re)compute table checksums
nNewTables = nTables - nZeroLengthTables +
(missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
- (missingPost ? 1 : 0);
+ (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
j = 0;
for (i = 0; i < nTables; ++i) {
@@ -933,6 +1166,14 @@
newTables[j].len = newNameLen;
newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
newNameLen);
+ } else if (newTables[j].tag == hheaTag && abbrevHMTX) {
+ newTables[j].len = newHHEALen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab,
+ newHHEALen);
+ } else if (newTables[j].tag == hmtxTag && abbrevHMTX) {
+ newTables[j].len = newHMTXLen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab,
+ newHMTXLen);
}
++j;
}
@@ -970,6 +1211,13 @@
newTables[j].len = sizeof(postTab);
++j;
}
+ if (missingOS2) {
+ newTables[j].tag = os2Tag;
+ newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab,
+ sizeof(os2Tab));
+ newTables[j].len = sizeof(os2Tab);
+ ++j;
+ }
qsort(newTables, nNewTables, sizeof(TrueTypeTable),
&cmpTrueTypeTableTag);
pos = 12 + nNewTables * 16;
@@ -1056,6 +1304,12 @@
(*outputFunc)(outputStream, nameTab, newTables[i].len);
} else if (newTables[i].tag == postTag && missingPost) {
(*outputFunc)(outputStream, postTab, newTables[i].len);
+ } else if (newTables[i].tag == os2Tag && missingOS2) {
+ (*outputFunc)(outputStream, os2Tab, newTables[i].len);
+ } else if (newTables[i].tag == hheaTag && abbrevHMTX) {
+ (*outputFunc)(outputStream, newHHEATab, newTables[i].len);
+ } else if (newTables[i].tag == hmtxTag && abbrevHMTX) {
+ (*outputFunc)(outputStream, newHMTXTab, newTables[i].len);
} else if (newTables[i].tag == locaTag && unsortedLoca) {
for (j = 0; j <= nGlyphs; ++j) {
if (locaFmt) {
@@ -1103,6 +1357,8 @@
}
}
+ gfree(newHMTXTab);
+ gfree(newHHEATab);
gfree(newCmapTab);
gfree(newNameTab);
gfree(tableDir);
@@ -1115,7 +1371,7 @@
FoFiOutputFunc outputFunc,
void *outputStream) {
char *name;
- char buf[64];
+ GooString *buf;
int i;
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
@@ -1124,15 +1380,17 @@
if (!(name = encoding[i])) {
name = ".notdef";
}
- sprintf(buf, "dup %d /", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("dup {0:d} /", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, name, strlen(name));
(*outputFunc)(outputStream, " put\n", 5);
}
} else {
for (i = 0; i < 256; ++i) {
- sprintf(buf, "dup %d /c%02x put\n", i, i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("dup {0:d} /c{1:02x} put\n", i, i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
}
(*outputFunc)(outputStream, "readonly def\n", 13);
@@ -1143,7 +1401,8 @@
FoFiOutputFunc outputFunc,
void *outputStream) {
char *name;
- char buf[64], buf2[16];
+ GooString *buf;
+ char buf2[16];
int i, k;
// always define '.notdef'
@@ -1178,8 +1437,9 @@
if (k > 0 && k < nGlyphs) {
(*outputFunc)(outputStream, "/", 1);
(*outputFunc)(outputStream, name, strlen(name));
- sprintf(buf, " %d def\n", k);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format(" {0:d} def\n", k);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
}
}
@@ -1482,14 +1742,15 @@
void FoFiTrueType::dumpString(Guchar *s, int length,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[64];
+ GooString *buf;
int pad, i, j;
(*outputFunc)(outputStream, "<", 1);
for (i = 0; i < length; i += 32) {
for (j = 0; j < 32 && i+j < length; ++j) {
- sprintf(buf, "%02X", s[i+j] & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GooString::format("{0:02x}", s[i+j] & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (i % (65536 - 32) == 65536 - 64) {
(*outputFunc)(outputStream, ">\n<", 3);
@@ -1536,12 +1797,9 @@
return checksum;
}
-#define toTag(a,b,c,d) (((unsigned int)(a)<<24) | ((unsigned int)(b)<<16) | ((unsigned int)(c)<<8) | (d))
-
void FoFiTrueType::parse() {
Guint topTag;
- int pos, i, j;
- unsigned int head;
+ int pos, ver, i, j;
parsedOk = gTrue;
@@ -1551,21 +1809,7 @@
return;
}
if (topTag == ttcfTag) {
- pos = getU32BE(12, &parsedOk);
- if (!parsedOk) {
- return;
- }
- } else {
- pos = 0;
- }
-
- // read the table directory
- head = getU32BE(pos, &parsedOk);
- if (! parsedOk)
- return;
- if (head == toTag('t','t','c','f')) {
/* TTC font */
- unsigned int tableDir;
int dircount;
dircount = getU32BE(8, &parsedOk);
@@ -1581,16 +1825,24 @@
pos = getU32BE(12 + faceIndex * 4, &parsedOk);
if (! parsedOk)
return;
+ } else {
+ pos = 0;
}
- pos += 4;
- nTables = getU16BE(pos, &parsedOk);
+ // check the sfnt version
+ ver = getU32BE(pos, &parsedOk);
if (!parsedOk) {
return;
}
+ openTypeCFF = ver == 0x4f54544f; // 'OTTO'
- pos += 8;
+ // read the table directory
+ nTables = getU16BE(pos + 4, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
+ pos += 12;
for (i = 0; i < nTables; ++i) {
tables[i].tag = getU32BE(pos, &parsedOk);
tables[i].checksum = getU32BE(pos + 4, &parsedOk);
@@ -1610,10 +1862,11 @@
// the Type 42 spec
if (seekTable("head") < 0 ||
seekTable("hhea") < 0 ||
- seekTable("loca") < 0 ||
seekTable("maxp") < 0 ||
- seekTable("glyf") < 0 ||
- seekTable("hmtx") < 0) {
+ seekTable("hmtx") < 0 ||
+ (!openTypeCFF && seekTable("loca") < 0) ||
+ (!openTypeCFF && seekTable("glyf") < 0) ||
+ (openTypeCFF && seekTable("CFF ") < 0)) {
parsedOk = gFalse;
return;
}
@@ -1662,23 +1915,28 @@
// 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) {
+ if (!openTypeCFF) {
+ i = seekTable("loca");
+ if (tables[i].len < 0) {
parsedOk = gFalse;
+ return;
+ }
+ if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
+ nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1;
+ }
+ 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;
}
- }
- if (!parsedOk) {
- return;
}
// read the post table
Index: FoFiTrueType.h
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiTrueType.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- FoFiTrueType.h 2 Feb 2006 22:50:01 -0000 1.3
+++ FoFiTrueType.h 25 Apr 2007 19:59:10 -0000 1.4
@@ -34,9 +34,12 @@
// Create a FoFiTrueType object from a file on disk.
static FoFiTrueType *load(char *fileName, int faceIndexA=0);
- FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA=0);
virtual ~FoFiTrueType();
+ // Returns true if this an OpenType font containing CFF data, false
+ // if it's a TrueType font (or OpenType font with TrueType data).
+ GBool isOpenTypeCFF() { return openTypeCFF; }
+
// Return the number of cmaps defined by this font.
int getNumCmaps();
@@ -58,6 +61,11 @@
// font does not have a post table.
int mapNameToGID(char *name);
+ // Return the mapping from CIDs to GIDs, and return the number of
+ // CIDs in *<nCIDs>. This is only useful for CID fonts. (Only
+ // useful for OpenType CFF fonts.)
+ Gushort *getCIDToGIDMap(int *nCIDs);
+
// Returns the least restrictive embedding licensing right (as
// defined by the TrueType spec):
// * 4: OS/2 table is missing or invalid
@@ -73,38 +81,63 @@
// <encoding> array specifies the mapping from char codes to names.
// If <encoding> is NULL, the encoding is unknown or undefined. The
// <codeToGID> array specifies the mapping from char codes to GIDs.
+ // (Not useful for OpenType CFF fonts.)
void convertToType42(char *psName, char **encoding,
Gushort *codeToGID,
FoFiOutputFunc outputFunc, void *outputStream);
+ // Convert to a Type 1 font, suitable for embedding in a PostScript
+ // file. This is only useful with 8-bit fonts. If <newEncoding> is
+ // not NULL, it will be used in place of the encoding in the Type 1C
+ // font. If <ascii> is true the eexec section will be hex-encoded,
+ // otherwise it will be left as binary data. If <psName> is
+ // non-NULL, it will be used as the PostScript font name. (Only
+ // useful for OpenType CFF fonts.)
+ void convertToType1(char *psName, char **newEncoding, GBool ascii,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
// Convert to a Type 2 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name (so we don't need to depend on the 'name' table in the
// font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
- // entries.
+ // entries. (Not useful for OpenType CFF fonts.)
void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
+ // Convert to a Type 0 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name. (Only useful for OpenType CFF fonts.)
+ void convertToCIDType0(char *psName,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name (so we don't need to depend on the 'name'
// table in the font). The <cidMap> array maps CIDs to GIDs; it has
- // <nCIDs> entries.
+ // <nCIDs> entries. (Not useful for OpenType CFF fonts.)
void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name. (Only useful for OpenType CFF fonts.)
+ void convertToType0(char *psName,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
// Write a clean TTF file, filling in missing tables and correcting
// 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.
+ // complete and correct, it will be written unmodified. (Not useful
+ // for OpenType CFF fonts.)
void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
char *name = NULL, Gushort *codeToGID = NULL);
private:
+ FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA);
void cvtEncoding(char **encoding,
FoFiOutputFunc outputFunc,
void *outputStream);
@@ -131,6 +164,7 @@
int locaFmt;
int bbox[4];
GooHash *nameToGID;
+ GBool openTypeCFF;
GBool parsedOk;
int faceIndex;
Index: FoFiType1.cc
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiType1.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- FoFiType1.cc 14 Sep 2005 21:20:36 -0000 1.5
+++ FoFiType1.cc 25 Apr 2007 19:59:10 -0000 1.6
@@ -75,7 +75,7 @@
void FoFiType1::writeEncoded(char **newEncoding,
FoFiOutputFunc outputFunc, void *outputStream) {
char buf[512];
- char *line;
+ char *line, *line2, *p;
int i;
// copy everything up to the encoding
@@ -101,19 +101,57 @@
}
(*outputFunc)(outputStream, "readonly def\n", 13);
- // copy everything after the encoding
+ // find the end of the encoding data
+ //~ this ought to parse PostScript tokens
if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line);
} else {
- for (line = getNextLine(line);
- line && strncmp(line, "readonly def", 12);
- line = getNextLine(line)) ;
- if (line) {
- line = getNextLine(line);
+ // skip "/Encoding" + one whitespace char,
+ // then look for 'def' preceded by PostScript whitespace
+ p = line + 10;
+ line = NULL;
+ for (; p < (char *)file + len; ++p) {
+ if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
+ *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
+ p + 4 <= (char *)file + len &&
+ !strncmp(p + 1, "def", 3)) {
+ line = p + 4;
+ break;
+ }
}
}
+
+ // some fonts have two /Encoding entries in their dictionary, so we
+ // check for a second one here
if (line) {
- (*outputFunc)(outputStream, line, ((char *)file + len) - line);
+ for (line2 = line, i = 0;
+ i < 20 && line2 && strncmp(line2, "/Encoding", 9);
+ line2 = getNextLine(line2), ++i) ;
+ if (i < 20 && line2) {
+ (*outputFunc)(outputStream, line, line2 - line);
+ if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
+ line = getNextLine(line2);
+ } else {
+ // skip "/Encoding" + one whitespace char,
+ // then look for 'def' preceded by PostScript whitespace
+ p = line2 + 10;
+ line = NULL;
+ for (; p < (char *)file + len; ++p) {
+ if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
+ *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
+ p + 4 <= (char *)file + len &&
+ !strncmp(p + 1, "def", 3)) {
+ line = p + 4;
+ break;
+ }
+ }
+ }
+ }
+
+ // copy everything after the encoding
+ if (line) {
+ (*outputFunc)(outputStream, line, ((char *)file + len) - line);
+ }
}
}
@@ -178,8 +216,15 @@
if (*p2) {
c = *p2;
*p2 = '\0';
- if ((code = atoi(p)) < 256) {
- *p2 = c;
+ code = atoi(p);
+ *p2 = c;
+ if (code == 8 && *p2 == '#') {
+ code = 0;
+ for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
+ code = code * 8 + (*p2 - '0');
+ }
+ }
+ if (code < 256) {
for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
if (*p == '/') {
++p;
Index: FoFiType1C.cc
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiType1C.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- FoFiType1C.cc 14 Sep 2005 21:20:36 -0000 1.3
+++ FoFiType1C.cc 25 Apr 2007 19:59:10 -0000 1.4
@@ -129,24 +129,33 @@
return map;
}
-void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
+void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc,
void *outputStream) {
+ int psNameLen;
Type1CEexecBuf eb;
Type1CIndex subrIdx;
Type1CIndexVal val;
[...965 lines suppressed...]
@@ -949,15 +1070,16 @@
int offset, int nBytes,
Type1CIndex *subrIdx,
Type1CPrivateDict *pDict) {
- char buf[512];
+ GooString *buf;
GooString *charBuf;
// generate the charstring
charBuf = new GooString();
cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
- sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
- eexecWrite(eb, buf);
+ buf = GooString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
+ eexecWrite(eb, buf->getCString());
+ delete buf;
eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
charBuf->getLength());
eexecWrite(eb, " ND\n");
Index: FoFiType1C.h
===================================================================
RCS file: /cvs/poppler/poppler/fofi/FoFiType1C.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- FoFiType1C.h 2 Feb 2006 22:50:01 -0000 1.3
+++ FoFiType1C.h 25 Apr 2007 19:59:10 -0000 1.4
@@ -138,7 +138,6 @@
// Create a FoFiType1C object from a file on disk.
static FoFiType1C *load(char *fileName);
- FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
virtual ~FoFiType1C();
// Return the font name.
@@ -156,8 +155,9 @@
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
- // otherwise it will be left as binary data.
- void convertToType1(char **newEncoding, GBool ascii,
+ // otherwise it will be left as binary data. If <psName> is non-NULL,
+ // it will be used as the PostScript font name.
+ void convertToType1(char *psName, char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
@@ -174,6 +174,7 @@
private:
+ FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
int offset, int nBytes,
Type1CIndex *subrIdx,
- Previous message: [poppler] poppler: ChangeLog,1.497,1.498 configure.ac,1.71,1.72
- Next message: [poppler] poppler/glib: poppler-action.cc, 1.10,
1.11 poppler-document.cc, 1.41, 1.42 poppler-page.cc, 1.54, 1.55
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the poppler
mailing list