CHANGES IN CUPS V1.1.20rc1
+ - Updated the pdftops filter to be based upon Xpdf
+ 2.02pl1 (STR #191)
- The scheduler did not reset the group list when
running CGI and filter processes (STR #185)
- The scheduler no longer calls malloc and free from the
//
// Array.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#pragma implementation
#endif
+#include <stdlib.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
}
Object *Array::get(int i, Object *obj) {
+ if (i < 0 || i >= length) {
+#ifdef DEBUG_MEM
+ abort();
+#else
+ return obj->initNull();
+#endif
+ }
return elems[i].fetch(xref, obj);
}
Object *Array::getNF(int i, Object *obj) {
+ if (i < 0 || i >= length) {
+#ifdef DEBUG_MEM
+ abort();
+#else
+ return obj->initNull();
+#endif
+ }
return elems[i].copy(obj);
}
//
// BuiltinFont.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// BuiltinFontTables.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// CMap.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Catalog.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// CharCodeToUnicode.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Decrypt.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
# DO NOT DELETE
-pdftops.o: ../cups/string.h config.h parseargs.h gtypes.h GString.h gmem.h
+pdftops.o: ../cups/string.h ../config.h parseargs.h gtypes.h GString.h gmem.h
pdftops.o: Object.h Array.h Dict.h Stream.h XRef.h Catalog.h Page.h PDFDoc.h
pdftops.o: Link.h PSOutputDev.h GlobalParams.h CharTypes.h OutputDev.h
pdftops.o: Params.h Error.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
pdftops.o: ../cups/md5.h ../cups/ppd.h
-Annot.o: config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h
-Annot.o: Gfx.h Annot.h
-Array.o: config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h
-BuiltinFont.o: config.h gmem.h FontEncodingTables.h BuiltinFont.h gtypes.h
-BuiltinFontTables.o: config.h FontEncodingTables.h BuiltinFontTables.h
+Annot.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Annot.o: Stream.h Gfx.h Annot.h
+Array.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Array.o: Stream.h
+BuiltinFont.o: ../config.h gmem.h FontEncodingTables.h BuiltinFont.h gtypes.h
+BuiltinFontTables.o: ../config.h FontEncodingTables.h BuiltinFontTables.h
BuiltinFontTables.o: BuiltinFont.h gtypes.h
-Catalog.o: config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Catalog.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
Catalog.o: Stream.h XRef.h Page.h Error.h Link.h Catalog.h
-CharCodeToUnicode.o: config.h gmem.h gfile.h gtypes.h GString.h Error.h
+CharCodeToUnicode.o: ../config.h gmem.h gfile.h gtypes.h GString.h Error.h
CharCodeToUnicode.o: GlobalParams.h CharTypes.h PSTokenizer.h
CharCodeToUnicode.o: CharCodeToUnicode.h
-CMap.o: config.h gmem.h gfile.h gtypes.h GString.h Error.h GlobalParams.h
+CMap.o: ../config.h gmem.h gfile.h gtypes.h GString.h Error.h GlobalParams.h
CMap.o: CharTypes.h PSTokenizer.h CMap.h
-Decrypt.o: config.h gmem.h Decrypt.h gtypes.h GString.h
-Dict.o: config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h
-Dict.o: XRef.h
-Error.o: config.h GlobalParams.h gtypes.h CharTypes.h Error.h
+Decrypt.o: ../config.h gmem.h Decrypt.h gtypes.h GString.h
+Dict.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Dict.o: Stream.h XRef.h
+Error.o: ../config.h GlobalParams.h gtypes.h CharTypes.h Error.h
FontEncoding.o: gmem.h FontEncoding.h gtypes.h
-FontEncodingTables.o: config.h FontEncodingTables.h
-FontFile.o: config.h gmem.h Error.h GlobalParams.h gtypes.h CharTypes.h
+FontEncodingTables.o: ../config.h FontEncodingTables.h
+FontFile.o: ../config.h gmem.h Error.h GlobalParams.h gtypes.h CharTypes.h
FontFile.o: CharCodeToUnicode.h FontEncodingTables.h FontFile.h GString.h
FontFile.o: CompactFontTables.h
-Function.o: config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Function.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
Function.o: Stream.h Error.h Function.h
-gfile.o: config.h GString.h gfile.h gtypes.h
-Gfx.o: config.h gmem.h GlobalParams.h gtypes.h CharTypes.h Object.h GString.h
-Gfx.o: Array.h Dict.h Stream.h Lexer.h Parser.h GfxFont.h GfxState.h
-Gfx.o: Function.h OutputDev.h Page.h Error.h Gfx.h
-GfxFont.o: config.h gmem.h Error.h Object.h gtypes.h GString.h Array.h Dict.h
-GfxFont.o: Stream.h GlobalParams.h CharTypes.h CMap.h CharCodeToUnicode.h
-GfxFont.o: FontEncodingTables.h BuiltinFontTables.h BuiltinFont.h FontFile.h
-GfxFont.o: GfxFont.h
-GfxState.o: config.h gmem.h Error.h Object.h gtypes.h GString.h Array.h
+gfile.o: ../config.h GString.h gfile.h gtypes.h
+Gfx.o: ../config.h gmem.h GlobalParams.h gtypes.h CharTypes.h Object.h
+Gfx.o: GString.h Array.h Dict.h Stream.h Lexer.h Parser.h GfxFont.h
+Gfx.o: GfxState.h Function.h OutputDev.h Page.h Error.h Gfx.h
+GfxFont.o: ../config.h gmem.h Error.h Object.h gtypes.h GString.h Array.h
+GfxFont.o: Dict.h Stream.h GlobalParams.h CharTypes.h CMap.h
+GfxFont.o: CharCodeToUnicode.h FontEncodingTables.h BuiltinFontTables.h
+GfxFont.o: BuiltinFont.h FontFile.h GfxFont.h
+GfxState.o: ../config.h gmem.h Error.h Object.h gtypes.h GString.h Array.h
GfxState.o: Dict.h Stream.h Page.h GfxState.h Function.h
-GHash.o: config.h gmem.h GString.h GHash.h gtypes.h
-GList.o: config.h gmem.h GList.h gtypes.h
-GlobalParams.o: config.h gmem.h GString.h GList.h gtypes.h GHash.h gfile.h
+GHash.o: ../config.h gmem.h GString.h GHash.h gtypes.h
+GList.o: ../config.h gmem.h GList.h gtypes.h
+GlobalParams.o: ../config.h gmem.h GString.h GList.h gtypes.h GHash.h gfile.h
GlobalParams.o: Error.h NameToCharCode.h CharTypes.h CharCodeToUnicode.h
GlobalParams.o: UnicodeMap.h CMap.h BuiltinFontTables.h BuiltinFont.h
GlobalParams.o: FontEncodingTables.h GlobalParams.h NameToUnicodeTable.h
GlobalParams.o: UnicodeMapTables.h DisplayFontTable.h UTF8.h
-gmempp.o: config.h gmem.h
-GString.o: config.h gtypes.h GString.h
-JBIG2Stream.o: config.h GList.h gtypes.h Error.h JBIG2Stream.h Object.h
+gmempp.o: ../config.h gmem.h
+GString.o: ../config.h gtypes.h GString.h
+JBIG2Stream.o: ../config.h GList.h gtypes.h Error.h JBIG2Stream.h Object.h
JBIG2Stream.o: gmem.h GString.h Array.h Dict.h Stream.h Stream-CCITT.h
-Lexer.o: config.h Lexer.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
-Lexer.o: Stream.h Error.h
-Link.o: config.h gmem.h GString.h Error.h Object.h gtypes.h Array.h Dict.h
+Lexer.o: ../config.h Lexer.h Object.h gtypes.h gmem.h GString.h Array.h
+Lexer.o: Dict.h Stream.h Error.h
+Link.o: ../config.h gmem.h GString.h Error.h Object.h gtypes.h Array.h Dict.h
Link.o: Stream.h Link.h
-NameToCharCode.o: config.h gmem.h NameToCharCode.h CharTypes.h
-Object.o: config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h Stream.h
-Object.o: Error.h XRef.h
-Outline.o: config.h gmem.h GString.h GList.h gtypes.h Link.h Object.h Array.h
-Outline.o: Dict.h Stream.h PDFDocEncoding.h CharTypes.h Outline.h
-OutputDev.o: config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
+NameToCharCode.o: ../config.h gmem.h NameToCharCode.h CharTypes.h
+Object.o: ../config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
+Object.o: Stream.h Error.h XRef.h
+Outline.o: ../config.h gmem.h GString.h GList.h gtypes.h Link.h Object.h
+Outline.o: Array.h Dict.h Stream.h PDFDocEncoding.h CharTypes.h Outline.h
+OutputDev.o: ../config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
OutputDev.o: Stream.h GfxState.h Function.h OutputDev.h CharTypes.h
-Page.o: config.h GlobalParams.h gtypes.h CharTypes.h Object.h gmem.h
+Page.o: ../config.h GlobalParams.h gtypes.h CharTypes.h Object.h gmem.h
Page.o: GString.h Array.h Dict.h Stream.h XRef.h Link.h OutputDev.h Gfx.h
Page.o: Annot.h Error.h Page.h
-Params.o: gtypes.h gmem.h GString.h config.h gfile.h Params.h
-Parser.o: config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h Stream.h
-Parser.o: Parser.h Lexer.h XRef.h Error.h Decrypt.h
-PDFDoc.o: config.h GString.h GlobalParams.h gtypes.h CharTypes.h Page.h
+Params.o: gtypes.h gmem.h GString.h ../config.h gfile.h Params.h
+Parser.o: ../config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
+Parser.o: Stream.h Parser.h Lexer.h XRef.h Error.h Decrypt.h
+PDFDoc.o: ../config.h GString.h GlobalParams.h gtypes.h CharTypes.h Page.h
PDFDoc.o: Object.h gmem.h Array.h Dict.h Stream.h Catalog.h XRef.h Link.h
PDFDoc.o: OutputDev.h Error.h ErrorCodes.h Lexer.h Parser.h Outline.h
PDFDoc.o: PDFDoc.h
PDFDocEncoding.o: PDFDocEncoding.h CharTypes.h
-PSOutputDev.o: config.h GString.h GlobalParams.h gtypes.h CharTypes.h
-PSOutputDev.o: Object.h gmem.h Array.h Dict.h Stream.h Error.h Function.h
-PSOutputDev.o: Gfx.h GfxState.h GfxFont.h CharCodeToUnicode.h UnicodeMap.h
-PSOutputDev.o: FontFile.h Catalog.h Page.h Annot.h PSOutputDev.h OutputDev.h
-PSTokenizer.o: config.h PSTokenizer.h gtypes.h
-Stream.o: config.h gmem.h gfile.h gtypes.h Error.h Object.h GString.h Array.h
-Stream.o: Dict.h Stream.h Decrypt.h JBIG2Stream.h Stream-CCITT.h
-UnicodeMap.o: config.h gmem.h gfile.h gtypes.h GString.h GList.h Error.h
+PSOutputDev.o: ../config.h GString.h GList.h gtypes.h GlobalParams.h
+PSOutputDev.o: CharTypes.h Object.h gmem.h Array.h Dict.h Stream.h Error.h
+PSOutputDev.o: Function.h Gfx.h GfxState.h GfxFont.h CharCodeToUnicode.h
+PSOutputDev.o: UnicodeMap.h FontFile.h Catalog.h Page.h Annot.h PSOutputDev.h
+PSOutputDev.o: OutputDev.h
+PSTokenizer.o: ../config.h PSTokenizer.h gtypes.h
+Stream.o: ../config.h gmem.h gfile.h gtypes.h Error.h Object.h GString.h
+Stream.o: Array.h Dict.h Stream.h Decrypt.h JBIG2Stream.h Stream-CCITT.h
+UnicodeMap.o: ../config.h gmem.h gfile.h gtypes.h GString.h GList.h Error.h
UnicodeMap.o: GlobalParams.h CharTypes.h UnicodeMap.h
-XRef.o: config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h Stream.h
-XRef.o: Lexer.h Parser.h Decrypt.h Error.h ErrorCodes.h XRef.h
-gmem.o: config.h gmem.h
+XRef.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+XRef.o: Stream.h Lexer.h Parser.h Decrypt.h Error.h ErrorCodes.h XRef.h
+gmem.o: ../config.h gmem.h
parseargs.o: parseargs.h gtypes.h
//
// Dict.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Error.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// ErrorCodes.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
#define errEncrypted 4 // file was encrypted and password was
// incorrect or not supplied
+#define errHighlightFile 5 // nonexistent or invalid highlight file
+
#endif
//
// FontEncodingTables.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// FontFile.cc
//
-// Copyright 1999-2002 Glyph & Cog, LLC
+// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
};
Type1CFontFile::Type1CFontFile(const char *fileA, int lenA) {
- Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
+ int nameIdxPos, namePos, nameLen;
- file = fileA;
+ file = (const Guchar *)fileA;
len = lenA;
name = NULL;
encoding = NULL;
+ ok = gFalse;
// some tools embed Type 1C fonts with an extra whitespace char at
// the beginning
- if (file[0] != '\x01') {
+ if (len > 0 && file[0] != '\x01') {
++file;
+ --len;
}
- // read header
- topOffSize = file[3] & 0xff;
+ // make sure the header exists
+ if (len < 4) {
+ return;
+ }
// read name index (first font only)
- nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
- idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
- idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
- name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
-
- topDictIdxPtr = getIndexEnd(nameIdxPtr);
- stringIdxPtr = getIndexEnd(topDictIdxPtr);
- gsubrIdxPtr = getIndexEnd(stringIdxPtr);
+ nameIdxPos = file[2] & 0xff;
+ if ((namePos = getIndexValPos(nameIdxPos, 0, &nameLen)) < 0) {
+ return;
+ }
+ name = new GString((char *)&file[namePos], nameLen);
+
+ topDictIdxPos = getIndexEnd(nameIdxPos);
+ stringIdxPos = getIndexEnd(topDictIdxPos);
+ gsubrIdxPos = getIndexEnd(stringIdxPos);
+
+ ok = gTrue;
}
Type1CFontFile::~Type1CFontFile() {
const char **Type1CFontFile::getEncoding() {
if (!encoding) {
- readNameAndEncoding();
+ readEncoding();
}
return (const char **)encoding;
}
-void Type1CFontFile::readNameAndEncoding() {
+void Type1CFontFile::readEncoding() {
char buf[256];
- Guchar *idxPtr0, *idxPtr1, *ptr;
+ int idxPos, idxLen, pos;
int nGlyphs;
int nCodes, nRanges, nLeft, nSups;
Gushort *glyphNames;
}
// read top dict (first font only)
- idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
- idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
+ if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
+ return;
+ }
charset = enc = charstrings = 0;
i = 0;
- ptr = idxPtr0;
- while (ptr < idxPtr1) {
- if (*ptr <= 27 || *ptr == 31) {
- key = *ptr++;
+ pos = idxPos;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
if (key == 0x0c) {
- key = (key << 8) | *ptr++;
+ if (pos >= idxPos + idxLen) {
+ return;
+ }
+ key = (key << 8) | file[pos++];
}
if (key == 0x0f) { // charset
charset = (int)op[0];
}
i = 0;
} else {
- x = getNum(&ptr, &isFP);
+ x = getNum(&pos, &isFP);
if (i < 48) {
op[i++] = x;
}
}
// get number of glyphs from charstrings index
- nGlyphs = getIndexLen((Guchar *)file + charstrings);
+ nGlyphs = getIndexLen(charstrings);
// read charset (GID -> name mapping)
glyphNames = readCharset(charset, nGlyphs);
}
}
} else {
- ptr = (Guchar *)file + enc;
- encFormat = *ptr++;
+ pos = enc;
+ if (pos < 0 || pos >= len) {
+ goto err0;
+ }
+ encFormat = file[pos++];
if ((encFormat & 0x7f) == 0) {
- nCodes = 1 + *ptr++;
+ if (pos >= len) {
+ goto err0;
+ }
+ nCodes = 1 + file[pos++];
if (nCodes > nGlyphs) {
nCodes = nGlyphs;
}
+ if (pos + nCodes - 1 > len) {
+ goto err0;
+ }
for (i = 1; i < nCodes; ++i) {
- c = *ptr++;
+ c = file[pos++];
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
encoding[c] = copyString(getString(glyphNames[i], buf));
}
} else if ((encFormat & 0x7f) == 1) {
- nRanges = *ptr++;
+ if (pos >= len) {
+ goto err0;
+ }
+ nRanges = file[pos++];
+ if (pos + 2 * nRanges > len) {
+ goto err0;
+ }
nCodes = 1;
for (i = 0; i < nRanges; ++i) {
- c = *ptr++;
- nLeft = *ptr++;
+ c = file[pos++];
+ nLeft = file[pos++];
for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
encoding[c] = copyString(getString(glyphNames[nCodes], buf));
++nCodes;
++c;
}
}
if (encFormat & 0x80) {
- nSups = *ptr++;
+ if (pos >= len) {
+ goto err0;
+ }
+ nSups = file[pos++];
+ if (pos + nSups * 3 > len) {
+ goto err0;
+ }
for (i = 0; i < nSups; ++i) {
- c = *ptr++;
- sid = getWord(ptr, 2);
- ptr += 2;
+ c = file[pos++];
+ sid = getWord(pos, 2);
+ pos += 2;
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
encoding[c] = copyString(getString(sid, buf));
}
}
}
- if (charset > 2) {
+ err0:
+ if (charset < 0 || charset > 2) {
gfree(glyphNames);
}
}
Type1CTopDict dict;
Type1CPrivateDict privateDict;
char buf[512], eBuf[256];
- Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
+ int idxPos, idxLen, pos;
int nGlyphs, nCodes, nRanges, nLeft, nSups;
Gushort *glyphNames;
- int encFormat, nSubrs, nCharStrings;
+ int encFormat, nCharStrings;
int c, sid;
- int i, j, n;
+ int i, j;
outputFunc = outputFuncA;
outputStream = outputStreamA;
// read top dict (first font only)
readTopDict(&dict);
- // get global subrs
- //~ ... global subrs are unimplemented
-
// write header and font dictionary, up to encoding
(*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
(*outputFunc)(outputStream, name->getCString(), name->getLength());
}
// get number of glyphs from charstrings index
- nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
+ nGlyphs = getIndexLen(dict.charStrings);
// read charset
glyphNames = readCharset(dict.charset, nGlyphs);
}
}
} else {
- ptr = (Guchar *)file + dict.encoding;
- encFormat = *ptr++;
+ pos = dict.encoding;
+ if (pos < 0 || pos >= len) {
+ goto err0;
+ }
+ encFormat = file[pos++];
if ((encFormat & 0x7f) == 0) {
- nCodes = 1 + *ptr++;
+ if (pos >= len) {
+ goto err0;
+ }
+ nCodes = 1 + file[pos++];
if (nCodes > nGlyphs) {
nCodes = nGlyphs;
}
+ if (pos + nCodes - 1 > len) {
+ goto err0;
+ }
for (i = 1; i < nCodes; ++i) {
- c = *ptr++;
+ c = file[pos++];
sprintf(buf, "dup %d /", c);
(*outputFunc)(outputStream, buf, strlen(buf));
getString(glyphNames[i], buf);
(*outputFunc)(outputStream, " put\n", 5);
}
} else if ((encFormat & 0x7f) == 1) {
- nRanges = *ptr++;
+ if (pos >= len) {
+ goto err0;
+ }
+ nRanges = file[pos++];
+ if (pos + 2 * nRanges > len) {
+ goto err0;
+ }
nCodes = 1;
for (i = 0; i < nRanges; ++i) {
- c = *ptr++;
- nLeft = *ptr++;
+ c = file[pos++];
+ nLeft = file[pos++];
for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
sprintf(buf, "dup %d /", c);
(*outputFunc)(outputStream, buf, strlen(buf));
}
}
if (encFormat & 0x80) {
- nSups = *ptr++;
+ if (pos >= len) {
+ goto err0;
+ }
+ nSups = file[pos++];
+ if (pos + nSups * 3 > len) {
+ goto err0;
+ }
for (i = 0; i < nSups; ++i) {
- c = *ptr++;
- sid = getWord(ptr, 2);
- ptr += 2;
+ c = file[pos++];
+ sid = getWord(pos, 2);
+ pos += 2;
sprintf(buf, "dup %d /", c);
(*outputFunc)(outputStream, buf, strlen(buf));
getString(sid, buf);
(*outputFunc)(outputStream, " put\n", 5);
}
}
+ err0:;
}
(*outputFunc)(outputStream, "readonly def\n", 13);
}
nominalWidthX = privateDict.nominalWidthX;
nominalWidthXFP = privateDict.nominalWidthXFP;
- // get subrs
- if (privateDict.subrsOffset != 0) {
- subrsIdxPtr = (Guchar *)file + dict.privateOffset +
- privateDict.subrsOffset;
- nSubrs = getIndexLen(subrsIdxPtr);
- sprintf(eBuf, "/Subrs %d array\n", nSubrs);
- eexecWrite(eBuf);
- idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
- for (i = 0; i < nSubrs; ++i) {
- idxPtr0 = idxPtr1;
- idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
- n = idxPtr1 - idxPtr0;
-#if 1 //~ Type 2 subrs are unimplemented
- error(-1, "Unimplemented Type 2 subrs");
-#else
- sprintf(eBuf, "dup %d %d RD ", i, n);
- eexecWrite(eBuf);
- eexecCvtGlyph(idxPtr0, n);
- eexecWrite(" NP\n");
-#endif
- }
- eexecWrite("ND\n");
- }
+ // set up subroutines
+ subrIdxPos = dict.privateOffset + privateDict.subrsOffset;
+ i = getIndexLen(gsubrIdxPos);
+ gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+ i = getIndexLen(subrIdxPos);
+ subrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
// get CharStrings
- charStringsIdxPtr = (Guchar *)file + dict.charStrings;
- nCharStrings = getIndexLen(charStringsIdxPtr);
+ nCharStrings = getIndexLen(dict.charStrings);
sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
eexecWrite(eBuf);
- idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
for (i = 0; i < nCharStrings; ++i) {
- idxPtr0 = idxPtr1;
- idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
- n = idxPtr1 - idxPtr0;
- eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
+ if ((idxPos = getIndexValPos(dict.charStrings, i, &idxLen)) >= 0) {
+ eexecCvtGlyph(getString(glyphNames[i], buf), idxPos, idxLen);
+ }
}
eexecWrite("end\n");
eexecWrite("end\n");
Gushort *charset;
int *cidMap;
Guchar *fdSelect;
- Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
+ int idxPos, idxLen, pos;
char buf[512], buf2[16];
int nGlyphs, nCIDs, gdBytes, nFDs;
int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
privateDicts[0].nominalWidthX = 0;
privateDicts[0].nominalWidthXFP = gFalse;
} else {
- fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
- nFDs = getIndexLen(fdArrayIdx);
+ if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
+ goto err0;
+ }
privateDicts = (Type1CPrivateDict *)
gmalloc(nFDs * sizeof(Type1CPrivateDict));
- idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
for (i = 0; i < nFDs; ++i) {
privateDicts[i].dictData = NULL;
- idxPtr0 = idxPtr1;
- idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
- ptr = idxPtr0;
+ }
+ for (i = 0; i < nFDs; ++i) {
+ privateDicts[i].dictData = NULL;
+ if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
+ goto err1;
+ }
+ pos = idxPos;
j = 0;
- while (ptr < idxPtr1) {
- if (*ptr <= 27 || *ptr == 31) {
- key = *ptr++;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
if (key == 0x0c) {
- key = (key << 8) | *ptr++;
+ if (pos >= idxPos + idxLen) {
+ goto err1;
+ }
+ key = (key << 8) | file[pos++];
}
if (key == 0x0012) {
readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
}
j = 0;
} else {
- x = getNum(&ptr, &isFP);
+ x = getNum(&pos, &isFP);
if (j < 48) {
op[j] = x;
fp[j++] = isFP;
}
// get the glyph count
- charStringsIdxPtr = (Guchar *)file + dict.charStrings;
- nGlyphs = getIndexLen(charStringsIdxPtr);
+ if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
+ goto err1;
+ }
// read the FDSelect table
fdSelect = (Guchar *)gmalloc(nGlyphs);
fdSelect[i] = 0;
}
} else {
- ptr = (Guchar *)file + dict.fdSelectOffset;
- fdSelectFmt = *ptr++;
+ pos = dict.fdSelectOffset;
+ if (pos < 0 || pos >= len) {
+ goto err2;
+ }
+ fdSelectFmt = file[pos++];
if (fdSelectFmt == 0) {
- memcpy(fdSelect, ptr, nGlyphs);
+ if (pos + nGlyphs > len) {
+ goto err2;
+ }
+ memcpy(fdSelect, file + pos, nGlyphs);
} else if (fdSelectFmt == 3) {
- nRanges = getWord(ptr, 2);
- ptr += 2;
- gid0 = getWord(ptr, 2);
- ptr += 2;
+ if (pos + 4 > len) {
+ goto err2;
+ }
+ nRanges = getWord(pos, 2);
+ pos += 2;
+ gid0 = getWord(pos, 2);
+ pos += 2;
+ if (pos + nRanges * 3 > len) {
+ goto err2;
+ }
for (i = 1; i <= nRanges; ++i) {
- fd = *ptr++;
- gid1 = getWord(ptr, 2);
- ptr += 2;
+ fd = file[pos++];
+ gid1 = getWord(pos, 2);
+ pos += 2;
for (j = gid0; j < gid1; ++j) {
fdSelect[j] = fd;
}
cidMap[charset[i]] = i;
}
+ // set up global subroutines
+ i = getIndexLen(gsubrIdxPos);
+ gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+
// build the charstrings
charStrings = new GString();
charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
for (i = 0; i < nCIDs; ++i) {
charStringOffsets[i] = charStrings->getLength();
if (cidMap[i] >= 0) {
- idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
- idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
- n = idxPtr1 - idxPtr0;
- j = fdSelect[cidMap[i]];
- defaultWidthX = privateDicts[j].defaultWidthX;
- defaultWidthXFP = privateDicts[j].defaultWidthXFP;
- nominalWidthX = privateDicts[j].nominalWidthX;
- nominalWidthXFP = privateDicts[j].nominalWidthXFP;
- cvtGlyph(idxPtr0, n);
- charStrings->append(charBuf);
- delete charBuf;
+ if ((idxPos = getIndexValPos(dict.charStrings,
+ cidMap[i], &idxLen)) >= 0) {
+ j = fdSelect[cidMap[i]];
+ defaultWidthX = privateDicts[j].defaultWidthX;
+ defaultWidthXFP = privateDicts[j].defaultWidthXFP;
+ nominalWidthX = privateDicts[j].nominalWidthX;
+ nominalWidthXFP = privateDicts[j].nominalWidthXFP;
+ subrIdxPos = dict.privateOffset + privateDicts[j].subrsOffset;
+ k = getIndexLen(subrIdxPos);
+ subrBias = (k < 1240) ? 107 : (k < 33900) ? 1131 : 32768;
+ cvtGlyph(idxPos, idxLen, gTrue);
+ charStrings->append(charBuf);
+ delete charBuf;
+ }
}
}
charStringOffsets[nCIDs] = charStrings->getLength();
}
(*outputFunc)(outputStream, "def\n", 4);
- //~ need to deal with subrs
-
// start the binary section
offset = (nCIDs + 1) * (1 + gdBytes);
sprintf(buf, "(Hex) %d StartData\n",
(*outputFunc)(outputStream, "\n", 1);
}
- for (i = 0; i < nFDs; ++i) {
- delete privateDicts[i].dictData;
- }
- gfree(privateDicts);
- gfree(cidMap);
- gfree(charset);
gfree(charStringOffsets);
delete charStrings;
+ gfree(cidMap);
+ gfree(charset);
+ err2:
gfree(fdSelect);
+ err1:
+ for (i = 0; i < nFDs; ++i) {
+ if (privateDicts[i].dictData) {
+ delete privateDicts[i].dictData;
+ }
+ }
+ gfree(privateDicts);
+ err0:;
}
void Type1CFontFile::convertToType0(const char *psName,
Gushort *charset;
int *cidMap;
Guchar *fdSelect;
- Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
+ int idxPos, idxLen, pos;
char buf[512];
char eBuf[256];
int nGlyphs, nCIDs, nFDs;
int key;
double x;
GBool isFP;
- int i, j, n;
+ int i, j;
outputFunc = outputFuncA;
outputStream = outputStreamA;
privateDicts[0].nominalWidthX = 0;
privateDicts[0].nominalWidthXFP = gFalse;
} else {
- fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
- nFDs = getIndexLen(fdArrayIdx);
+ if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
+ goto err0;
+ }
privateDicts = (Type1CPrivateDict *)
gmalloc(nFDs * sizeof(Type1CPrivateDict));
- idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
for (i = 0; i < nFDs; ++i) {
privateDicts[i].dictData = NULL;
- idxPtr0 = idxPtr1;
- idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
- ptr = idxPtr0;
+ }
+ for (i = 0; i < nFDs; ++i) {
+ privateDicts[i].dictData = NULL;
+ if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
+ goto err1;
+ }
+ pos = idxPos;
j = 0;
- while (ptr < idxPtr1) {
- if (*ptr <= 27 || *ptr == 31) {
- key = *ptr++;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
if (key == 0x0c) {
- key = (key << 8) | *ptr++;
+ if (pos >= idxPos + idxLen) {
+ goto err1;
+ }
+ key = (key << 8) | file[pos++];
}
if (key == 0x0012) {
readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
}
j = 0;
} else {
- x = getNum(&ptr, &isFP);
+ x = getNum(&pos, &isFP);
if (j < 48) {
op[j] = x;
fp[j++] = isFP;
}
// get the glyph count
- charStringsIdxPtr = (Guchar *)file + dict.charStrings;
- nGlyphs = getIndexLen(charStringsIdxPtr);
+ if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
+ goto err1;
+ }
// read the FDSelect table
fdSelect = (Guchar *)gmalloc(nGlyphs);
fdSelect[i] = 0;
}
} else {
- ptr = (Guchar *)file + dict.fdSelectOffset;
- fdSelectFmt = *ptr++;
+ pos = dict.fdSelectOffset;
+ if (pos < 0 || pos >= len) {
+ goto err2;
+ }
+ fdSelectFmt = file[pos++];
if (fdSelectFmt == 0) {
- memcpy(fdSelect, ptr, nGlyphs);
+ if (pos + nGlyphs > len) {
+ goto err2;
+ }
+ memcpy(fdSelect, file + pos, nGlyphs);
} else if (fdSelectFmt == 3) {
- nRanges = getWord(ptr, 2);
- ptr += 2;
- gid0 = getWord(ptr, 2);
- ptr += 2;
+ if (pos + 4 > len) {
+ goto err2;
+ }
+ nRanges = getWord(pos, 2);
+ pos += 2;
+ gid0 = getWord(pos, 2);
+ pos += 2;
+ if (pos + nRanges * 3 > len) {
+ goto err2;
+ }
for (i = 1; i <= nRanges; ++i) {
- fd = *ptr++;
- gid1 = getWord(ptr, 2);
- ptr += 2;
+ fd = file[pos++];
+ gid1 = getWord(pos, 2);
+ pos += 2;
for (j = gid0; j < gid1; ++j) {
fdSelect[j] = fd;
}
cidMap[charset[i]] = i;
}
+ // set up global subroutines
+ i = getIndexLen(gsubrIdxPos);
+ gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+
// write the descendant Type 1 fonts
for (i = 0; i < nCIDs; i += 256) {
nominalWidthX = privateDicts[fd].nominalWidthX;
nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
+ // set up the subroutines
+ subrIdxPos = dict.privateOffset + privateDicts[fd].subrsOffset;
+ j = getIndexLen(subrIdxPos);
+ subrBias = (j < 1240) ? 107 : (j < 33900) ? 1131 : 32768;
+
// start the CharStrings
sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
eexecWrite(eBuf);
// write the .notdef CharString
- idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
- idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
- n = idxPtr1 - idxPtr0;
- eexecCvtGlyph(".notdef", idxPtr0, n);
+ if ((idxPos = getIndexValPos(dict.charStrings, 0, &idxLen)) >= 0) {
+ eexecCvtGlyph(".notdef", idxPos, idxLen);
+ }
// write the CharStrings
for (j = 0; j < 256 && i+j < nCIDs; ++j) {
if (cidMap[i+j] >= 0) {
- idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
- idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
- n = idxPtr1 - idxPtr0;
- sprintf(buf, "c%02x", j);
- eexecCvtGlyph(buf, idxPtr0, n);
+ if ((idxPos = getIndexValPos(dict.charStrings,
+ cidMap[i+j], &idxLen)) >= 0) {
+ sprintf(buf, "c%02x", j);
+ eexecCvtGlyph(buf, idxPos, idxLen);
+ }
}
}
eexecWrite("end\n");
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
// clean up
- for (i = 0; i < nFDs; ++i) {
- delete privateDicts[i].dictData;
- }
- gfree(privateDicts);
gfree(cidMap);
gfree(charset);
+ err2:
gfree(fdSelect);
+ err1:
+ for (i = 0; i < nFDs; ++i) {
+ if (privateDicts[i].dictData) {
+ delete privateDicts[i].dictData;
+ }
+ }
+ gfree(privateDicts);
+ err0:;
}
void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
- Guchar *idxPtr0, *idxPtr1, *ptr;
+ int idxPos, idxLen, pos;
double x;
GBool isFP;
int key;
int i;
- idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
- idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
dict->version = 0;
dict->notice = 0;
dict->copyright = 0;
dict->supplement = 0;
dict->fdArrayOffset = 0;
dict->fdSelectOffset = 0;
+ if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
+ return;
+ }
i = 0;
- ptr = idxPtr0;
- while (ptr < idxPtr1) {
- if (*ptr <= 27 || *ptr == 31) {
- key = *ptr++;
+ pos = idxPos;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
if (key == 0x0c) {
- key = (key << 8) | *ptr++;
+ if (pos >= idxPos + idxLen) {
+ break;
+ }
+ key = (key << 8) | file[pos++];
}
switch (key) {
case 0x0000: dict->version = (int)op[0]; break;
}
i = 0;
} else {
- x = getNum(&ptr, &isFP);
+ x = getNum(&pos, &isFP);
if (i < 48) {
op[i] = x;
fp[i++] = isFP;
void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
int offset, int size) {
- Guchar *idxPtr0, *idxPtr1, *ptr;
+ int pos;
char eBuf[256];
int key;
double x;
privateDict->defaultWidthXFP = gFalse;
privateDict->nominalWidthX = 0;
privateDict->nominalWidthXFP = gFalse;
- idxPtr0 = (Guchar *)file + offset;
- idxPtr1 = idxPtr0 + size;
- ptr = idxPtr0;
+ if (offset < 0 || offset + size > len) {
+ return;
+ }
+ pos = offset;
i = 0;
- while (ptr < idxPtr1) {
- if (*ptr <= 27 || *ptr == 31) {
- key = *ptr++;
+ while (pos < offset + size) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
if (key == 0x0c) {
- key = (key << 8) | *ptr++;
+ if (pos >= offset + size) {
+ break;
+ }
+ key = (key << 8) | file[pos++];
}
switch (key) {
case 0x0006:
}
i = 0;
} else {
- x = getNum(&ptr, &isFP);
+ x = getNum(&pos, &isFP);
if (i < 48) {
op[i] = x;
fp[i++] = isFP;
Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
Gushort *glyphNames;
- Guchar *ptr;
+ int pos;
int charsetFormat, c;
int nLeft, i, j;
glyphNames = type1CExpertSubsetCharset;
} else {
glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
- glyphNames[0] = 0;
- ptr = (Guchar *)file + charset;
- charsetFormat = *ptr++;
+ for (i = 0; i < nGlyphs; ++i) {
+ glyphNames[i] = 0;
+ }
+ pos = charset;
+ if (pos < 0 || pos >= len) {
+ goto err0;
+ }
+ charsetFormat = file[pos++];
if (charsetFormat == 0) {
+ if (pos + (nGlyphs - 1) * 2 >= len) {
+ goto err0;
+ }
for (i = 1; i < nGlyphs; ++i) {
- glyphNames[i] = getWord(ptr, 2);
- ptr += 2;
+ glyphNames[i] = getWord(pos, 2);
+ pos += 2;
}
} else if (charsetFormat == 1) {
i = 1;
while (i < nGlyphs) {
- c = getWord(ptr, 2);
- ptr += 2;
- nLeft = *ptr++;
+ if (pos + 3 > len) {
+ goto err0;
+ }
+ c = getWord(pos, 2);
+ pos += 2;
+ nLeft = file[pos++];
for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
glyphNames[i++] = c++;
}
} else if (charsetFormat == 2) {
i = 1;
while (i < nGlyphs) {
- c = getWord(ptr, 2);
- ptr += 2;
- nLeft = getWord(ptr, 2);
- ptr += 2;
+ if (pos + 4 > len) {
+ goto err0;
+ }
+ c = getWord(pos, 2);
+ pos += 2;
+ nLeft = getWord(pos, 2);
+ pos += 2;
for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
glyphNames[i++] = c++;
}
}
}
}
+ err0:
return glyphNames;
}
}
}
-void Type1CFontFile::eexecCvtGlyph(const char *glyphName, Guchar *s, int n) {
+void Type1CFontFile::eexecCvtGlyph(const char *glyphName, int pos, int n) {
char eBuf[256];
- cvtGlyph(s, n);
+ cvtGlyph(pos, n, gTrue);
sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
eexecWrite(eBuf);
eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
delete charBuf;
}
-void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
- int nHints;
+void Type1CFontFile::cvtGlyph(int pos, int n, GBool top) {
int x;
- GBool first = gTrue;
+ int subrPos, subrLen;
double d, dx, dy;
GBool dFP;
Gushort r2;
Guchar byte;
int i, k;
- charBuf = new GString();
- charBuf->append((char)73);
- charBuf->append((char)58);
- charBuf->append((char)147);
- charBuf->append((char)134);
+ if (pos < 0 || pos + n > len) {
+ return;
+ }
+
+ if (top) {
+ charBuf = new GString();
+ charBuf->append((char)73);
+ charBuf->append((char)58);
+ charBuf->append((char)147);
+ charBuf->append((char)134);
+ nOps = 0;
+ nHints = 0;
+ firstOp = gTrue;
+ }
- i = 0;
- nOps = 0;
- nHints = 0;
- while (i < n) {
- if (s[i] == 12) {
- switch (s[i+1]) {
+ i = pos;
+ while (i < pos + n) {
+ if (file[i] == 12) {
+ if (i + 2 > pos + n) {
+ break;
+ }
+ switch (file[i+1]) {
case 0: // dotsection (should be Type 1 only?)
// ignored
break;
case 28: // exch
case 29: // index
case 30: // roll
- error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
+ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
break;
default:
- error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
+ error(-1, "Illegal Type 2 charstring op: 12.%d", file[i+1]);
break;
}
i += 2;
nOps = 0;
- } else if (s[i] == 19) { // hintmask
+ } else if (file[i] == 19) { // hintmask
// ignored
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps == 1);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps > 0) {
if (nOps & 1) {
}
i += 1 + ((nHints + 7) >> 3);
nOps = 0;
- } else if (s[i] == 20) { // cntrmask
+ } else if (file[i] == 20) { // cntrmask
// ignored
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps == 1);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps > 0) {
if (nOps & 1) {
}
i += 1 + ((nHints + 7) >> 3);
nOps = 0;
- } else if (s[i] == 28) {
- x = (s[i+1] << 8) + s[i+2];
+ } else if (file[i] == 28) {
+ if (i + 3 > len) {
+ break;
+ }
+ x = (file[i+1] << 8) + file[i+2];
if (x & 0x8000) {
x |= -1 << 15;
}
op[nOps++] = x;
}
i += 3;
- } else if (s[i] <= 31) {
- switch (s[i]) {
+ } else if (file[i] == 10) { // callsubr
+ if (nOps >= 1) {
+ k = subrBias + (int)op[nOps - 1];
+ --nOps;
+ if ((subrPos = getIndexValPos(subrIdxPos, k, &subrLen)) >= 0) {
+ cvtGlyph(subrPos, subrLen, gFalse);
+ }
+ } else {
+ error(-1, "Too few args to Type 2 callsubr");
+ }
+ // don't clear the stack
+ ++i;
+ } else if (file[i] == 29) { // callgsubr
+ if (nOps >= 1) {
+ k = gsubrBias + (int)op[nOps - 1];
+ --nOps;
+ if ((subrPos = getIndexValPos(gsubrIdxPos, k, &subrLen)) >= 0) {
+ cvtGlyph(subrPos, subrLen, gFalse);
+ }
+ } else {
+ error(-1, "Too few args to Type 2 callgsubr");
+ }
+ // don't clear the stack
+ ++i;
+ } else if (file[i] == 11) { // return
+ // don't clear the stack
+ ++i;
+ } else if (file[i] <= 31) {
+ switch (file[i]) {
case 4: // vmoveto
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps == 2);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps != 1) {
error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
}
break;
case 14: // endchar / seac
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps == 1 || nOps == 5);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps == 4) {
eexecDumpNum(0, 0);
}
break;
case 21: // rmoveto
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps == 3);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps != 2) {
error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
eexecDumpOp1(21);
break;
case 22: // hmoveto
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps == 2);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps != 1) {
error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
}
break;
case 1: // hstem
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps & 1);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps & 1) {
error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
nHints += nOps / 2;
break;
case 3: // vstem
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps & 1);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps & 1) {
error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
break;
case 18: // hstemhm
// ignored
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps & 1);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps & 1) {
error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
break;
case 23: // vstemhm
// ignored
- if (first) {
+ if (firstOp) {
cvtGlyphWidth(nOps & 1);
- first = gFalse;
+ firstOp = gFalse;
}
if (nOps & 1) {
error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
}
nHints += nOps / 2;
break;
- case 10: // callsubr
- case 11: // return
case 16: // blend
- case 29: // callgsubr
- error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
+ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
break;
default:
- error(-1, "Illegal Type 2 charstring op: %d", s[i]);
+ error(-1, "Illegal Type 2 charstring op: %d", file[i]);
break;
}
++i;
nOps = 0;
- } else if (s[i] <= 246) {
+ } else if (file[i] <= 246) {
if (nOps < 48) {
fp[nOps] = gFalse;
- op[nOps++] = (int)s[i] - 139;
+ op[nOps++] = (int)file[i] - 139;
}
++i;
- } else if (s[i] <= 250) {
+ } else if (file[i] <= 250) {
+ if (i + 2 > len) {
+ break;
+ }
if (nOps < 48) {
fp[nOps] = gFalse;
- op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
+ op[nOps++] = (((int)file[i] - 247) << 8) + (int)file[i+1] + 108;
}
i += 2;
- } else if (s[i] <= 254) {
+ } else if (file[i] <= 254) {
+ if (i + 2 > len) {
+ break;
+ }
if (nOps < 48) {
fp[nOps] = gFalse;
- op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
+ op[nOps++] = -(((int)file[i] - 251) << 8) - (int)file[i+1] - 108;
}
i += 2;
} else {
- x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
- if (x & 0x80000000)
+ if (i + 5 > len) {
+ break;
+ }
+ x = (file[i+1] << 24) | (file[i+2] << 16) | (file[i+3] << 8) | file[i+4];
+ if (x & 0x80000000) {
x |= -1 << 31;
+ }
if (nOps < 48) {
fp[nOps] = gTrue;
op[nOps++] = (double)x / 65536.0;
}
// charstring encryption
- r2 = 4330;
- for (i = 0; i < charBuf->getLength(); ++i) {
- byte = charBuf->getChar(i) ^ (r2 >> 8);
- charBuf->setChar(i, byte);
- r2 = (byte + r2) * 52845 + 22719;
+ if (top) {
+ r2 = 4330;
+ for (i = 0; i < charBuf->getLength(); ++i) {
+ byte = charBuf->getChar(i) ^ (r2 >> 8);
+ charBuf->setChar(i, byte);
+ r2 = (byte + r2) * 52845 + 22719;
+ }
}
}
sprintf(buf, "] def\n");
}
-int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
- return (int)getWord(indexPtr, 2);
+int Type1CFontFile::getIndexLen(int indexPos) {
+ if (indexPos + 2 > len) {
+ return -1;
+ }
+ return (int)getWord(indexPos, 2);
}
-Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
- int n, offSize;
- Guchar *idxStartPtr;
+int Type1CFontFile::getIndexValPos(int indexPos, int i, int *valLen) {
+ int n, offSize, idxStartPos;
+ int pos0, pos1;
- n = (int)getWord(indexPtr, 2);
- offSize = indexPtr[2];
- idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
- return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
+ if (indexPos < 0 || indexPos + 3 > len) {
+ return -1;
+ }
+ n = (int)getWord(indexPos, 2);
+ if (i >= n) {
+ return -1;
+ }
+ offSize = file[indexPos + 2];
+ if (offSize < 1 || offSize > 4) {
+ return -1;
+ }
+ idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
+ if (idxStartPos >= len) {
+ return -1;
+ }
+ pos0 = idxStartPos + getWord(indexPos + 3 + i * offSize, offSize);
+ pos1 = idxStartPos + getWord(indexPos + 3 + (i + 1) * offSize, offSize);
+ if (pos0 < 0 || pos0 >= len || pos1 < pos0 || pos1 > len) {
+ return -1;
+ }
+ *valLen = pos1 - pos0;
+ return pos0;
}
-Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
- int n, offSize;
- Guchar *idxStartPtr;
+int Type1CFontFile::getIndexEnd(int indexPos) {
+ int n, offSize, idxStartPos;
- n = (int)getWord(indexPtr, 2);
- offSize = indexPtr[2];
- idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
- return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
+ if (indexPos + 3 > len) {
+ return -1;
+ }
+ n = (int)getWord(indexPos, 2);
+ offSize = file[indexPos + 2];
+ idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
+ if (idxStartPos >= len) {
+ return -1;
+ }
+ return idxStartPos + getWord(indexPos + 3 + n * offSize, offSize);
}
-Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
+Guint Type1CFontFile::getWord(int pos, int size) {
Guint x;
int i;
+ if (pos < 0 || pos + size > len) {
+ return 0;
+ }
x = 0;
for (i = 0; i < size; ++i) {
- x = (x << 8) + *ptr++;
+ x = (x << 8) + file[pos + i];
}
return x;
}
-double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
+double Type1CFontFile::getNum(int *pos, GBool *isFP) {
static char nybChars[16] = "0123456789.ee -";
int b0, b, nyb0, nyb1;
double x;
x = 0;
*isFP = gFalse;
- b0 = (*ptr)[0];
+ if (*pos >= len) {
+ return 0;
+ }
+ b0 = file[*pos];
if (b0 < 28) {
x = 0;
} else if (b0 == 28) {
- x = ((*ptr)[1] << 8) + (*ptr)[2];
- *ptr += 3;
+ if (*pos + 3 <= len) {
+ x = (file[*pos + 1] << 8) + file[*pos + 2];
+ *pos += 3;
+ }
} else if (b0 == 29) {
- x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
- *ptr += 5;
+ if (*pos + 5 <= len) {
+ x = (file[*pos + 1] << 24) + (file[*pos + 2] << 16) +
+ (file[*pos + 3] << 8) + file[*pos + 4];
+ *pos += 5;
+ }
} else if (b0 == 30) {
- *ptr += 1;
+ *pos += 1;
i = 0;
do {
- b = *(*ptr)++;
+ if (*pos >= len) {
+ break;
+ }
+ b = file[(*pos)++];
nyb0 = b >> 4;
nyb1 = b & 0x0f;
if (nyb0 == 0xf) {
x = 0;
} else if (b0 < 247) {
x = b0 - 139;
- *ptr += 1;
+ *pos += 1;
} else if (b0 < 251) {
- x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
- *ptr += 2;
+ if (*pos + 2 <= len) {
+ x = ((b0 - 247) << 8) + file[*pos + 1] + 108;
+ *pos += 2;
+ }
} else {
- x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
- *ptr += 2;
+ if (*pos + 2 <= len) {
+ x = -((b0 - 251) << 8) - file[*pos + 1] - 108;
+ *pos += 2;
+ }
}
return x;
}
char *Type1CFontFile::getString(int sid, char *buf) {
- Guchar *idxPtr0, *idxPtr1;
- int n;
+ int idxPos, n;
if (sid < 391) {
strcpy(buf, type1CStdStrings[sid]);
} else {
sid -= 391;
- idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
- idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
- if ((n = idxPtr1 - idxPtr0) > 255) {
- n = 255;
+ idxPos = getIndexValPos(stringIdxPos, sid, &n);
+ if (idxPos < 0 || n < 0 || n > 255 || idxPos + n > len) {
+ buf[0] = '\0';
+ } else {
+ strncpy(buf, (char *)&file[idxPos], n);
+ buf[n] = '\0';
}
- strncpy(buf, (char *)idxPtr0, n);
- buf[n] = '\0';
}
return buf;
}
tableHdrs[i].checksum = getULong(pos+4);
tableHdrs[i].offset = getULong(pos+8);
tableHdrs[i].length = getULong(pos+12);
+ if (tableHdrs[i].offset + tableHdrs[i].length < tableHdrs[i].offset ||
+ tableHdrs[i].offset + tableHdrs[i].length > (Guint)len) {
+ tableHdrs[i].offset = (Guint)-1;
+ }
pos += 16;
}
const char **TrueTypeFontFile::getEncoding() {
int cmap[256];
int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
- int cmapLen, cmapOffset, cmapFirst;
- int segCnt, segStart, segEnd, segDelta, segOffset;
- int pos, i, j, k;
+ int pos, i, j;
Guint fmt;
GString *s;
int stringIdx, stringPos, n;
// if the font has a Windows-symbol cmap, use it;
// otherwise, use the first cmap in the table
+ cmapPlatform = 0; // make gcc happy
+ cmapEncoding = 0; // make gcc happy
for (i = 0; i < nCmaps; ++i) {
cmapPlatform = getUShort(pos + 4 + 8*i);
cmapEncoding = getUShort(pos + 4 + 8*i + 2);
// read the cmap
cmapFmt = getUShort(pos);
- switch (cmapFmt) {
- case 0: // byte encoding table (Apple standard)
- cmapLen = getUShort(pos + 2);
- for (i = 0; i < cmapLen && i < 256; ++i) {
- cmap[i] = getByte(pos + 6 + i);
- }
- break;
- case 4: // segment mapping to delta values (Microsoft standard)
- if (cmapPlatform == 3 && cmapEncoding == 0) {
- // Windows-symbol uses char codes 0xf000 - 0xf0ff
- cmapOffset = 0xf000;
- } else {
- cmapOffset = 0;
- }
- segCnt = getUShort(pos + 6) / 2;
- for (i = 0; i < segCnt; ++i) {
- segEnd = getUShort(pos + 14 + 2*i);
- segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
- segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
- segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
- if (segStart - cmapOffset <= 0xff &&
- segEnd - cmapOffset >= 0) {
- for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
- j <= segEnd && j - cmapOffset <= 0xff;
- ++j) {
- if (segOffset == 0) {
- k = (j + segDelta) & 0xffff;
- } else {
- k = getUShort(pos + 16 + 6*segCnt + 2*i +
- segOffset + 2 * (j - segStart));
- if (k != 0) {
- k = (k + segDelta) & 0xffff;
- }
- }
- cmap[j - cmapOffset] = k;
- }
+ for (i = 0; i < 256; ++i) {
+ cmap[i] = getCmapEntry(cmapFmt, pos, i);
+ }
+ // Windows-symbol sometimes uses char codes 0xf000 - 0xf0ff, so
+ // we use these to override 0x0000 - 0x00ff
+ if (cmapPlatform == 3 && cmapEncoding == 0) {
+ for (i = 0; i < 256; ++i) {
+ if ((j = getCmapEntry(cmapFmt, pos, 0xf000 + i)) != 0) {
+ cmap[i] = j;
}
}
- break;
- case 6: // trimmed table mapping
- cmapFirst = getUShort(pos + 6);
- cmapLen = getUShort(pos + 8);
- for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
- cmap[i] = getUShort(pos + 10 + 2*i);
- }
- break;
- default:
- error(-1, "Unimplemented cmap format (%d) in TrueType font file",
- cmapFmt);
- break;
}
}
++stringIdx, stringPos += 1 + getByte(stringPos)) ;
}
n = getByte(stringPos);
- s = new GString(file + stringPos + 1, n);
- encoding[i] = copyString(s->getCString());
- delete s;
+ if (stringPos >= 0 && stringPos + 1 + n <= len) {
+ s = new GString(file + stringPos + 1, n);
+ encoding[i] = copyString(s->getCString());
+ delete s;
+ } else {
+ encoding[i] = copyString(macGlyphNames[0]);
+ }
++stringIdx;
stringPos += 1 + n;
}
void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
CharCodeToUnicode *toUnicode,
GBool pdfFontHasEncoding,
+ GBool pdfFontIsSymbolic,
FontFileOutputFunc outputFunc,
void *outputStream) {
char buf[512];
// write the guts of the dictionary
cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
- cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
+ cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding, pdfFontIsSymbolic,
outputFunc, outputStream);
cvtSfnts(outputFunc, outputStream, NULL);
for (i = 0; i < nTables; ++i) {
if (!strncmp(tableHdrs[i].tag, tag, 4)) {
- return tableHdrs[i].offset;
+ return (int)tableHdrs[i].offset;
}
}
return -1;
for (i = 0; i < nTables; ++i) {
if (!strncmp(tableHdrs[i].tag, tag, 4)) {
+ if (tableHdrs[i].offset == (Guint)-1) {
+ return -1;
+ }
return i;
}
}
void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
CharCodeToUnicode *toUnicode,
GBool pdfFontHasEncoding,
+ GBool pdfFontIsSymbolic,
FontFileOutputFunc outputFunc,
void *outputStream) {
int unicodeCmap, macRomanCmap, msSymbolCmap;
// 1. If the PDF font has an encoding:
// 1a. If the TrueType font has a Microsoft Unicode cmap, use it,
// and use the Unicode indexes, not the char codes.
- // 1b. If the TrueType font has a Macintosh Roman cmap, use it,
+ // 1b. If the PDF font is symbolic and the TrueType font has a
+ // Microsoft Symbol cmap, use it, and use (0xf000 + char code).
+ // 1c. If the TrueType font has a Macintosh Roman cmap, use it,
// and reverse map the char names through MacRomanEncoding to
// get char codes.
// 2. If the PDF font does not have an encoding:
for (i = 0; i < nCmaps; ++i) {
cmapPlatform = getUShort(pos + 4 + 8*i);
cmapEncoding = getUShort(pos + 4 + 8*i + 2);
- if (cmapPlatform == 3 && cmapEncoding == 1) {
+ if ((cmapPlatform == 3 && cmapEncoding == 1) || cmapPlatform == 0) {
unicodeCmap = i;
} else if (cmapPlatform == 1 && cmapEncoding == 0) {
macRomanCmap = i;
if (unicodeCmap >= 0) {
i = unicodeCmap;
mode = t42FontModeUnicode;
+ } else if (pdfFontIsSymbolic && msSymbolCmap >= 0) {
+ i = msSymbolCmap;
+ mode = t42FontModeCharCodeOffset;
+ cmapOffset = 0xf000;
} else if (macRomanCmap >= 0) {
i = macRomanCmap;
mode = t42FontModeMacRoman;
// map char name to glyph index:
// 1. use encoding to map name to char code
// 2. use cmap to map char code to glyph index
- j = 0; // make gcc happy
- for (i = 0; i < 256; ++i) {
+ // N.B. We do this in reverse order because font subsets can have
+ // weird encodings that use the same character name twice, and
+ // the first definition is probably the one we want.
+ k = 0; // make gcc happy
+ for (i = 255; i >= 0; --i) {
if (pdfFontHasEncoding) {
name = encodingA[i];
} else {
switch (mode) {
case t42FontModeUnicode:
toUnicode->mapToUnicode((CharCode)i, &u, 1);
- j = (int)u;
+ k = getCmapEntry(cmapFmt, pos, (int)u);
break;
case t42FontModeCharCode:
- j = i;
+ k = getCmapEntry(cmapFmt, pos, i);
break;
case t42FontModeCharCodeOffset:
- j = cmapOffset + i;
+ if ((k = getCmapEntry(cmapFmt, pos, cmapOffset + i)) == 0) {
+ k = getCmapEntry(cmapFmt, pos, i);
+ }
break;
case t42FontModeMacRoman:
j = globalParams->getMacRomanCharCode(name);
+ k = getCmapEntry(cmapFmt, pos, j);
break;
}
// note: Distiller (maybe Adobe's PS interpreter in general)
// doesn't like TrueType fonts that have CharStrings entries
// which point to nonexistent glyphs, hence the (k < nGlyphs)
// test
- if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
- k < nGlyphs) {
+ if (k > 0 && k < nGlyphs) {
(*outputFunc)(outputStream, "/", 1);
(*outputFunc)(outputStream, name, strlen(name));
sprintf(buf, " %d def\n", k);
segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
+ if (code < segStart) {
+ return 0;
+ }
if (segOffset == 0) {
i = (code + segDelta) & 0xffff;
} else {
memcpy(headTable, file + seekTable("head"), 54);
headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
- // read the original 'loca' table and construct the new one,
- // padding each glyph out to a multiple of 4 bytes, and also
- // sorting the glyph data into glyph index order
+ // read the original 'loca' table and sort it into proper order --
+ // some (non-compliant) fonts have out-of-order loca tables; in
+ // order to correctly handle the case where (compliant) fonts have
+ // empty entries in the middle of the table, cmpTrueTypeLocaPos uses
+ // pos as its primary sort key, and idx as its secondary key
+ // (ensuring that adjacent entries with the same pos value remain in
+ // the same order)
origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
sizeof(TrueTypeLoca));
pos = seekTable("loca");
}
origLocaTable[nGlyphs].length = 0;
qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaIdx);
+
+ // construct the new 'loca' table, padding each glyph out to a
+ // multiple of 4 bytes
locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
pos = 0;
for (i = 0; i <= nGlyphs; ++i) {
glyphLength = origLocaTable[j].length;
pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
length += glyphLength + pad;
- checksum += computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
- glyphLength);
+ if (glyphLength >= 0 &&
+ glyfPos + origLocaTable[j].pos + glyphLength <= len) {
+ checksum +=
+ computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
+ glyphLength);
+ }
}
} else {
if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
glyfPos = seekTable("glyf");
for (j = 0; j < nGlyphs; ++j) {
length = origLocaTable[j].length;
- if (length > 0) {
+ if (length > 0 &&
+ glyfPos + origLocaTable[j].pos + length <= len) {
dumpString(file + glyfPos + origLocaTable[j].pos, length,
outputFunc, outputStream);
}
// already reported during the construction of the table
// headers
if ((length = newTableHdrs[i].length) > 0) {
- dumpString(file + seekTable(t42Tables[i].tag), length,
- outputFunc, outputStream);
+ j = seekTable(t42Tables[i].tag);
+ if (j >= 0) {
+ dumpString(file + seekTable(t42Tables[i].tag), length,
+ outputFunc, outputStream);
+ }
}
}
}
};
GBool haveCmap, haveName, havePost;
GBool dirCmap, dirName, dirPost;
- int nNewTables, nAllTables, pad;
+ GBool unsortedLoca;
+ int nNewTables, nZeroLengthTables, nAllTables;
+ TTFontTableHdr *newTableHdrs;
char *tableDir;
- Guint t, pos;
- int i, j;
+ TrueTypeLoca *origLocaTable;
+ char *locaTable;
+ int length, glyfLength;
+ Guint t, pos, pos2;
+ int i, j, k;
- // check for missing tables
+ // check for missing/broken tables
haveCmap = seekTable("cmap") >= 0;
haveName = seekTable("name") >= 0;
havePost = seekTable("post") >= 0;
+ unsortedLoca = gFalse;
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ pos2 = getULong(pos + 4*i);
+ } else {
+ pos2 = 2 * getUShort(pos + 2*i);
+ }
+ if (pos2 < pos) {
+ unsortedLoca = gTrue;
+ break;
+ }
+ pos = pos2;
+ }
nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
- if (!nNewTables && !mungedCmapSize) {
- // none are missing - write the TTF file as is
+ nZeroLengthTables = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (tableHdrs[i].length == 0) {
+ ++nZeroLengthTables;
+ }
+ }
+ if (!nNewTables && !nZeroLengthTables && !mungedCmapSize && !unsortedLoca) {
+ // nothing is broken - write the TTF file as is
fwrite(file, 1, len, out);
return;
}
+ // if the glyph data isn't sorted (as listed in the 'loca' table),
+ // construct a new 'loca' table
+ if (unsortedLoca) {
+ origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
+ sizeof(TrueTypeLoca));
+ pos = seekTable("loca");
+ for (i = 0; i <= nGlyphs; ++i) {
+ origLocaTable[i].idx = i;
+ if (locaFmt) {
+ origLocaTable[i].pos = getULong(pos + 4*i);
+ } else {
+ origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
+ }
+ }
+ qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaPos);
+ for (i = 0; i < nGlyphs; ++i) {
+ origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
+ }
+ origLocaTable[nGlyphs].length = 0;
+ qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaIdx);
+ locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ locaTable[4*i ] = (char)(pos >> 24);
+ locaTable[4*i+1] = (char)(pos >> 16);
+ locaTable[4*i+2] = (char)(pos >> 8);
+ locaTable[4*i+3] = (char) pos;
+ } else {
+ locaTable[2*i ] = (char)(pos >> 9);
+ locaTable[2*i+1] = (char)(pos >> 1);
+ }
+ length = origLocaTable[i].length;
+ if (length & 3) {
+ length += 4 - (length & 3);
+ }
+ pos += length;
+ }
+ glyfLength = pos;
+ } else {
+ origLocaTable = NULL; // make gcc happy
+ locaTable = NULL; // make gcc happy
+ glyfLength = 0; // make gcc happy
+ }
+
// construct the new table directory
- nAllTables = nTables + nNewTables;
- tableDir = (char *)gmalloc(12 + nAllTables * 16);
- memcpy(tableDir, file, 12 + nTables * 16);
- tableDir[4] = (char)((nAllTables >> 8) & 0xff);
- tableDir[5] = (char)(nAllTables & 0xff);
- for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
- t = 1 << (4 + i);
- tableDir[6] = (char)((t >> 8) & 0xff);
- tableDir[7] = (char)(t & 0xff);
- tableDir[8] = (char)((i >> 8) & 0xff);
- tableDir[9] = (char)(i & 0xff);
- t = nAllTables * 16 - t;
- tableDir[10] = (char)((t >> 8) & 0xff);
- tableDir[11] = (char)(t & 0xff);
+ nAllTables = nTables - nZeroLengthTables + nNewTables;
+ newTableHdrs = (TTFontTableHdr *)gmalloc(nAllTables *
+ sizeof(TTFontTableHdr));
dirCmap = haveCmap;
dirName = haveName;
dirPost = havePost;
+ pos = 12 + nAllTables * 16;
j = 0;
- pad = (len & 3) ? 4 - (len & 3) : 0;
- pos = len + pad + 16 * nNewTables;
for (i = 0; i < nTables; ++i) {
if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
- tableDir[12 + 16*j ] = 'c';
- tableDir[12 + 16*j + 1] = 'm';
- tableDir[12 + 16*j + 2] = 'a';
- tableDir[12 + 16*j + 3] = 'p';
- tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
- tableDir[12 + 16*j + 5] = (char)0;
- tableDir[12 + 16*j + 6] = (char)0;
- tableDir[12 + 16*j + 7] = (char)0;
- tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
- tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
- pos += sizeof(cmapTab);
+ memcpy(newTableHdrs[j].tag, "cmap", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(cmapTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
++j;
dirCmap = gTrue;
}
if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
- tableDir[12 + 16*j ] = 'n';
- tableDir[12 + 16*j + 1] = 'a';
- tableDir[12 + 16*j + 2] = 'm';
- tableDir[12 + 16*j + 3] = 'e';
- tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
- tableDir[12 + 16*j + 5] = (char)0;
- tableDir[12 + 16*j + 6] = (char)0;
- tableDir[12 + 16*j + 7] = (char)0;
- tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
- tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
- pos += sizeof(nameTab);
+ memcpy(newTableHdrs[j].tag, "name", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(nameTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
++j;
dirName = gTrue;
}
- if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
- tableDir[12 + 16*j ] = 'p';
- tableDir[12 + 16*j + 1] = 'o';
- tableDir[12 + 16*j + 2] = 's';
- tableDir[12 + 16*j + 3] = 't';
- tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
- tableDir[12 + 16*j + 5] = (char)0;
- tableDir[12 + 16*j + 6] = (char)0;
- tableDir[12 + 16*j + 7] = (char)0;
- tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
- tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
- pos += sizeof(postTab);
+ if (!dirPost && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
+ memcpy(newTableHdrs[j].tag, "post", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(postTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
++j;
dirPost = gTrue;
}
- tableDir[12 + 16*j ] = tableHdrs[i].tag[0];
- tableDir[12 + 16*j + 1] = tableHdrs[i].tag[1];
- tableDir[12 + 16*j + 2] = tableHdrs[i].tag[2];
- tableDir[12 + 16*j + 3] = tableHdrs[i].tag[3];
- tableDir[12 + 16*j + 4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
- tableDir[12 + 16*j + 5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
- tableDir[12 + 16*j + 6] = (char)((tableHdrs[i].checksum >> 8) & 0xff);
- tableDir[12 + 16*j + 7] = (char)( tableHdrs[i].checksum & 0xff);
- t = tableHdrs[i].offset + nNewTables * 16;
- tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( t & 0xff);
- tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length & 0xff);
- ++j;
+ // throw away zero-length tables - they confuse FreeType
+ if (tableHdrs[i].length > 0) {
+ memcpy(newTableHdrs[j].tag, tableHdrs[i].tag, 4);
+ newTableHdrs[j].checksum = tableHdrs[i].checksum;
+ newTableHdrs[j].offset = pos;
+ if (unsortedLoca && !strncmp(tableHdrs[i].tag, "loca", 4)) {
+ newTableHdrs[j].length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ } else if (unsortedLoca && !strncmp(tableHdrs[i].tag, "glyf", 4)) {
+ newTableHdrs[j].length = glyfLength;
+ } else {
+ newTableHdrs[j].length = tableHdrs[i].length;
+ }
+ pos += newTableHdrs[j].length;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ }
}
if (!dirCmap) {
- tableDir[12 + 16*j ] = 'c';
- tableDir[12 + 16*j + 1] = 'm';
- tableDir[12 + 16*j + 2] = 'a';
- tableDir[12 + 16*j + 3] = 'p';
- tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
- tableDir[12 + 16*j + 5] = (char)0;
- tableDir[12 + 16*j + 6] = (char)0;
- tableDir[12 + 16*j + 7] = (char)0;
- tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
- tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
- pos += sizeof(cmapTab);
+ memcpy(newTableHdrs[j].tag, "cmap", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(cmapTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
++j;
- dirCmap = gTrue;
}
if (!dirName) {
- tableDir[12 + 16*j ] = 'n';
- tableDir[12 + 16*j + 1] = 'a';
- tableDir[12 + 16*j + 2] = 'm';
- tableDir[12 + 16*j + 3] = 'e';
- tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
- tableDir[12 + 16*j + 5] = (char)0;
- tableDir[12 + 16*j + 6] = (char)0;
- tableDir[12 + 16*j + 7] = (char)0;
- tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
- tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
- pos += sizeof(nameTab);
+ memcpy(newTableHdrs[j].tag, "name", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(nameTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
++j;
- dirName = gTrue;
}
if (!dirPost) {
- tableDir[12 + 16*j ] = 'p';
- tableDir[12 + 16*j + 1] = 'o';
- tableDir[12 + 16*j + 2] = 's';
- tableDir[12 + 16*j + 3] = 't';
- tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
- tableDir[12 + 16*j + 5] = (char)0;
- tableDir[12 + 16*j + 6] = (char)0;
- tableDir[12 + 16*j + 7] = (char)0;
- tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
- tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
- tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
- tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
- tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
- tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
- tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
- tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
- pos += sizeof(postTab);
+ memcpy(newTableHdrs[j].tag, "post", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(postTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
++j;
- dirPost = gTrue;
+ }
+ tableDir = (char *)gmalloc(12 + nAllTables * 16);
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = (char)((nAllTables >> 8) & 0xff); // numTables
+ tableDir[5] = (char)(nAllTables & 0xff);
+ for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
+ t = 1 << (4 + i);
+ tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
+ tableDir[7] = (char)(t & 0xff);
+ tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
+ tableDir[9] = (char)(i & 0xff);
+ t = nAllTables * 16 - t;
+ tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
+ tableDir[11] = (char)(t & 0xff);
+ pos = 12;
+ for (i = 0; i < nAllTables; ++i) {
+ tableDir[pos ] = newTableHdrs[i].tag[0];
+ tableDir[pos+ 1] = newTableHdrs[i].tag[1];
+ tableDir[pos+ 2] = newTableHdrs[i].tag[2];
+ tableDir[pos+ 3] = newTableHdrs[i].tag[3];
+ tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
+ tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
+ tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
+ tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
+ tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
+ tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
+ tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
+ tableDir[pos+11] = (char) newTableHdrs[i].offset;
+ tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
+ tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
+ tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
+ tableDir[pos+15] = (char) newTableHdrs[i].length;
+ pos += 16;
}
// write the table directory
fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
- // write the original tables
- fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
-
- // write the new tables
- for (i = 0; i < pad; ++i) {
- fputc((char)0, out);
- }
- if (!haveCmap) {
- fwrite(cmapTab, 1, sizeof(cmapTab), out);
- }
- if (!haveName) {
- fwrite(nameTab, 1, sizeof(nameTab), out);
- }
- if (!havePost) {
- fwrite(postTab, 1, sizeof(postTab), out);
+ // write the tables
+ for (i = 0; i < nAllTables; ++i) {
+ if (!haveCmap && !strncmp(newTableHdrs[i].tag, "cmap", 4)) {
+ fwrite(cmapTab, 1, newTableHdrs[i].length, out);
+ } else if (!haveName && !strncmp(newTableHdrs[i].tag, "name", 4)) {
+ fwrite(nameTab, 1, newTableHdrs[i].length, out);
+ } else if (!havePost && !strncmp(newTableHdrs[i].tag, "post", 4)) {
+ fwrite(postTab, 1, newTableHdrs[i].length, out);
+ } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "loca", 4)) {
+ fwrite(locaTable, 1, newTableHdrs[i].length, out);
+ } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "glyf", 4)) {
+ pos = seekTable("glyf");
+ for (j = 0; j < nGlyphs; ++j) {
+ length = origLocaTable[j].length;
+ if (length > 0 &&
+ pos + origLocaTable[j].pos + length <= (Guint)len) {
+ fwrite(file + pos + origLocaTable[j].pos, 1, length, out);
+ if ((k = length & 3)) {
+ for (; k < 4; ++k) {
+ fputc((char)0, out);
+ }
+ }
+ }
+ }
+ } else {
+ fwrite(file + seekTable(newTableHdrs[i].tag),
+ 1, newTableHdrs[i].length, out);
+ }
+ if ((j = (newTableHdrs[i].length & 3))) {
+ for (; j < 4; ++j) {
+ fputc((char)0, out);
+ }
+ }
}
-
+
gfree(tableDir);
+ gfree(newTableHdrs);
+ if (unsortedLoca) {
+ gfree(origLocaTable);
+ gfree(locaTable);
+ }
}
Type1CFontFile(const char *fileA, int lenA);
virtual ~Type1CFontFile();
+ GBool isOk() { return ok; }
virtual const char *getName();
virtual const char **getEncoding();
private:
- void readNameAndEncoding();
+ void readEncoding();
void readTopDict(Type1CTopDict *dict);
void readPrivateDict(Type1CPrivateDict *privateDict,
int offset, int size);
Gushort *readCharset(int charset, int nGlyphs);
void eexecWrite(const char *s);
- void eexecCvtGlyph(const char *glyphName, Guchar *s, int n);
- void cvtGlyph(Guchar *s, int n);
+ void eexecCvtGlyph(const char *glyphName, int pos, int n);
+ void cvtGlyph(int pos, int n, GBool top);
void cvtGlyphWidth(GBool useOp);
void eexecDumpNum(double x, GBool fpA);
void eexecDumpOp1(int opA);
void eexecWriteCharstring(Guchar *s, int n);
void getDeltaInt(char *buf, const char *key, double *opA, int n);
void getDeltaReal(char *buf, const char *key, double *opA, int n);
- int getIndexLen(Guchar *indexPtr);
- Guchar *getIndexValPtr(Guchar *indexPtr, int i);
- Guchar *getIndexEnd(Guchar *indexPtr);
- Guint getWord(Guchar *ptr, int size);
- double getNum(Guchar **ptr, GBool *fp);
+ int getIndexLen(int indexPos);
+ int getIndexValPos(int indexPos, int i, int *valLen);
+ int getIndexEnd(int indexPos);
+ Guint getWord(int pos, int size);
+ double getNum(int *pos, GBool *fp);
char *getString(int sid, char *buf);
- const char *file;
+ const Guchar *file;
int len;
GString *name;
char **encoding;
- int topOffSize;
- Guchar *topDictIdxPtr;
- Guchar *stringIdxPtr;
- Guchar *gsubrIdxPtr;
+ int topDictIdxPos;
+ int stringIdxPos;
+ int gsubrIdxPos;
+ int subrIdxPos;
+ int gsubrBias;
+ int subrBias;
FontFileOutputFunc outputFunc;
void *outputStream;
double op[48]; // operands
GBool fp[48]; // true if operand is fixed point
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
double defaultWidthX; // default glyph width
double nominalWidthX; // nominal glyph width
GBool defaultWidthXFP; // true if defaultWidthX is fixed point
Gushort r1; // eexec encryption key
GString *charBuf; // charstring output buffer
int line; // number of eexec chars on current line
+
+ GBool ok;
};
//------------------------------------------------------------------------
void convertToType42(const char *name, const char **encodingA,
CharCodeToUnicode *toUnicode,
GBool pdfFontHasEncoding,
+ GBool pdfFontIsSymbolic,
FontFileOutputFunc outputFunc, void *outputStream);
// Convert to a Type 2 CIDFont, suitable for embedding in a
void cvtEncoding(const char **encodingA, GBool pdfFontHasEncoding,
FontFileOutputFunc outputFunc, void *outputStream);
void cvtCharStrings(const char **encodingA, CharCodeToUnicode *toUnicode,
- GBool pdfFontHasEncoding,
+ GBool pdfFontHasEncoding, GBool pdfFontIsSymbolic,
FontFileOutputFunc outputFunc, void *outputStream);
int getCmapEntry(int cmapFmt, int pos, int code);
void cvtSfnts(FontFileOutputFunc outputFunc, void *outputStream,
//
// Function.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
Object obj1, obj2;
- GBool hasN;
int i;
ok = gFalse;
error(-1, "Exponential function with more than one input");
goto err1;
}
- hasN = hasRange;
-
- //----- default values
- for (i = 0; i < funcMaxOutputs; ++i) {
- c0[i] = 0;
- c1[i] = 1;
- }
//----- C0
if (dict->lookup("C0", &obj1)->isArray()) {
- if (!hasN) {
- n = obj1.arrayGetLength();
- hasN = gTrue;
- } else if (obj1.arrayGetLength() != n) {
+ if (hasRange && obj1.arrayGetLength() != n) {
error(-1, "Function's C0 array is wrong length");
goto err2;
}
+ n = obj1.arrayGetLength();
for (i = 0; i < n; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isNum()) {
c0[i] = obj2.getNum();
obj2.free();
}
+ } else {
+ if (hasRange && n != 1) {
+ error(-1, "Function's C0 array is wrong length");
+ goto err2;
+ }
+ n = 1;
+ c0[0] = 0;
}
obj1.free();
//----- C1
if (dict->lookup("C1", &obj1)->isArray()) {
- if (!hasN) {
- n = obj1.arrayGetLength();
- hasN = gTrue;
- } else if (obj1.arrayGetLength() != n) {
+ if (obj1.arrayGetLength() != n) {
error(-1, "Function's C1 array is wrong length");
goto err2;
}
c1[i] = obj2.getNum();
obj2.free();
}
+ } else {
+ if (n != 1) {
+ error(-1, "Function's C1 array is wrong length");
+ goto err2;
+ }
+ c1[0] = 1;
}
obj1.free();
e = obj1.getNum();
obj1.free();
- // this isn't supposed to happen, but I've run into (broken) PDF
- // files where it does
- if (!hasN) {
- error(-1, "Exponential function does not define number of output values");
- n = 1;
- }
-
ok = gTrue;
return;
//
// GHash.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// GList.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Simple variable-length string type.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Gfx.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// GfxFont.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
const char *properName;
};
+// Acrobat 4.0 and earlier substituted Base14-compatible fonts without
+// providing Widths and a FontDescriptor, so we munge the names into
+// the proper Base14 names. This table is from implementation note 44
+// in the PDF 1.4 spec, with some additions based on empirical
+// evidence.
static StdFontMapEntry stdFontMap[] = {
{ "Arial", "Helvetica" },
{ "Arial,Bold", "Helvetica-Bold" },
}
void GfxFont::findExtFontFile() {
+ static const char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
+ static const char *ttExts[] = { ".ttf", NULL };
+
if (name) {
if (type == fontType1) {
- extFontFile = globalParams->findFontFile(name, ".pfa", ".pfb");
+ extFontFile = globalParams->findFontFile(name, type1Exts);
} else if (type == fontTrueType) {
- extFontFile = globalParams->findFontFile(name, ".ttf", NULL);
+ extFontFile = globalParams->findFontFile(name, ttExts);
}
}
}
type = typeA;
ctu = NULL;
- // Acrobat 4.0 and earlier substituted Base14-compatible fonts
- // without providing Widths and a FontDescriptor, so we munge the
- // names into the proper Base14 names. (This table is from
- // implementation note 44 in the PDF 1.4 spec.)
+ // do font name substitution for various aliases of the Base 14 font
+ // names
if (name) {
a = 0;
b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
fontFile = new Type1FontFile(buf, len);
} else {
fontFile = new Type1CFontFile(buf, len);
+ if (!((Type1CFontFile *)fontFile)->isOk()) {
+ delete fontFile;
+ fontFile = NULL;
+ }
}
- if (fontFile->getName()) {
+ if (fontFile && fontFile->getName()) {
if (embFontName) {
delete embFontName;
}
embFontName = new GString(fontFile->getName());
}
- if (!baseEnc) {
+ if (fontFile && !baseEnc) {
baseEnc = fontFile->getEncoding();
baseEncFromFontFile = gTrue;
}
fontDict->lookup("Widths", &obj1);
if (obj1.isArray()) {
flags |= fontFixedWidth;
+ if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
+ lastChar = firstChar + obj1.arrayGetLength() - 1;
+ }
for (code = firstChar; code <= lastChar; ++code) {
obj1.arrayGet(code - firstChar, &obj2);
if (obj2.isNum()) {
// GfxCIDFont
//------------------------------------------------------------------------
-static int cmpWidthExcep(const void *w1, const void *w2) {
+static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcep *)w1)->first -
((GfxFontCIDWidthExcep *)w2)->first;
}
-static int cmpWidthExcepV(const void *w1, const void *w2) {
+static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcepV *)w1)->first -
((GfxFontCIDWidthExcepV *)w2)->first;
}
//
// GfxState.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// GlobalParams.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
} else if (!cmd->cmp("displayCIDFontT1")) {
parseDisplayFont(tokens, displayCIDFonts,
displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontTT")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontTT, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontTT")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontTT, fileName, line);
} else if (!cmd->cmp("psFile")) {
parsePSFile(tokens, fileName, line);
} else if (!cmd->cmp("psFont")) {
}
GString *GlobalParams::findFontFile(GString *fontName,
- const char *ext1, const char *ext2) {
+ const char **exts) {
GString *dir, *fileName;
+ const char **ext;
FILE *f;
int i;
for (i = 0; i < fontDirs->getLength(); ++i) {
dir = (GString *)fontDirs->get(i);
- if (ext1) {
- fileName = appendToPath(dir->copy(), fontName->getCString());
- fileName->append(ext1);
- if ((f = fopen(fileName->getCString(), "r"))) {
- fclose(f);
- return fileName;
- }
- delete fileName;
- }
- if (ext2) {
+ for (ext = exts; *ext; ++ext) {
fileName = appendToPath(dir->copy(), fontName->getCString());
- fileName->append(ext2);
+ fileName->append(*ext);
if ((f = fopen(fileName->getCString(), "r"))) {
fclose(f);
return fileName;
GBool GlobalParams::setPSPaperSize(const char *size) {
globalParamsLock;
- if (!strcmp(size, "letter")) {
+ if (!strcmp(size, "match")) {
+ psPaperWidth = psPaperHeight = -1;
+ } else if (!strcmp(size, "letter")) {
psPaperWidth = 612;
psPaperHeight = 792;
} else if (!strcmp(size, "legal")) {
GBool getPSASCIIHex();
EndOfLineKind getTextEOL();
GBool getTextKeepTinyChars();
- GString *findFontFile(GString *fontName, const char *ext1, const char *ext2);
+ GString *findFontFile(GString *fontName, const char **exts);
GString *getInitialZoom();
FontRastControl getT1libControl();
FontRastControl getFreeTypeControl();
//
// JBIG2Stream.cc
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
len = 0;
prefix = 0;
while (table[i].rangeLen != jbig2HuffmanEOT) {
- //~ if buildTable removes the entries with prefixLen=0, this is unneeded
- if (table[i].prefixLen > 0) {
- while (len < table[i].prefixLen) {
- prefix = (prefix << 1) | readBit();
- ++len;
+ while (len < table[i].prefixLen) {
+ prefix = (prefix << 1) | readBit();
+ ++len;
+ }
+ if (prefix == table[i].prefix) {
+ if (table[i].rangeLen == jbig2HuffmanOOB) {
+ return gFalse;
}
- if (prefix == table[i].prefix) {
- if (table[i].rangeLen == jbig2HuffmanOOB) {
- return gFalse;
- }
- if (table[i].rangeLen == jbig2HuffmanLOW) {
- *x = table[i].val - readBits(32);
- } else if (table[i].rangeLen > 0) {
- *x = table[i].val + readBits(table[i].rangeLen);
- } else {
- *x = table[i].val;
- }
- return gTrue;
+ if (table[i].rangeLen == jbig2HuffmanLOW) {
+ *x = table[i].val - readBits(32);
+ } else if (table[i].rangeLen > 0) {
+ *x = table[i].val + readBits(table[i].rangeLen);
+ } else {
+ *x = table[i].val;
}
+ return gTrue;
}
++i;
}
return (buf >> bufLen) & 1;
}
-static int cmpHuffmanTabEntries(const void *p1, const void *p2) {
- return ((JBIG2HuffmanTable *)p1)->prefixLen
- - ((JBIG2HuffmanTable *)p2)->prefixLen;
-}
-
-//~ should remove entries with prefixLen = 0
void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
- Guint i, prefix;
-
- qsort(table, len, sizeof(JBIG2HuffmanTable), &cmpHuffmanTabEntries);
- for (i = 0; i < len && table[i].prefixLen == 0; ++i) {
- table[i].prefix = 0;
+ Guint i, j, k, prefix;
+ JBIG2HuffmanTable tab;
+
+ // stable selection sort:
+ // - entries with prefixLen > 0, in ascending prefixLen order
+ // - entry with prefixLen = 0, rangeLen = EOT
+ // - all other entries with prefixLen = 0
+ // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
+ for (i = 0; i < len; ++i) {
+ for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
+ if (j == len) {
+ break;
+ }
+ for (k = j + 1; k < len; ++k) {
+ if (table[k].prefixLen > 0 &&
+ table[k].prefixLen < table[j].prefixLen) {
+ j = k;
+ }
+ }
+ if (j != i) {
+ tab = table[j];
+ for (k = j; k > i; --k) {
+ table[k] = table[k - 1];
+ }
+ table[i] = tab;
+ }
}
+ table[i] = table[len];
+
+ // assign prefixes
+ i = 0;
prefix = 0;
table[i++].prefix = prefix++;
- for (; i < len; ++i) {
+ for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
prefix <<= table[i].prefixLen - table[i-1].prefixLen;
table[i].prefix = prefix++;
}
++nBytesRead;
}
while (1) {
- if (bufLen > 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
+ if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
if (bufLen <= 12) {
code = buf << (12 - bufLen);
} else {
}
p = &whiteTab2[code & 0x1ff];
}
- if (p->bits > 0 && p->bits < (int)bufLen) {
+ if (p->bits > 0 && p->bits <= (int)bufLen) {
bufLen -= p->bits;
return p->n;
}
++nBytesRead;
}
while (1) {
- if (bufLen > 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
+ if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
if (bufLen <= 13) {
code = buf << (13 - bufLen);
} else {
code = buf >> (bufLen - 13);
}
p = &blackTab1[code & 0x7f];
- } else if (bufLen > 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
+ } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
if (bufLen <= 12) {
code = buf << (12 - bufLen);
} else {
}
p = &blackTab3[code & 0x3f];
}
- if (p->bits > 0 && p->bits < (int)bufLen) {
+ if (p->bits > 0 && p->bits <= (int)bufLen) {
bufLen -= p->bits;
return p->n;
}
// JBIG2Bitmap
//------------------------------------------------------------------------
+struct JBIG2BitmapPtr {
+ Guchar *p;
+ int shift;
+ int x;
+};
+
class JBIG2Bitmap: public JBIG2Segment {
public:
{ data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
void clearPixel(int x, int y)
{ data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
+ void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
+ int nextPixel(JBIG2BitmapPtr *ptr);
void duplicateRow(int yDest, int ySrc);
void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
Guchar *getDataPtr() { return data; }
memset(data, 0xff, h * line);
}
+inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
+ if (y < 0 || y >= h || x >= w) {
+ ptr->p = NULL;
+ } else if (x < 0) {
+ ptr->p = &data[y * line];
+ ptr->shift = 7;
+ ptr->x = x;
+ } else {
+ ptr->p = &data[y * line + (x >> 3)];
+ ptr->shift = 7 - (x & 7);
+ ptr->x = x;
+ }
+}
+
+inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
+ int pix;
+
+ if (!ptr->p) {
+ pix = 0;
+ } else if (ptr->x < 0) {
+ ++ptr->x;
+ pix = 0;
+ } else {
+ pix = (*ptr->p >> ptr->shift) & 1;
+ if (++ptr->x == w) {
+ ptr->p = NULL;
+ } else if (ptr->shift == 0) {
+ ++ptr->p;
+ ptr->shift = 7;
+ } else {
+ --ptr->shift;
+ }
+ }
+ return pix;
+}
+
void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
memcpy(data + yDest * line, data + ySrc * line, line);
}
huffDecoder = new JBIG2HuffmanDecoder();
mmrDecoder = new JBIG2MMRDecoder();
- segments = new GList();
+ segments = globalSegments = new GList();
if (globalsStream->isStream()) {
curStr = globalsStream->getStream();
curStr->reset();
mmrDecoder->setStream(curStr);
readSegments();
}
- globalSegments = segments;
segments = NULL;
curStr = NULL;
} else {
if (contextUsed && inputSymbolDict) {
resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
- if (refAgg) {
- resetRefinementStats(sdrTemplate,
- inputSymbolDict->getRefinementRegionStats());
- }
} else {
resetGenericStats(sdTemplate, NULL);
- if (refAgg) {
- resetRefinementStats(sdrTemplate, NULL);
- }
}
resetIntStats(symCodeLen);
arithDecoder->start();
}
+ // set up the arithmetic decoder for refinement/aggregation
+ if (refAgg) {
+ if (contextUsed && inputSymbolDict) {
+ resetRefinementStats(sdrTemplate,
+ inputSymbolDict->getRefinementRegionStats());
+ } else {
+ resetRefinementStats(sdrTemplate, NULL);
+ }
+ }
+
// allocate symbol widths storage
symWidths = NULL;
if (huff && !refAgg) {
break;
}
}
+#if 0 //~ This special case was added about a year before the final draft
+ //~ of the JBIG2 spec was released. I have encountered some old
+ //~ JBIG2 images that predate it.
+ if (0) {
+#else
if (refAggNum == 1) {
+#endif
if (huff) {
symID = huffDecoder->readBits(symCodeLen);
huffDecoder->decodeInt(&refDX, huffTableO);
// read the collective bitmap
if (huff && !refAgg) {
huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
- if (huff) {
- huffDecoder->reset();
- }
+ huffDecoder->reset();
if (bmSize == 0) {
collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
bmSize = symHeight * ((totalWidth + 7) >> 3);
p = collBitmap->getDataPtr();
for (k = 0; k < (Guint)bmSize; ++k) {
- *p++ = str->getChar();
+ *p++ = curStr->getChar();
}
} else {
collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
}
ex = !ex;
}
-
+
for (i = 0; i < numNewSyms; ++i) {
delete bitmaps[numInputSyms + i];
}
JBIG2Bitmap **syms;
Guint w, h, x, y, segInfoFlags, extCombOp;
Guint flags, huff, refine, logStrips, refCorner, transposed;
- Guint combOp, defPixel, sOffset, templ;
+ Guint combOp, defPixel, templ;
+ int sOffset;
Guint huffFlags, huffFS, huffDS, huffDT;
Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
Guint numInstances, numSyms, symCodeLen;
combOp = (flags >> 7) & 3;
defPixel = (flags >> 9) & 1;
sOffset = (flags >> 10) & 0x1f;
+ if (sOffset & 0x10) {
+ sOffset |= -1 - 0x0f;
+ }
templ = (flags >> 15) & 1;
huffFS = huffDS = huffDT = 0; // make gcc happy
huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
runLengthTab[34].val = 0x20b;
runLengthTab[34].prefixLen = huffDecoder->readBits(4);
runLengthTab[34].rangeLen = 7;
+ runLengthTab[35].prefixLen = 0;
runLengthTab[35].rangeLen = jbig2HuffmanEOT;
huffDecoder->buildTable(runLengthTab, 35);
symCodeTab = (JBIG2HuffmanTable *)gmalloc((numSyms + 1) *
} else {
symCodeTab[i++].prefixLen = j;
}
-
}
+ symCodeTab[numSyms].prefixLen = 0;
symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
huffDecoder->buildTable(symCodeTab, numSyms);
huffDecoder->reset();
} else {
symCodeTab = NULL;
resetIntStats(symCodeLen);
- if (refine) {
- resetRefinementStats(templ, NULL);
- }
arithDecoder->start();
}
+ if (refine) {
+ resetRefinementStats(templ, NULL);
+ }
bitmap = readTextRegion(huff, refine, w, h, numInstances,
logStrips, numSyms, symCodeTab, symCodeLen, syms,
JBIG2Bitmap **syms,
Guint defPixel, Guint combOp,
Guint transposed, Guint refCorner,
- Guint sOffset,
+ int sOffset,
JBIG2HuffmanTable *huffFSTable,
JBIG2HuffmanTable *huffDSTable,
JBIG2HuffmanTable *huffDTTable,
JBIG2Bitmap *bitmap;
GBool ltp;
Guint ltpCX, cx, cx0, cx1, cx2;
+ JBIG2BitmapPtr cxPtr0, cxPtr1;
+ JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
int *refLine, *codingLine;
int code1, code2, code3;
int x, y, a0, pix, i, refI, codingI;
}
}
- // set up the context
switch (templ) {
case 0:
- cx0 = (bitmap->getPixel(0, y-2) << 1) |
- bitmap->getPixel(1, y-2);
- cx1 = (bitmap->getPixel(0, y-1) << 2) |
- (bitmap->getPixel(1, y-1) << 1) |
- bitmap->getPixel(2, y-1);
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-2, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+ bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
+ bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
+ bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
+ (bitmap->nextPixel(&atPtr0) << 3) |
+ (bitmap->nextPixel(&atPtr1) << 2) |
+ (bitmap->nextPixel(&atPtr2) << 1) |
+ bitmap->nextPixel(&atPtr3);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x0f;
+ }
break;
+
case 1:
- cx0 = (bitmap->getPixel(0, y-2) << 2) |
- (bitmap->getPixel(1, y-2) << 1) |
- bitmap->getPixel(2, y-2);
- cx1 = (bitmap->getPixel(0, y-1) << 2) |
- (bitmap->getPixel(1, y-1) << 1) |
- bitmap->getPixel(2, y-1);
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-2, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
+ bitmap->nextPixel(&atPtr0);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x0f;
+ }
break;
+
case 2:
- cx0 = (bitmap->getPixel(0, y-2) << 1) |
- bitmap->getPixel(1, y-2);
- cx1 = (bitmap->getPixel(0, y-1) << 1) |
- bitmap->getPixel(1, y-1);
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-2, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
+ bitmap->nextPixel(&atPtr0);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x07;
+ }
break;
+
case 3:
- cx1 = (bitmap->getPixel(0, y-1) << 1) |
- bitmap->getPixel(1, y-1);
- cx2 = 0;
- break;
- }
- // decode the row
- for (x = 0; x < w; ++x) {
+ // set up the context
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
- // check for a skipped pixel
- if (useSkip && skip->getPixel(x, y)) {
- pix = 0;
-
- } else {
+ // decode the row
+ for (x = 0; x < w; ++x) {
// build the context
- switch (templ) {
- case 0:
- cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
- (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) |
- (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) |
- (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) |
- bitmap->getPixel(x + atx[3], y + aty[3]);
- break;
- case 1:
- cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
- bitmap->getPixel(x + atx[0], y + aty[0]);
- break;
- case 2:
- cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
- bitmap->getPixel(x + atx[0], y + aty[0]);
- break;
- case 3:
- cx = (cx1 << 5) | (cx2 << 1) |
- bitmap->getPixel(x + atx[0], y + aty[0]);
- break;
- }
+ cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
+ bitmap->nextPixel(&atPtr0);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
// decode the pixel
- if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
bitmap->setPixel(x, y);
}
- }
- // update the context
- switch (templ) {
- case 0:
- cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07;
- cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x0f;
- break;
- case 1:
- cx0 = ((cx0 << 1) | bitmap->getPixel(x+3, y-2)) & 0x0f;
- cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x07;
- break;
- case 2:
- cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07;
- cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x0f;
- cx2 = ((cx2 << 1) | pix) & 0x03;
- break;
- case 3:
- cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x1f;
- cx2 = ((cx2 << 1) | pix) & 0x0f;
- break;
+ // update the context
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x0f;
}
+ break;
}
}
}
JBIG2Bitmap *bitmap;
GBool ltp;
Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
+ JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
+ JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
int x, y, pix;
bitmap = new JBIG2Bitmap(0, w, h);
ltp = 0;
for (y = 0; y < h; ++y) {
- // set up the context
if (templ) {
- cx0 = bitmap->getPixel(0, y-1);
- cx2 = 0; // unused
- cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) |
- refBitmap->getPixel(-refDX, y-refDY);
- cx4 = refBitmap->getPixel(-refDX, y+1-refDY);
- } else {
- cx0 = bitmap->getPixel(0, y-1);
- cx2 = refBitmap->getPixel(-refDX, y-1-refDY);
- cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) |
- refBitmap->getPixel(-refDX, y-refDY);
- cx4 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 1) |
- refBitmap->getPixel(-refDX, y+1-refDY);
- }
-
- // set up the typical prediction context
- tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
- if (tpgrOn) {
- tpgrCX0 = (refBitmap->getPixel(-1-refDX, y-1-refDY) << 2) |
- (refBitmap->getPixel(-refDX, y-1-refDY) << 1) |
- refBitmap->getPixel(1-refDX, y-1-refDY);
- tpgrCX1 = (refBitmap->getPixel(-1-refDX, y-refDY) << 2) |
- (refBitmap->getPixel(-refDX, y-refDY) << 1) |
- refBitmap->getPixel(1-refDX, y-refDY);
- tpgrCX2 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 2) |
- (refBitmap->getPixel(-refDX, y+1-refDY) << 1) |
- refBitmap->getPixel(1-refDX, y+1-refDY);
- }
-
- for (x = 0; x < w; ++x) {
-
- // update the context
- if (templ) {
- cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 7;
- cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
- cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 3;
- } else {
- cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 3;
- cx2 = ((cx2 << 1) | refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 3;
- cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
- cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7;
- }
+ // set up the context
+ bitmap->getPixelPtr(0, y-1, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(-1, y, &cxPtr1);
+ refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
+ cx3 = refBitmap->nextPixel(&cxPtr3);
+ cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
+ refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
+ cx4 = refBitmap->nextPixel(&cxPtr4);
+
+ // set up the typical prediction context
+ tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
if (tpgrOn) {
- // update the typical predictor context
- tpgrCX0 = ((tpgrCX0 << 1) |
- refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 7;
- tpgrCX1 = ((tpgrCX1 << 1) |
- refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
- tpgrCX2 = ((tpgrCX2 << 1) |
- refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7;
-
- // check for a "typical" pixel
- if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
- ltp = !ltp;
+ refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
+ tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
+ tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
+ tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ }
+
+ for (x = 0; x < w; ++x) {
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
+ cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
+ cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
+
+ if (tpgrOn) {
+ // update the typical predictor context
+ tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
+ tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
+ tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
+
+ // check for a "typical" pixel
+ if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
+ ltp = !ltp;
+ }
+ if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
+ bitmap->clearPixel(x, y);
+ continue;
+ } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
+ bitmap->setPixel(x, y);
+ continue;
+ }
}
- if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
- bitmap->clearPixel(x, y);
- continue;
- } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
+
+ // build the context
+ cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
+ (refBitmap->nextPixel(&cxPtr2) << 5) |
+ (cx3 << 2) | cx4;
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
bitmap->setPixel(x, y);
- continue;
}
}
- // build the context
- if (templ) {
- cx = (cx0 << 7) | (bitmap->getPixel(x-1, y) << 6) |
- (refBitmap->getPixel(x-refDX, y-1-refDY) << 5) |
- (cx3 << 2) | cx4;
- } else {
- cx = (cx0 << 11) | (bitmap->getPixel(x-1, y) << 10) |
- (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
- (bitmap->getPixel(x+atx[0], y+aty[0]) << 1) |
- refBitmap->getPixel(x+atx[1]-refDX, y+aty[1]-refDY);
+ } else {
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-1, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(-1, y, &cxPtr1);
+ refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
+ cx2 = refBitmap->nextPixel(&cxPtr2);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
+ cx3 = refBitmap->nextPixel(&cxPtr3);
+ cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
+ refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
+ cx4 = refBitmap->nextPixel(&cxPtr4);
+ cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
+ bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
+ refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
+
+ // set up the typical prediction context
+ tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
+ if (tpgrOn) {
+ refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
+ tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
+ tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
+ tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
}
- // decode the pixel
- if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
- bitmap->setPixel(x, y);
+ for (x = 0; x < w; ++x) {
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
+ cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
+ cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
+ cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
+
+ if (tpgrOn) {
+ // update the typical predictor context
+ tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
+ tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
+ tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
+
+ // check for a "typical" pixel
+ if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
+ ltp = !ltp;
+ }
+ if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
+ bitmap->clearPixel(x, y);
+ continue;
+ } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
+ bitmap->setPixel(x, y);
+ continue;
+ }
+ }
+
+ // build the context
+ cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
+ (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
+ (bitmap->nextPixel(&cxPtr5) << 1) |
+ refBitmap->nextPixel(&cxPtr6);
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
}
}
}
goto eofError;
}
oob = flags & 1;
- prefixBits = (flags >> 1) & 7;
- rangeBits = (flags >> 4) & 7;
+ prefixBits = ((flags >> 1) & 7) + 1;
+ rangeBits = ((flags >> 4) & 7) + 1;
huffDecoder->reset();
huffTabSize = 8;
huffTab[i].val = 0;
huffTab[i].prefixLen = 0;
huffTab[i].rangeLen = jbig2HuffmanEOT;
- ++i;
huffDecoder->buildTable(huffTab, i);
// create and store the new table segment
}
*x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
if (c0 & 0x80) {
- *x |= -1 - 0xffffffff;
+ *x |= -1 - (int)0xffffffff;
}
return gTrue;
}
//
// JBIG2Stream.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
JBIG2Bitmap **syms,
Guint defPixel, Guint combOp,
Guint transposed, Guint refCorner,
- Guint sOffset,
+ int sOffset,
JBIG2HuffmanTable *huffFSTable,
JBIG2HuffmanTable *huffDSTable,
JBIG2HuffmanTable *huffDTTable,
//
// Lexer.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Link.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
// get page
if (a->getLength() < 2) {
- error(-1, "Annotation destination array has wrong length");
+ error(-1, "Annotation destination array is too short");
return;
}
a->getNF(0, &obj1);
// Fit link
} else if (obj1.isName("Fit")) {
- if (a->getLength() != 2) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFit;
// FitH link
} else if (obj1.isName("FitH")) {
- if (a->getLength() != 3) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFitH;
// FitV link
} else if (obj1.isName("FitV")) {
- if (a->getLength() != 3) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFitV;
// FitR link
} else if (obj1.isName("FitR")) {
- if (a->getLength() != 6) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 6) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFitR;
// FitB link
} else if (obj1.isName("FitB")) {
- if (a->getLength() != 2) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFitB;
// FitBH link
} else if (obj1.isName("FitBH")) {
- if (a->getLength() != 3) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFitBH;
// FitBV link
} else if (obj1.isName("FitBV")) {
- if (a->getLength() != 3) {
- error(-1, "Annotation destination array has wrong length");
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
goto err2;
}
kind = destFitBV;
#
-# "$Id: Makefile,v 1.6.2.10 2003/05/14 20:03:13 mike Exp $"
+# "$Id: Makefile,v 1.6.2.11 2003/07/20 00:40:03 mike Exp $"
#
# pdftops filter Makefile for the Common UNIX Printing System (CUPS).
#
#
-# End of "$Id: Makefile,v 1.6.2.10 2003/05/14 20:03:13 mike Exp $".
+# End of "$Id: Makefile,v 1.6.2.11 2003/07/20 00:40:03 mike Exp $".
#
//
// NameToCharCode.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Object.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Outline.cc
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Outline.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//
// OutputDev.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det;
}
-void OutputDev::cvtDevToUser(int dx, int dy, double *ux, double *uy) {
+void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) {
*ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4];
*uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5];
}
//----- coordinate conversion
// Convert between device and user coordinates.
- virtual void cvtDevToUser(int dx, int dy, double *ux, double *uy);
+ virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy);
virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
//----- link borders
//
// PDFDoc.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// PDFDocEncoding.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//
// PDFDocEncoding.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//
// PSOutputDev.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#include <signal.h>
#include <math.h>
#include "GString.h"
+#include "GList.h"
#include "config.h"
#include "GlobalParams.h"
#include "Object.h"
" /customcolorimage {",
" gsave",
" [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
- " 0 4 getinterval cvx",
+ " 0 4 getinterval",
" [ exch /dup load exch { mul exch dup } /forall load",
" /pop load dup ] cvx",
" ] setcolorspace",
"/pdfImSep {",
" findcmykcustomcolor exch",
" dup /Width get /pdfImBuf1 exch string def",
+ " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def",
+ " /pdfImDecodeLow exch def",
" begin Width Height BitsPerComponent ImageMatrix DataSource end",
" /pdfImData exch def",
" { pdfImData pdfImBuf1 readstring pop",
" 0 1 2 index length 1 sub {",
- " 1 index exch 2 copy get 255 exch sub put",
+ " 1 index exch 2 copy get",
+ " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi",
+ " 255 exch sub put",
" } for }",
" 6 5 roll customcolorimage",
" { currentfile pdfImBuf readline",
fontFileIDs = NULL;
fontFileNames = NULL;
font16Enc = NULL;
+ xobjStack = NULL;
embFontList = NULL;
customColors = NULL;
t3String = NULL;
fontFileIDs = NULL;
fontFileNames = NULL;
font16Enc = NULL;
+ xobjStack = NULL;
embFontList = NULL;
customColors = NULL;
t3String = NULL;
mode = modeA;
paperWidth = globalParams->getPSPaperWidth();
paperHeight = globalParams->getPSPaperHeight();
+ if (paperWidth < 0 || paperHeight < 0) {
+ page = catalog->getPage(firstPage);
+ paperWidth = (int)(page->getWidth() + 0.5);
+ paperHeight = (int)(page->getHeight() + 0.5);
+ }
if (mode == psModeForm) {
lastPage = firstPage;
}
fontFileNames = (GString **)gmalloc(fontFileNameSize * sizeof(GString *));
font16EncLen = 0;
font16EncSize = 0;
+ xobjStack = new GList();
// initialize embedded font resource comment list
embFontList = new GString();
}
gfree(font16Enc);
}
+ if (xobjStack) {
+ delete xobjStack;
+ }
while (customColors) {
cc = customColors;
customColors = cc->next;
}
void PSOutputDev::setupResources(Dict *resDict) {
- Object xObjDict, xObj, resObj;
- int i;
+ Object xObjDict, xObjRef, xObj, resObj;
+ Ref ref0, ref1;
+ GBool skip;
+ int i, j;
setupFonts(resDict);
setupImages(resDict);
resDict->lookup("XObject", &xObjDict);
if (xObjDict.isDict()) {
for (i = 0; i < xObjDict.dictGetLength(); ++i) {
- xObjDict.dictGetVal(i, &xObj);
- if (xObj.isStream()) {
- xObj.streamGetDict()->lookup("Resources", &resObj);
- if (resObj.isDict()) {
- setupResources(resObj.getDict());
+
+ // avoid infinite recursion on XObjects
+ skip = gFalse;
+ if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) {
+ ref0 = xObjRef.getRef();
+ for (j = 0; j < xobjStack->getLength(); ++j) {
+ ref1 = *(Ref *)xobjStack->get(j);
+ if (ref1.num == ref0.num && ref1.gen == ref0.gen) {
+ skip = gTrue;
+ break;
+ }
+ }
+ if (!skip) {
+ xobjStack->append(&ref0);
}
- resObj.free();
}
- xObj.free();
+ if (!skip) {
+
+ // process the XObject's resource dictionary
+ xObjDict.dictGetVal(i, &xObj);
+ if (xObj.isStream()) {
+ xObj.streamGetDict()->lookup("Resources", &resObj);
+ if (resObj.isDict()) {
+ setupResources(resObj.getDict());
+ }
+ resObj.free();
+ }
+ xObj.free();
+ }
+
+ if (xObjRef.isRef() && !skip) {
+ xobjStack->del(xobjStack->getLength() - 1);
+ }
+ xObjRef.free();
}
}
xObjDict.free();
GString *psNameStr;
const char *psName;
char type3Name[64], buf[16];
+ GBool subst;
UnicodeMap *uMap;
const char *charName;
double xs, ys;
xs = ys = 1;
psNameStr = NULL;
+ subst = gFalse;
// check for resident 8-bit font
if (font->getName() &&
// do 8-bit font substitution
} else if (!font->isCIDFont()) {
+ subst = gTrue;
name = font->getName();
psName = NULL;
if (name) {
getPSFont16(font->getName(),
((GfxCIDFont *)font)->getCollection(),
font->getWMode()))) {
+ subst = gTrue;
psName = fontParam->psFontName->getCString();
if (font16EncLen >= font16EncSize) {
font16EncSize += 16;
writePSFmt((i == 0) ? "[ " : " ");
for (j = 0; j < 8; ++j) {
if (font->getType() == fontTrueType &&
+ !subst &&
!((Gfx8BitFont *)font)->getHasEncoding()) {
sprintf(buf, "c%02x", i+j);
charName = buf;
// convert it to a Type 1 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
t1cFile = new Type1CFontFile(fontBuf, fontLen);
- t1cFile->convertToType1(outputFunc, outputStream);
+ if (t1cFile->isOk()) {
+ t1cFile->convertToType1(outputFunc, outputStream);
+ }
delete t1cFile;
gfree(fontBuf);
ctu = ((Gfx8BitFont *)font)->getToUnicode();
ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
+ ((Gfx8BitFont *)font)->isSymbolic(),
outputFunc, outputStream);
ctu->decRefCnt();
delete ttFile;
ctu = ((Gfx8BitFont *)font)->getToUnicode();
ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
+ ((Gfx8BitFont *)font)->isSymbolic(),
outputFunc, outputStream);
ctu->decRefCnt();
delete ttFile;
// convert it to a Type 0 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
t1cFile = new Type1CFontFile(fontBuf, fontLen);
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- t1cFile->convertToCIDType0(psName, outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- t1cFile->convertToType0(psName, outputFunc, outputStream);
+ if (t1cFile->isOk()) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ t1cFile->convertToCIDType0(psName, outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ t1cFile->convertToType0(psName, outputFunc, outputStream);
+ }
}
delete t1cFile;
gfree(fontBuf);
PSFont16Enc *font16Enc; // encodings for substitute 16-bit fonts
int font16EncLen; // number of entries in font16Enc array
int font16EncSize; // size of font16Enc array
+ GList *xobjStack; // stack of XObject dicts currently being
+ // processed
double tx, ty; // global translation
double xScale, yScale; // global scaling
//
// PSTokenizer.cc
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//
// PSTokenizer.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Page.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Parser.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
Xpdf
====
-version 0.93
-2001-oct-25
+version 2.02
+2003-mar-24
The Xpdf software and documentation are
-copyright 1996-2001 Derek B. Noonburg.
+copyright 1996-2003 Glyph & Cog, LLC.
Email: derekn@foolabs.com
WWW: http://www.foolabs.com/xpdf/
The PDF data structures, operators, and specification are
-copyright 1995 Adobe Systems Inc.
+copyright 1985-2001 Adobe Systems Inc.
What is Xpdf?
-------------
-Xpdf is a viewer for Portable Document Format (PDF) files. (These are
-also sometimes also called 'Acrobat' files, from the name of Adobe's
-PDF software.) Xpdf runs under the X Window System on UNIX, VMS, and
-OS/2. The non-X components of the package (pdftops, pdftotext, etc.)
-also run on Win32 systems and should run on pretty much any system
-with a decent C++ compiler.
+Xpdf is an open source viewer for Portable Document Format (PDF)
+files. (These are also sometimes also called 'Acrobat' files, from
+the name of Adobe's PDF software.) The Xpdf project also includes a
+PDF text extractor, PDF-to-PostScript converter, and various other
+utilities.
+
+Xpdf runs under the X Window System on UNIX, VMS, and OS/2. The non-X
+components (pdftops, pdftotext, etc.) also run on Win32 systems and
+should run on pretty much any system with a decent C++ compiler.
Xpdf is designed to be small and efficient. It can use Type 1,
TrueType, or standard X fonts.
- If you make useful changes to Xpdf, please make the source code
available -- post it on a web site, email it to me, whatever.
-If you're interested in commercial licensing, please contact me by
-email: derekn@foolabs.com .
+If you're interested in commercial licensing, please see the Glyph &
+Cog web site:
+
+ http://www.glyphandcog.com/
Compatibility
much any system which runs X11 and has Unix-like libraries. You'll
need ANSI C++ and C compilers to compile it.
-The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdfimages)
-can also be compiled on Win32 systems. See the Xpdf web page for
-details.
+The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdffonts,
+pdfimages) can also be compiled on Win32 systems. See the Xpdf web
+page for details.
If you compile Xpdf for a system not listed on the web page, please
let me know. If you're willing to make your binary available by ftp
pdftotext file.pdf
-There are three additional utilities (which are fully described in
+There are four additional utilities (which are fully described in
their man pages):
pdfinfo -- dumps a PDF file's Info dictionary (plus some other
useful information)
+ pdffonts -- lists the fonts used in a PDF file along with various
+ information for each font
pdftopbm -- converts a PDF file to a series of PBM-format bitmaps
pdfimages -- extracts the images from a PDF file
pages (xpdf.1, etc.) and the VMS help files (xpdf.hlp, etc.).
+Upgrading from Xpdf 0.9x
+------------------------
+
+WARNING: Xpdf 1.x switched to a completely different config file setup
+than Xpdf 0.9x.
+
+Many of the configuration options that used to be X resources have
+been moved into the Xpdf config file. There are also lots of new and
+improved options. If you're upgrading from Xpdf 0.9x, please read
+through the sample config file (doc/sample-xpdfrc) and the xpdfrc(5)
+man page.
+
+The Asian language support has been pulled out into separate packages,
+loaded at run time. This is much cleaner than the 0.9x approach -- it
+makes the base distribution smaller, allows the language support
+packages to be upgraded separately, and lets users customize Xpdf for
+other text encodings without modifying the source. See the web site
+(http://www.foolabs.com/xpdf) for info on downloading the language
+support packages.
+
+All of the Xpdf tools, including the X viewer and the command line
+programs, read the same config file. They first attempt to read the
+user's personal config file:
+
+ $HOME/.xpdfrc
+
+If it is not found, the Xpdf tools read a system-wide config file,
+typically something like:
+
+ /usr/local/etc/xpdfrc
+
+(this location can be customized when building Xpdf).
+
+The Win32 command line tools look in the directory containing the
+executable, e.g.:
+
+ C:/Program Files/Xpdf/xpdfrc
+
+Xpdf comes with a "sample-xpdfrc" file in the doc directory. This is
+a good starting point for constructing your own config file.
+
+For full details, please see the xpdfrc(5) man page.
+
+
Fonts
-----
-Xpdf uses X server fonts. It requires the following fonts:
+By default, Xpdf will use X server fonts. It requires the following
+fonts:
* Courier: medium-r, bold-r, medium-o, and bold-o
* Helvetica: medium-r, bold-r, medium-o, and bold-o
* Symbol: medium-r
* Zapf Dingbats: medium-r
-Most X installations should already have all of these fonts, except
-Zapf Dingbats. You can install a Type 1 Zapf Dingbats font -- see the
-mkfontdir(1) man page for details. Use this font descriptor in your
-fonts.scale file:
-
- -itc-zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific
-
-You can get a Type 1 font file from the ghostscript 4.x distribution
-(look for d050000l.pfb).
-
-X servers, starting at R5, support font scaling. Xpdf will
-automatically take advantage of this. There are two types of scaling.
-The first type uses standard bitmap fonts: if a font doesn't exist in
-the requested size, the server will scale the bitmapped characters.
-This is reasonably fast, and the results are readable but not very
-pretty. X servers can also handle true scalable, e.g., Type 1, fonts.
-(See the mkfontdir(1) man page for details on setting these up.)
-Scalable fonts are slower, especially since PDF documents tend to use
-lots of fonts, but they look much nicer.
-
-Some X servers also support font rotation. Xpdf will use this feature
-if available.
-
-For Japanese support, you will need a Japanese font of the form:
-
- -*-fixed-medium-r-normal-*-NN-*-*-*-*-*-jisx0208.1983-0
-
-and an X server that can handle 16-bit fonts. You can also set this
-font using the xpdf.japaneseFont resource.
-
-For Chinese GB (simplified Chinese) support, you will need a font of
-the form:
-
- -*-fangsong ti-medium-r-normal-*-%s-*-*-*-*-*-gb2312.1980-0
-
-You can replace this font using the xpdf.chineseGBFont resource.
-
-For Chinese CNS (traditional Chinese) support, you will need a font of
-the form:
-
- -*-fixed-medium-r-normal--*-%s-*-*-*-*-big5-0
-
-You can replace this font using the xpdf.chineseCNSFont resource.
-
-If compiled with t1lib support, xpdf will use t1lib to render embedded
-Type 1 and Type 1C fonts. In addition, xpdf can be configured to use
-t1lib for the base 14 fonts and for substituted fonts. To enable this
-feature, you must set an X resource for each Type 1 font file. For
-example:
-
- xpdf.t1TimesRoman: /usr/local/fonts/Times-Roman.pfa
- xpdf.t1TimesItalic: /usr/local/fonts/Times-Italic.pfa
- xpdf.t1TimesBold: /usr/local/fonts/Times-Bold.pfa
- xpdf.t1TimesBoldItalic: /usr/local/fonts/Times-BoldItalic.pfa
- xpdf.t1Helvetica: /usr/local/fonts/Helvetica.pfa
- xpdf.t1HelveticaOblique: /usr/local/fonts/Helvetica-Oblique.pfa
- xpdf.t1HelveticaBold: /usr/local/fonts/Helvetica-Bold.pfa
- xpdf.t1HelveticaBoldOblique: /usr/local/fonts/Helvetica-BoldOblique.pfa
- xpdf.t1Courier: /usr/local/fonts/Courier.pfa
- xpdf.t1CourierOblique: /usr/local/fonts/Courier-Oblique.pfa
- xpdf.t1CourierBold: /usr/local/fonts/Courier-Bold.pfa
- xpdf.t1CourierBoldOblique: /usr/local/fonts/Courier-BoldOblique.pfa
- xpdf.t1Symbol: /usr/local/fonts/Symbol.pfa
- xpdf.t1ZapfDingbats: /usr/local/fonts/ZapfDingbats.pfa
-
-Ghostscript comes with a set of free, high-quality Type 1 fonts,
-donated by URW++ Design and Development Incorporated. The xpdf X
-resources needed for these fonts are:
-
- xpdf.t1TimesRoman: /usr/ghostscript/fonts/n021003l.pfb
- xpdf.t1TimesItalic: /usr/ghostscript/fonts/n021023l.pfb
- xpdf.t1TimesBold: /usr/ghostscript/fonts/n021004l.pfb
- xpdf.t1TimesBoldItalic: /usr/ghostscript/fonts/n021024l.pfb
- xpdf.t1Helvetica: /usr/ghostscript/fonts/n019003l.pfb
- xpdf.t1HelveticaOblique: /usr/ghostscript/fonts/n019023l.pfb
- xpdf.t1HelveticaBold: /usr/ghostscript/fonts/n019004l.pfb
- xpdf.t1HelveticaBoldOblique: /usr/ghostscript/fonts/n019024l.pfb
- xpdf.t1Courier: /usr/ghostscript/fonts/n022003l.pfb
- xpdf.t1CourierOblique: /usr/ghostscript/fonts/n022023l.pfb
- xpdf.t1CourierBold: /usr/ghostscript/fonts/n022004l.pfb
- xpdf.t1CourierBoldOblique: /usr/ghostscript/fonts/n022024l.pfb
- xpdf.t1Symbol: /usr/ghostscript/fonts/s050000l.pfb
- xpdf.t1ZapfDingbats: /usr/ghostscript/fonts/d050000l.pfb
-
-You will obviously need to replace '/usr/ghostscript/fonts' with the
+Most X installations should already have all of these fonts (except
+maybe Zapf Dingbats).
+
+If Xpdf is built with support for t1lib (or FreeType 2), you can get
+much higher quality text by using Type 1 fonts instead of X server
+fonts. For example, you can use the Type 1 fonts that come with
+ghostscript. To do this, add the following lines to the xpdfrc file
+(e.g., /usr/local/etc/xpdfrc or $HOME/.xpdfrc):
+
+displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+
+You will need to replace '/usr/local/share/ghostscript/fonts' with the
appropriate path on your system.
-The Unisys LZW Patent
----------------------
-
-Nearly all PDF files include data which has been compressed with the
-LZW compression algorithm. Unfortunately, LZW is covered by a
-software patent which is owned by Unisys Corporation. Unisys refuses
-to license this patent for PDF-related use in software such as Xpdf
-which is released for free and which may be freely redistributed.
-(This is same algorithm which is used by GIF. However, Unisys is not
-doing licensing for free PDF viwers in the same way as for free GIF
-viewers.)
-
-As a workaround, Xpdf converts PDF-format LZW data to compress-format
-LZW data. (The standard UNIX compress utility also uses LZW, but with
-a slightly different file format.) This conversion does *not*
-decompress the data; it simply converts it to a different file format.
-Xpdf then calls uncompress to actually decompress the data.
-
-I have been told by several notable people that the LZW patent covers
-compression only, and does not cover decompression. This seems pretty
-fuzzy to me, so I'm going to stick with my workaround, at least for
-now.
-
-For Unisys's slant on things (mostly regarding GIF), see
-<http://www.unisys.com/LeadStory/lzwterms.html> and
-<http://www.unisys.com/LeadStory/lzwfaq.html>. These pages mention
-an email address for feedback.
-
-
Compiling Xpdf
--------------
Bugs
----
-Type 3 fonts are still not well supported by Xpdf.
-
If you find a bug in Xpdf, i.e., if it prints an error message,
crashes, or incorrectly displays a document, and you don't see that
bug listed here, please send me email, with a pointer (URL, ftp site,
* Brendan Miller for the icon idea.
* Olly Betts for help testing pdftotext.
* Peter Ganten for the OS/2 port.
-* Michael Richmond for the Win32 port of pdftops and pdftotext.
+* Michael Richmond for the Win32 port of pdftops and pdftotext and the
+ xpdf/cygwin/XFree86 build instructions.
* Frank M. Siegert for improvements in the PostScript code.
* Leo Smiers for the decryption patches.
* Rainer Menzner for creating t1lib, and for helping me adapt it to
* Pine Tree Systems A/S for funding the OPI and EPS support in
pdftops.
* Easy Software Products for funding the "sh" operator support.
+* Tom Kacvinsky for help with FreeType and for being my interface to
+ the FreeType team.
+* Theppitak Karoonboonyanan for help with Thai support.
+* Leonard Rosenthol for help and contributions on a bunch of things.
+* Alexandros Diamantidis and Maria Adaloglou for help with Greek
+ support.
+* Lawrence Lai for help with the CJK Unicode maps.
+
+Various people have contributed modifications made for use by the
+pdftex project:
+
+* Han The Thanh
+* Martin Schröder of ArtCom GmbH
References
----------
-Adobe Systems Inc., _PDF Reference_, 2nd ed.
-Addison-Wesley, 2000, ISBN 0-201-61588-6.
-[The printed manual for PDF version 1.3.]
+Adobe Systems Inc., _PDF Reference: Adobe Portable Document Format
+version 1.4_, 3nd ed.
+Addison-Wesley, 2001, ISBN 0-201-75839-3.
+http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDFReference.pdf
+[The printed manual for PDF version 1.4.]
Adobe Systems Inc., _Portable Document Format: Changes from Version
1.3 to 1.4_, Adobe Developer Support Technical Note #5409.
http://www.adobe.com/supportservice/devrelations/PDFS/TN/5014.CIDFont_Spec.pdf
[CMap file format needed for Japanese and Chinese font support.]
-Adobe Systems, Inc., _Adobe-Japan1-2 Character Collection for
+Adobe Systems, Inc., _Adobe-Japan1-4 Character Collection for
CID-Keyed Fonts_, Adobe Developer Support Technical Note #5078.
-1994.
+2000.
http://partners.adobe.com/asn/developer/PDFS/TN/5078.CID_Glyph.pdf
[The Adobe Japanese character set.]
-Adobe Systems, Inc., _Adobe-GB1-3 Character Collection for
+Adobe Systems, Inc., _Adobe-GB1-4 Character Collection for
CID-Keyed Fonts_, Adobe Developer Support Technical Note #5079.
-1998.
-http://partners.adobe.com/asn/developer/PDFS/TN/5079.GB_CharColl.pdf
-[The Adobe Chinese GB character set.]
+2000.
+http://partners.adobe.com/asn/developer/pdfs/tn/5079.Adobe-GB1-4.pdf
+[The Adobe Chinese GB (simplified) character set.]
Adobe Systems, Inc., _Adobe-CNS1-3 Character Collection for
CID-Keyed Fonts_, Adobe Developer Support Technical Note #5080.
2000.
http://partners.adobe.com/asn/developer/PDFS/TN/5080.CNS_CharColl.pdf
-[The Adobe Chinese CNS character set.]
+[The Adobe Chinese CNS (traditional) character set.]
Adobe Systems Inc., _Supporting the DCT Filters in PostScript Level
2_, Adobe Developer Support Technical Note #5116. 1992.
ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/
[The actual CMap files for the 16-bit CJK encodings.]
+Adobe Systems Inc., Unicode glyph lists.
+http://partners.adobe.com/asn/developer/type/unicodegn.html
+http://partners.adobe.com/asn/developer/type/glyphlist.txt
+http://partners.adobe.com/asn/developer/type/corporateuse.txt
+http://partners.adobe.com/asn/developer/type/zapfdingbats.txt
+[Mappings between character names to Unicode.]
+
Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_. 1993.
http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf
ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz
[This is the algorithm used to encrypt PDF files.]
-CCITT, _Blue Book_, Volume VII Fascicle 3: "Terminal Equipment and
-Protocols for Telematic Services", Recommendations T.4 and T.6.
-ftp://ftp.uu.net/doc/standards/ccitt/1988/7_3_01.ps
-ftp://ftp.uu.net/doc/standards/ccitt/1988/7_3_02.ps
-[The official Group 3 and 4 fax standards. The online copies are
-unfortunately misformatted.]
+T. Boutell, et al., "PNG (Portable Network Graphics) Specification,
+Version 1.0. RFC 2083.
+[PDF uses the PNG filter algorithms.]
+
+CCITT, "Information Technology - Digital Compression and Coding of
+Continuous-tone Still Images - Requirements and Guidelines", CCITT
+Recommendation T.81.
+http://www.w3.org/Graphics/JPEG/
+[The official JPEG spec.]
+
+A. Chernov, "Registration of a Cyrillic Character Set". RFC 1489.
+[Documentation for the KOI8-R Cyrillic encoding.]
+
+Roman Czyborra, "The ISO 8859 Alphabet Soup".
+http://czyborra.com/charsets/iso8859.html
+[Documentation on the various ISO 859 encodings.]
L. Peter Deutsch, "ZLIB Compressed Data Format Specification version
3.3". RFC 1950.
Communications_. Ziff-Davis Press, 1993, ISBN 1-56276-077-7.
[CCITT Group 3 and 4 fax decoding.]
+ISO/IEC, _Information technology -- Lossy/lossless coding of bi-level
+images_. ISO/IEC 14492, First edition (2001-12-15).
+http://webstore.ansi.org/
+[The official JBIG2 standard. The final draft of this spec is
+available from http://www.jpeg.org/jbighomepage.html.]
+
+ITU, "Standardization of Group 3 facsimile terminals for document
+transmission", ITU-T Recommendation T.4, 1999.
+ITU, "Facsimile coding schemes and coding control functions for Group 4
+facsimile apparatus", ITU-T Recommendation T.6, 1993.
+http://www.itu.int/
+[The official Group 3 and 4 fax standards - used by the CCITTFaxDecode
+stream, as well as the JBIG2Decode stream.]
+
Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, "Practical
Fast 1-D DCT Algorithms with 11 Multiplications". IEEE Intl. Conf. on
Acoustics, Speech & Signal Processing, 1989, 988-991.
http://www.microsoft.com/typography/tt/tt.htm
[The TrueType font spec (in MS Word format, naturally).]
+Thai Industrial Standard, "Standard for Thai Character Codes for
+Computers", TIS-620-2533 (1990).
+http://www.nectec.or.th/it-standards/std620/std620.htm
+[The TIS-620 Thai encoding.]
+
+P. Peterlin, "ISO 8859-2 (Latin 2) Resources".
+http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html
+[This is a web page with all sorts of useful Latin-2 character set and
+font information.]
+
Charles Poynton, "Color FAQ".
http://www.inforamp.net/~poynton/ColorFAQ.html
[The mapping from the CIE 1931 (XYZ) color space to RGB.]
R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321.
[MD5 is used in PDF document encryption.]
-Gregory K. Wallace, "The JPEG Still Picture Compression Standard".
-ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz
-[Good description of the JPEG standard. Also published in CACM, April
-1991, and submitted to IEEE Transactions on Consumer Electronics.]
+Unicode Consortium, "Unicode Home Page".
+http://www.unicode.org/
+[Online copy of the Unicode spec.]
W3C Recommendation, "PNG (Portable Network Graphics) Specification
Version 1.0".
http://www.w3.org/Graphics/PNG/
[Defines the PNG image predictor.]
-"ISO 8859-2 (Latin 2) Resources".
-http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html
-[This is a web page with all sorts of useful Latin-2 character set and
-font information.]
+Gregory K. Wallace, "The JPEG Still Picture Compression Standard".
+ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz
+[Good description of the JPEG standard. Also published in CACM, April
+1991, and submitted to IEEE Transactions on Consumer Electronics.]
+
+F. Yergeau, "UTF-8, a transformation format of ISO 10646". RFC 2279.
+[A commonly used Unicode encoding.]
//
// Stream.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
// Read one scan from a progressive or non-interleaved JPEG stream.
void DCTStream::readScan() {
int data[64];
- int x1, y1, dy1, x2, y2, y3, cc, i;
+ int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
int h, v, horiz, vert, hSub, vSub;
int *p1;
int c;
break;
}
}
+ dx1 = mcuWidth / compInfo[cc].hSample;
dy1 = mcuHeight / compInfo[cc].vSample;
} else {
+ dx1 = mcuWidth;
dy1 = mcuHeight;
}
- for (y1 = 0; y1 < bufHeight; y1 += dy1) {
- for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
+ for (y1 = 0; y1 < height; y1 += dy1) {
+ for (x1 = 0; x1 < width; x1 += dx1) {
// deal with restart marker
if (restartInterval > 0 && restartCtr == 0) {
hSub = horiz / 8;
vSub = vert / 8;
for (y2 = 0; y2 < dy1; y2 += vert) {
- for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
+ for (x2 = 0; x2 < dx1; x2 += horiz) {
// pull out the current values
p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
return gFalse;
}
i += run;
- j = dctZigZag[i++];
- data[j] = amp;
+ if (i < 64) {
+ j = dctZigZag[i++];
+ data[j] = amp;
+ }
}
}
return gTrue;
eobRun = 0;
for (k = 0; k < j; ++k) {
if ((bit = readBit()) == EOF) {
- return 9999;
+ return gFalse;
}
eobRun = (eobRun << 1) | bit;
}
int len, repeat, code;
int i;
+ codeLenCodeTab.codes = NULL;
+
// read lengths
if ((numLitCodes = getCodeWord(5)) == EOF) {
goto err;
if ((repeat = getCodeWord(2)) == EOF) {
goto err;
}
- for (repeat += 3; repeat > 0; --repeat) {
+ repeat += 3;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
+ for (; repeat > 0; --repeat) {
codeLengths[i++] = len;
}
} else if (code == 17) {
if ((repeat = getCodeWord(3)) == EOF) {
goto err;
}
+ repeat += 3;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
len = 0;
- for (repeat += 3; repeat > 0; --repeat) {
+ for (; repeat > 0; --repeat) {
codeLengths[i++] = 0;
}
} else if (code == 18) {
if ((repeat = getCodeWord(7)) == EOF) {
goto err;
}
+ repeat += 11;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
len = 0;
- for (repeat += 11; repeat > 0; --repeat) {
+ for (; repeat > 0; --repeat) {
codeLengths[i++] = 0;
}
} else {
//
// UnicodeMap.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
//
// XRef.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
if (obj2.isInt()) {
*pos = (Guint)obj2.getInt();
more = gTrue;
+ } else if (obj2.isRef()) {
+ // certain buggy PDF generators generate "/Prev NNN 0 R" instead
+ // of "/Prev NNN"
+ *pos = (Guint)obj2.getRefNum();
+ more = gTrue;
} else {
more = gFalse;
}
//------------------------------------------------------------------------
// xpdf version
-#define xpdfVersion "2.01"
-#define xpdfVersionNum 2.01
+#define xpdfVersion "2.02pl1"
+#define xpdfVersionNum 2.02
#define xpdfMajorVersion 2
-#define xpdfMinorVersion 1
+#define xpdfMinorVersion 2
#define xpdfMajorVersionStr "2"
+#define xpdfMinorVersionStr "2"
// supported PDF version
#define supportedPDFVersionStr "1.4"
#define xpdfCopyright "Copyright 1996-2003 Glyph & Cog, LLC"
// Windows resource file stuff
-#define winxpdfVersion "WinXpdf 2.01"
+#define winxpdfVersion "WinXpdf 2.02"
#define xpdfCopyrightAmp "Copyright 1996-2003 Glyph && Cog, LLC"
//------------------------------------------------------------------------
//
// Miscellaneous file and directory name manipulation.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//
// Use gmalloc/gfree for C++ new/delete operators.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================