]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Mirror 1.1.x change.
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sun, 20 Jul 2003 00:40:06 +0000 (00:40 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sun, 20 Jul 2003 00:40:06 +0000 (00:40 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/branches/branch-1.2@3797 7a7537e8-13f0-0310-91df-b6672ffda945

51 files changed:
CHANGES-1.1.txt
pdftops/Array.cxx
pdftops/BuiltinFont.cxx
pdftops/BuiltinFontTables.cxx
pdftops/CMap.cxx
pdftops/Catalog.cxx
pdftops/CharCodeToUnicode.cxx
pdftops/Decrypt.cxx
pdftops/Dependencies
pdftops/Dict.cxx
pdftops/Error.cxx
pdftops/ErrorCodes.h
pdftops/FontEncodingTables.cxx
pdftops/FontFile.cxx
pdftops/FontFile.h
pdftops/Function.cxx
pdftops/GHash.cxx
pdftops/GList.cxx
pdftops/GString.cxx
pdftops/Gfx.cxx
pdftops/GfxFont.cxx
pdftops/GfxState.cxx
pdftops/GlobalParams.cxx
pdftops/GlobalParams.h
pdftops/JBIG2Stream.cxx
pdftops/JBIG2Stream.h
pdftops/Lexer.cxx
pdftops/Link.cxx
pdftops/Makefile
pdftops/NameToCharCode.cxx
pdftops/Object.cxx
pdftops/Outline.cxx
pdftops/Outline.h
pdftops/OutputDev.cxx
pdftops/OutputDev.h
pdftops/PDFDoc.cxx
pdftops/PDFDocEncoding.cxx
pdftops/PDFDocEncoding.h
pdftops/PSOutputDev.cxx
pdftops/PSOutputDev.h
pdftops/PSTokenizer.cxx
pdftops/PSTokenizer.h
pdftops/Page.cxx
pdftops/Parser.cxx
pdftops/README
pdftops/Stream.cxx
pdftops/UnicodeMap.cxx
pdftops/XRef.cxx
pdftops/config.h
pdftops/gfile.cxx
pdftops/gmempp.cxx

index 0126324af47037991e0d66e65976d36a5397d483..3d613d12c6dd02b41e9c73e9944dbeb158eaa01c 100644 (file)
@@ -3,6 +3,8 @@ CHANGES-1.1.txt
 
 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
index aa97ab20de6c9bfe88080205abb649b878d93493..e8b1a94285494b928b7cb62243891037b37d5978 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Array.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -12,6 +12,7 @@
 #pragma implementation
 #endif
 
+#include <stdlib.h>
 #include <stddef.h>
 #include "gmem.h"
 #include "Object.h"
@@ -46,9 +47,23 @@ void Array::add(Object *elem) {
 }
 
 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);
 }
index 0525ab8ae50095afe6be8719c25d8737226c262e..4152812302f7aaa3ba89261961bb3fc8b54b3305 100644 (file)
@@ -2,7 +2,7 @@
 //
 // BuiltinFont.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 169fd6fdfd9ff455fc210cac7ea0554424aa1b4b..af05e3bef9fbcabdc959b79b5d46718425519813 100644 (file)
@@ -2,7 +2,7 @@
 //
 // BuiltinFontTables.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 28dc3eae2b380004c9b2fac4b60add62e2312db8..36af0f27825ccffce580abbfdec9420096e373d4 100644 (file)
@@ -2,7 +2,7 @@
 //
 // CMap.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 80b2320b034866bf555564b45d0c6525a0af670a..e116cc4fe2ef023efb2c0a868b656e566a395407 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Catalog.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 8d527a3abac35b054d7d19d5ea4f344a2071126e..f28ad51789b3c6c7badffaa0ec34fdfe5db822ae 100644 (file)
@@ -2,7 +2,7 @@
 //
 // CharCodeToUnicode.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 93caa5e783a3838e33c2f055938d9bb6658c28f4..a076ed152803a9a96d720774d210a09325939871 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Decrypt.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index cae0cfc559f6dfdf14a9a36587ae427768e652da..560d06b24c8cbe4d6259650afb07fe664a6b88af 100644 (file)
@@ -1,87 +1,89 @@
 # 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
index c773637a868461e6b08d481318d7205be1451513..57ca2c334343b00b6fef355c171e9a0616566aa2 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Dict.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 5f6ea93786f7c78bf16069ffb20f1db1d6be1829..6315c721f0489e762aeffa9691f3cf352f49a5f5 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Error.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 4e0d38a6632d3651ff1b98c9965b83817085bdb7..8de2b01b880a188649bcdfe7176cd9418fe9c720 100644 (file)
@@ -2,7 +2,7 @@
 //
 // ErrorCodes.h
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -21,4 +21,6 @@
 #define errEncrypted        4  // file was encrypted and password was
                                // incorrect or not supplied
 
+#define errHighlightFile    5  // nonexistent or invalid highlight file
+
 #endif
index 289d0c8d61aeafb59d2dbf7ad4aef534cb1d5fab..6ebef787421f28f525ed7452cfb927c49d3d12f5 100644 (file)
@@ -2,7 +2,7 @@
 //
 // FontEncodingTables.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 91700e0f61ad40cdc2a87958468e894401726b0a..084e4727e550061681bb8f09630d3d9ab2433abd 100644 (file)
@@ -2,7 +2,7 @@
 //
 // FontFile.cc
 //
-// Copyright 1999-2002 Glyph & Cog, LLC
+// Copyright 1999-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -190,31 +190,38 @@ struct Type1CPrivateDict {
 };
 
 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() {
@@ -235,14 +242,14 @@ const char *Type1CFontFile::getName() {
 
 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;
@@ -260,16 +267,20 @@ void Type1CFontFile::readNameAndEncoding() {
   }
 
   // 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];
@@ -280,7 +291,7 @@ void Type1CFontFile::readNameAndEncoding() {
       }
       i = 0;
     } else {
-      x = getNum(&ptr, &isFP);
+      x = getNum(&pos, &isFP);
       if (i < 48) {
        op[i++] = x;
       }
@@ -288,7 +299,7 @@ void Type1CFontFile::readNameAndEncoding() {
   }
 
   // get number of glyphs from charstrings index
-  nGlyphs = getIndexLen((Guchar *)file + charstrings);
+  nGlyphs = getIndexLen(charstrings);
 
   // read charset (GID -> name mapping)
   glyphNames = readCharset(charset, nGlyphs);
@@ -307,24 +318,45 @@ void Type1CFontFile::readNameAndEncoding() {
       }
     }
   } 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;
@@ -332,17 +364,27 @@ void Type1CFontFile::readNameAndEncoding() {
       }
     }
     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);
   }
 }
@@ -352,12 +394,12 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
   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;
@@ -365,9 +407,6 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
   // 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());
@@ -447,7 +486,7 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
   }
 
   // get number of glyphs from charstrings index
-  nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
+  nGlyphs = getIndexLen(dict.charStrings);
 
   // read charset
   glyphNames = readCharset(dict.charset, nGlyphs);
@@ -468,15 +507,24 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
        }
       }
     } 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);
@@ -484,11 +532,17 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
          (*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));
@@ -501,11 +555,17 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
        }
       }
       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);
@@ -513,6 +573,7 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
          (*outputFunc)(outputStream, " put\n", 5);
        }
       }
+     err0:;
     }
     (*outputFunc)(outputStream, "readonly def\n", 13);
   }
@@ -537,41 +598,21 @@ void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
   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");
@@ -606,7 +647,7 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
   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;
@@ -635,29 +676,36 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
     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;
@@ -676,8 +724,9 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
   }
 
   // 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);
@@ -686,19 +735,31 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
       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;
        }
@@ -728,23 +789,30 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
     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();
@@ -831,8 +899,6 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
   }
   (*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",
@@ -873,15 +939,20 @@ void Type1CFontFile::convertToCIDType0(const char *psName,
     (*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,
@@ -892,7 +963,7 @@ 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;
@@ -900,7 +971,7 @@ void Type1CFontFile::convertToType0(const char *psName,
   int key;
   double x;
   GBool isFP;
-  int i, j, n;
+  int i, j;
 
   outputFunc = outputFuncA;
   outputStream = outputStreamA;
@@ -920,29 +991,36 @@ void Type1CFontFile::convertToType0(const char *psName,
     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;
@@ -961,8 +1039,9 @@ void Type1CFontFile::convertToType0(const char *psName,
   }
 
   // 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);
@@ -971,19 +1050,31 @@ void Type1CFontFile::convertToType0(const char *psName,
       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;
        }
@@ -1013,6 +1104,10 @@ void Type1CFontFile::convertToType0(const char *psName,
     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) {
 
@@ -1074,24 +1169,28 @@ void Type1CFontFile::convertToType0(const char *psName,
     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");
@@ -1136,24 +1235,27 @@ void Type1CFontFile::convertToType0(const char *psName,
   (*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;
@@ -1188,13 +1290,19 @@ void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
   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;
@@ -1234,7 +1342,7 @@ void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
       }
       i = 0;
     } else {
-      x = getNum(&ptr, &isFP);
+      x = getNum(&pos, &isFP);
       if (i < 48) {
        op[i] = x;
        fp[i++] = isFP;
@@ -1245,7 +1353,7 @@ void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
 
 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
                                     int offset, int size) {
-  Guchar *idxPtr0, *idxPtr1, *ptr;
+  int pos;
   char eBuf[256];
   int key;
   double x;
@@ -1258,15 +1366,19 @@ void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
   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:
@@ -1349,7 +1461,7 @@ void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
       }
       i = 0;
     } else {
-      x = getNum(&ptr, &isFP);
+      x = getNum(&pos, &isFP);
       if (i < 48) {
        op[i] = x;
        fp[i++] = isFP;
@@ -1360,7 +1472,7 @@ void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
 
 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
   Gushort *glyphNames;
-  Guchar *ptr;
+  int pos;
   int charsetFormat, c;
   int nLeft, i, j;
 
@@ -1372,20 +1484,31 @@ Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
     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++;
        }
@@ -1393,16 +1516,20 @@ Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
     } 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;
 }
 
@@ -1423,10 +1550,10 @@ void Type1CFontFile::eexecWrite(const char *s) {
   }
 }
 
-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());
@@ -1434,28 +1561,37 @@ void Type1CFontFile::eexecCvtGlyph(const char *glyphName, Guchar *s, int n) {
   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;
@@ -1564,19 +1700,19 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
       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) {
@@ -1587,11 +1723,11 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
       }
       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) {
@@ -1602,8 +1738,11 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
       }
       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;
       }
@@ -1612,12 +1751,39 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        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);
@@ -1668,9 +1834,9 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        }
        break;
       case 14:                 // endchar / seac
-       if (first) {
+       if (firstOp) {
          cvtGlyphWidth(nOps == 1 || nOps == 5);
-         first = gFalse;
+         firstOp = gFalse;
        }
        if (nOps == 4) {
          eexecDumpNum(0, 0);
@@ -1686,9 +1852,9 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        }
        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);
@@ -1698,9 +1864,9 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        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);
@@ -1871,9 +2037,9 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        }
        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);
@@ -1899,9 +2065,9 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        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);
@@ -1928,9 +2094,9 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        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);
@@ -1939,49 +2105,56 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
        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;
@@ -1991,11 +2164,13 @@ void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
   }
 
   // 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;
+    }
   }
 }
 
@@ -2130,42 +2305,71 @@ void Type1CFontFile::getDeltaReal(char *buf, const char *key, double *opA,
   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;
@@ -2174,20 +2378,31 @@ double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
 
   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) {
@@ -2221,32 +2436,35 @@ double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
     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;
 }
@@ -2640,6 +2858,10 @@ TrueTypeFontFile::TrueTypeFontFile(const char *fileA, int lenA) {
     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;
   }
 
@@ -2712,9 +2934,7 @@ const char *TrueTypeFontFile::getName() {
 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;
@@ -2736,6 +2956,8 @@ const char **TrueTypeFontFile::getEncoding() {
 
     // 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);
@@ -2752,56 +2974,17 @@ const char **TrueTypeFontFile::getEncoding() {
 
     // 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;
     }
   }
 
@@ -2840,9 +3023,13 @@ const char **TrueTypeFontFile::getEncoding() {
                   ++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;
          }
@@ -2884,6 +3071,7 @@ const char **TrueTypeFontFile::getEncoding() {
 void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
                                       CharCodeToUnicode *toUnicode,
                                       GBool pdfFontHasEncoding,
+                                      GBool pdfFontIsSymbolic,
                                       FontFileOutputFunc outputFunc,
                                       void *outputStream) {
   char buf[512];
@@ -2906,7 +3094,7 @@ void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
 
   // 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);
 
@@ -3163,7 +3351,7 @@ int TrueTypeFontFile::seekTable(const char *tag) {
 
   for (i = 0; i < nTables; ++i) {
     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
-      return tableHdrs[i].offset;
+      return (int)tableHdrs[i].offset;
     }
   }
   return -1;
@@ -3174,6 +3362,9 @@ int TrueTypeFontFile::seekTableIdx(const char *tag) {
 
   for (i = 0; i < nTables; ++i) {
     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
+      if (tableHdrs[i].offset == (Guint)-1) {
+       return -1;
+      }
       return i;
     }
   }
@@ -3210,6 +3401,7 @@ void TrueTypeFontFile::cvtEncoding(const char **encodingA, GBool pdfFontHasEncod
 void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
                                      CharCodeToUnicode *toUnicode,
                                      GBool pdfFontHasEncoding,
+                                     GBool pdfFontIsSymbolic,
                                      FontFileOutputFunc outputFunc,
                                      void *outputStream) {
   int unicodeCmap, macRomanCmap, msSymbolCmap;
@@ -3234,7 +3426,9 @@ void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
   // 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:
@@ -3250,7 +3444,7 @@ void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
   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;
@@ -3264,6 +3458,10 @@ void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
     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;
@@ -3291,8 +3489,11 @@ void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
   // 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 {
@@ -3303,24 +3504,26 @@ void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
       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);
@@ -3369,6 +3572,9 @@ int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
     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 {
@@ -3423,9 +3629,13 @@ void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
   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");
@@ -3443,6 +3653,9 @@ void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
   }
   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) {
@@ -3492,8 +3705,12 @@ void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
        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) {
@@ -3585,7 +3802,8 @@ void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
       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);
        }
@@ -3595,8 +3813,11 @@ void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
       // 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);
+       }
       }
     }
   }
@@ -3697,209 +3918,265 @@ void TrueTypeFontFile::writeTTF(FILE *out) {
   };
   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);
+  }
 }
index f40e998e6635d88049b971bc58352b9b86ab20b1..fddc8d5119c5a7fc8114063f8d4b91683910612d 100644 (file)
@@ -75,6 +75,7 @@ public:
 
   Type1CFontFile(const char *fileA, int lenA);
   virtual ~Type1CFontFile();
+  GBool isOk() { return ok; }
 
   virtual const char *getName();
   virtual const char **getEncoding();
@@ -97,14 +98,14 @@ public:
 
 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);
@@ -112,29 +113,33 @@ private:
   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
@@ -142,6 +147,8 @@ private:
   Gushort r1;                  // eexec encryption key
   GString *charBuf;            // charstring output buffer
   int line;                    // number of eexec chars on current line
+
+  GBool ok;
 };
 
 //------------------------------------------------------------------------
@@ -171,6 +178,7 @@ public:
   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
@@ -217,7 +225,7 @@ private:
   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,
index 6882941fde1eea0697d8f191cecbaf6822fc666f..19c4451867b7d2b6d883b5a91a1d1fe0c92b8dac 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Function.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -412,7 +412,6 @@ void SampledFunction::transform(double *in, double *out) {
 
 ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
   Object obj1, obj2;
-  GBool hasN;
   int i;
 
   ok = gFalse;
@@ -425,23 +424,14 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
     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()) {
@@ -451,15 +441,19 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
       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;
     }
@@ -472,6 +466,12 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
       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();
 
@@ -483,13 +483,6 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
   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;
 
index b3182653ab8099ecab065321820bcb3a0ef88a68..756580401b150ebf82d9e7271ec9782651ae9d57 100644 (file)
@@ -2,7 +2,7 @@
 //
 // GHash.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index de3a4ed6b88c6c1924577a2d048d1a361b633b2a..50c9bcfa743d9673ed51d0080e99d52b046879ee 100644 (file)
@@ -2,7 +2,7 @@
 //
 // GList.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 1291a27b25d031608863c25ec633a68f1e101060..f17599aa323ef864e0db50f0799a86cc5905c542 100644 (file)
@@ -4,7 +4,7 @@
 //
 // Simple variable-length string type.
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index d05d51562d3c4793831e50a77549f28698d04274..0ea019bea34696a271be547112216af576a0150a 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Gfx.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 376403c453d3037193a668b89af1ffee96c96c48..071710ff2b80de75759316aad59f57b2915a90b4 100644 (file)
@@ -2,7 +2,7 @@
 //
 // GfxFont.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -35,6 +35,11 @@ struct StdFontMapEntry {
   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" },
@@ -304,11 +309,14 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits) {
 }
 
 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);
     }
   }
 }
@@ -396,10 +404,8 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
   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);
@@ -553,14 +559,18 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
        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;
       }
@@ -713,6 +723,9 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
   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()) {
@@ -827,12 +840,12 @@ Dict *Gfx8BitFont::getResources() {
 // 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;
 }
index 51e9326ac1cfd1d812b07a5806aa5d9dc22c1e44..a9e8836babf1590c1eadc9c3ee6c31499637c752 100644 (file)
@@ -2,7 +2,7 @@
 //
 // GfxState.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 0f723f1f6c018d81e9191313d997d8e900b0a941..507ca3675ada0ad5d706814b647975d5b1d22e8b 100644 (file)
@@ -2,7 +2,7 @@
 //
 // GlobalParams.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -357,6 +357,12 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
       } 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")) {
@@ -1076,25 +1082,17 @@ GBool GlobalParams::getTextKeepTinyChars() {
 }
 
 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;
@@ -1241,7 +1239,9 @@ void GlobalParams::setPSImageableArea(int left, int bottom, int right, int top)
 
 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")) {
index 6cb91b4c06df0a988a71571475aaba3e89db752d..99c04745e88c5390a3bce06832109fcb60c098d3 100644 (file)
@@ -157,7 +157,7 @@ public:
   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();
index 25f8756d9f19d9568c3f4e1ebcdf58e2a0ef9066..2b1a3679a0bf6921bdfc96db903912f32199e7de 100644 (file)
@@ -2,7 +2,7 @@
 //
 // JBIG2Stream.cc
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -655,25 +655,22 @@ GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
   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;
   }
@@ -713,22 +710,41 @@ Guint JBIG2HuffmanDecoder::readBit() {
   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++;
   }
@@ -810,7 +826,7 @@ int JBIG2MMRDecoder::getWhiteCode() {
     ++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 {
@@ -825,7 +841,7 @@ int JBIG2MMRDecoder::getWhiteCode() {
       }
       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;
     }
@@ -853,14 +869,14 @@ int JBIG2MMRDecoder::getBlackCode() {
     ++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 {
@@ -875,7 +891,7 @@ int JBIG2MMRDecoder::getBlackCode() {
       }
       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;
     }
@@ -938,6 +954,12 @@ private:
 // JBIG2Bitmap
 //------------------------------------------------------------------------
 
+struct JBIG2BitmapPtr {
+  Guchar *p;
+  int shift;
+  int x;
+};
+
 class JBIG2Bitmap: public JBIG2Segment {
 public:
 
@@ -958,6 +980,8 @@ 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; }
@@ -1032,6 +1056,42 @@ void JBIG2Bitmap::clearToOne() {
   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);
 }
@@ -1365,7 +1425,7 @@ JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
   huffDecoder = new JBIG2HuffmanDecoder();
   mmrDecoder = new JBIG2MMRDecoder();
 
-  segments = new GList();
+  segments = globalSegments = new GList();
   if (globalsStream->isStream()) {
     curStr = globalsStream->getStream();
     curStr->reset();
@@ -1374,7 +1434,6 @@ JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
     mmrDecoder->setStream(curStr);
     readSegments();
   }
-  globalSegments = segments;
 
   segments = NULL;
   curStr = NULL;
@@ -1768,20 +1827,23 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
   } 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) {
@@ -1834,7 +1896,13 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
            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);
@@ -1878,15 +1946,13 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
     // 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,
@@ -1924,7 +1990,7 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
     }
     ex = !ex;
   }
-  
+
   for (i = 0; i < numNewSyms; ++i) {
     delete bitmaps[numInputSyms + i];
   }
@@ -1965,7 +2031,8 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
   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;
@@ -1993,6 +2060,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
   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
@@ -2135,6 +2205,7 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
     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) *
@@ -2158,8 +2229,8 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
       } else {
        symCodeTab[i++].prefixLen = j;
       }
-
     }
+    symCodeTab[numSyms].prefixLen = 0;
     symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
     huffDecoder->buildTable(symCodeTab, numSyms);
     huffDecoder->reset();
@@ -2168,11 +2239,11 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
   } 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,
@@ -2219,7 +2290,7 @@ JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
                                         JBIG2Bitmap **syms,
                                         Guint defPixel, Guint combOp,
                                         Guint transposed, Guint refCorner,
-                                        Guint sOffset,
+                                        int sOffset,
                                         JBIG2HuffmanTable *huffFSTable,
                                         JBIG2HuffmanTable *huffDSTable,
                                         JBIG2HuffmanTable *huffDTTable,
@@ -2686,6 +2757,8 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
   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;
@@ -2880,99 +2953,151 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
        }
       }
 
-      // 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;
       }
     }
   }
@@ -3076,6 +3201,8 @@ JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
   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);
@@ -3091,87 +3218,144 @@ JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int 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);
+       }
       }
     }
   }
@@ -3239,8 +3423,8 @@ void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
     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;
@@ -3282,7 +3466,6 @@ void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
   huffTab[i].val = 0;
   huffTab[i].prefixLen = 0;
   huffTab[i].rangeLen = jbig2HuffmanEOT;
-  ++i;
   huffDecoder->buildTable(huffTab, i);
 
   // create and store the new table segment
@@ -3467,7 +3650,7 @@ GBool JBIG2Stream::readLong(int *x) {
   }
   *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
   if (c0 & 0x80) {
-    *x |= -1 - 0xffffffff;
+    *x |= -1 - (int)0xffffffff;
   }
   return gTrue;
 }
index 05a4d28c3298b7be7266c7d6018f71c950d3076c..d4b389c39412fced01a33002ae1502553d30b1d2 100644 (file)
@@ -2,7 +2,7 @@
 //
 // JBIG2Stream.h
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -60,7 +60,7 @@ private:
                              JBIG2Bitmap **syms,
                              Guint defPixel, Guint combOp,
                              Guint transposed, Guint refCorner,
-                             Guint sOffset,
+                             int sOffset,
                              JBIG2HuffmanTable *huffFSTable,
                              JBIG2HuffmanTable *huffDSTable,
                              JBIG2HuffmanTable *huffDTTable,
index 508b9f5299c23f7172266e06c694440ac1aa53b6..5ee492a521d5cb2c91a1ba487efd20676357b325 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Lexer.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 500e5f7b7504c14417184177689a98317402b34d..a85a476f90c3dda77529a2281ba986f02d77b52e 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Link.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -148,7 +148,7 @@ LinkDest::LinkDest(Array *a) {
 
   // 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);
@@ -219,16 +219,16 @@ LinkDest::LinkDest(Array *a) {
 
   // 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;
@@ -241,8 +241,8 @@ LinkDest::LinkDest(Array *a) {
 
   // 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;
@@ -255,8 +255,8 @@ LinkDest::LinkDest(Array *a) {
 
   // 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;
@@ -287,16 +287,16 @@ LinkDest::LinkDest(Array *a) {
 
   // 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;
@@ -309,8 +309,8 @@ LinkDest::LinkDest(Array *a) {
 
   // 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;
index 2eb48ca8898d492c30c143504237a342b96e1658..90def21ed7d140bf86e36cf290b8b8d3e7ad80cf 100644 (file)
@@ -1,5 +1,5 @@
 #
-# "$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).
 #
@@ -123,5 +123,5 @@ include Dependencies
 
 
 #
-# 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 $".
 #
index 00998160b01ae1994e4a44f6aaf67e84f90298b0..d3603258a4e124a5e184a7ff28f518dc49283859 100644 (file)
@@ -2,7 +2,7 @@
 //
 // NameToCharCode.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 8d01b958c9f21f2ca338b85489e4070719ddda66..04650d90a18ba25081b39f71a8579adedb914aa6 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Object.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index d1ee52691c8b502af3c9ead950bcecb4f9968f19..83463e0213e9586ae0123544570b0de4f29990f4 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Outline.cc
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 57d73f1ed62400fad95424afe6c8538cc52ed845..237cb184c5809aa9daabe9e5f1be1086ac2908a7 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Outline.h
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index bba8f1f707cec04a171ea012f78346e29c8b590e..26e05c700ea737c76fbd10e988217cb53cb63ff6 100644 (file)
@@ -2,7 +2,7 @@
 //
 // OutputDev.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -38,7 +38,7 @@ void OutputDev::setDefaultCTM(double *ctm) {
   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];
 }
index 0a7bc09b300f8d873b259325861ceaaf5600179d..13d58c9cbe02815d11c75658829e522b7bc7a5d5 100644 (file)
@@ -72,7 +72,7 @@ public:
   //----- 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
index 42460b995997694a060738bf5eafe48134456a4d..6c06a5da45316f6fa63ef6734ffd360693599807 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PDFDoc.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 4f1e20132c55b00ad5b1b9127d715939d4863a2a..89dc3828312affbdce4eda00a558781efba983e5 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PDFDocEncoding.h
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 6fc157f89d69701793e835292de752748e17459f..3259d3e1064250d2185407f3ec1146adfd395040 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PDFDocEncoding.h
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 386c84ef4689390c24dbbfc541a39721b2f2dd35..85b0a85d9af2941171c030b8f0784f6c4dca7ec6 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PSOutputDev.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -18,6 +18,7 @@
 #include <signal.h>
 #include <math.h>
 #include "GString.h"
+#include "GList.h"
 #include "config.h"
 #include "GlobalParams.h"
 #include "Object.h"
@@ -104,7 +105,7 @@ static const char *prolog[] = {
   "  /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",
@@ -332,11 +333,15 @@ static const char *prolog[] = {
   "/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",
@@ -507,6 +512,7 @@ PSOutputDev::PSOutputDev(const char *fileName, XRef *xrefA, Catalog *catalog,
   fontFileIDs = NULL;
   fontFileNames = NULL;
   font16Enc = NULL;
+  xobjStack = NULL;
   embFontList = NULL;
   customColors = NULL;
   t3String = NULL;
@@ -551,6 +557,7 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
   fontFileIDs = NULL;
   fontFileNames = NULL;
   font16Enc = NULL;
+  xobjStack = NULL;
   embFontList = NULL;
   customColors = NULL;
   t3String = NULL;
@@ -581,6 +588,11 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   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;
   }
@@ -605,6 +617,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   fontFileNames = (GString **)gmalloc(fontFileNameSize * sizeof(GString *));
   font16EncLen = 0;
   font16EncSize = 0;
+  xobjStack = new GList();
 
   // initialize embedded font resource comment list
   embFontList = new GString();
@@ -818,6 +831,9 @@ PSOutputDev::~PSOutputDev() {
     }
     gfree(font16Enc);
   }
+  if (xobjStack) {
+    delete xobjStack;
+  }
   while (customColors) {
     cc = customColors;
     customColors = cc->next;
@@ -826,8 +842,10 @@ PSOutputDev::~PSOutputDev() {
 }
 
 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);
@@ -835,15 +853,40 @@ void PSOutputDev::setupResources(Dict *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();
@@ -874,6 +917,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
   GString *psNameStr;
   const char *psName;
   char type3Name[64], buf[16];
+  GBool subst;
   UnicodeMap *uMap;
   const char *charName;
   double xs, ys;
@@ -899,6 +943,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
 
   xs = ys = 1;
   psNameStr = NULL;
+  subst = gFalse;
 
   // check for resident 8-bit font
   if (font->getName() &&
@@ -969,6 +1014,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
 
   // do 8-bit font substitution
   } else if (!font->isCIDFont()) {
+    subst = gTrue;
     name = font->getName();
     psName = NULL;
     if (name) {
@@ -1030,6 +1076,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
                getPSFont16(font->getName(),
                            ((GfxCIDFont *)font)->getCollection(),
                            font->getWMode()))) {
+    subst = gTrue;
     psName = fontParam->psFontName->getCString();
     if (font16EncLen >= font16EncSize) {
       font16EncSize += 16;
@@ -1074,6 +1121,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
       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;
@@ -1293,7 +1341,9 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
   // 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);
 
@@ -1335,6 +1385,7 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
   ctu = ((Gfx8BitFont *)font)->getToUnicode();
   ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
                          ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
+                         ((Gfx8BitFont *)font)->isSymbolic(),
                          outputFunc, outputStream);
   ctu->decRefCnt();
   delete ttFile;
@@ -1380,6 +1431,7 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, const char *psName) {
   ctu = ((Gfx8BitFont *)font)->getToUnicode();
   ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
                          ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
+                         ((Gfx8BitFont *)font)->isSymbolic(),
                          outputFunc, outputStream);
   ctu->decRefCnt();
   delete ttFile;
@@ -1419,12 +1471,14 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
   // 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);
index 2ab12fc90ca4361ff9b29517968dc5050b8fc29a..82478453676ca4ed254ad29c57508ac297c80278 100644 (file)
@@ -217,6 +217,8 @@ private:
   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
index 598278904dcdfa64a692f19c73f89dc821ce588a..834b0ca2d7d5f5e2812954e0611aab7daec66276 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PSTokenizer.cc
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index f53a42319b28f33b23e3da3aa56e8baa92acc3ae..d8d3476181c141804b6d1262e6b308901a1a3e31 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PSTokenizer.h
 //
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 32dd4551c840b83175a760eb297aa0c8aa87f1b4..520adedb12abc9829b728f6e2f7d3e7bb5191a20 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Page.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 5e3c7c9c427e8ae95b6753215b5289612317b2a1..d7fb9d4eb89ac31bee565c70632701a89e397ca2 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Parser.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 4835a82f827cf0e8248553b5be3e26599f01b831..f089d05d66bc462124f74dd707a7c73df9b60ba1 100644 (file)
@@ -1,28 +1,31 @@
 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.
@@ -51,8 +54,10 @@ informal clarifications:
 - 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
@@ -66,9 +71,9 @@ implementations, as well as VMS and OS/2.  It should work on pretty
 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
@@ -118,11 +123,13 @@ To generate a plain text file, run pdftotext:
 
   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
 
@@ -130,10 +137,55 @@ Command line options and many other details are described in the man
 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
@@ -141,123 +193,34 @@ Xpdf uses X server fonts.  It requires the following fonts:
 * 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
 --------------
 
@@ -267,8 +230,6 @@ See the separate file, INSTALL.
 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,
@@ -287,7 +248,8 @@ Thanks to:
 * 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
@@ -295,14 +257,29 @@ Thanks 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.
@@ -325,23 +302,23 @@ Adobe Developer Support Technical Specification #5014.  1995.
 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.
@@ -356,6 +333,13 @@ Adobe Systems Inc., CMap files.
 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
 
@@ -364,12 +348,22 @@ ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz
 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.
@@ -394,6 +388,20 @@ Robert L. Hummel, _Programmer's Technical Reference: Data and Fax
 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.
@@ -403,6 +411,16 @@ Microsoft, _TrueType 1.0 Font Files_, rev. 1.66.  1995.
 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.]
@@ -410,17 +428,19 @@ http://www.inforamp.net/~poynton/ColorFAQ.html
 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.]
index dc6e078438e2bbf9f36a09b51feb269ab4c654cc..6e0e138fefc663ee1ecce6f73282a23954e11396 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Stream.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -2141,7 +2141,7 @@ GBool DCTStream::readMCURow() {
 // 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;
@@ -2152,13 +2152,15 @@ void DCTStream::readScan() {
        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) {
@@ -2186,7 +2188,7 @@ void DCTStream::readScan() {
        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)];
@@ -2282,8 +2284,10 @@ GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
        return gFalse;
       }
       i += run;
-      j = dctZigZag[i++];
-      data[j] = amp;
+      if (i < 64) {
+       j = dctZigZag[i++];
+       data[j] = amp;
+      }
     }
   }
   return gTrue;
@@ -2369,7 +2373,7 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
       eobRun = 0;
       for (k = 0; k < j; ++k) {
        if ((bit = readBit()) == EOF) {
-         return 9999;
+         return gFalse;
        }
        eobRun = (eobRun << 1) | bit;
       }
@@ -3446,6 +3450,8 @@ GBool FlateStream::readDynamicCodes() {
   int len, repeat, code;
   int i;
 
+  codeLenCodeTab.codes = NULL;
+
   // read lengths
   if ((numLitCodes = getCodeWord(5)) == EOF) {
     goto err;
@@ -3488,23 +3494,35 @@ GBool FlateStream::readDynamicCodes() {
       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 {
index a2c0d1d3a9666b7b866032a6359bf4241d0f796b..7c7ada2fcec5f72e9f2165f0cec42e6425ffa030 100644 (file)
@@ -2,7 +2,7 @@
 //
 // UnicodeMap.cc
 //
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index 867a39d99a0358e9e9d7d965f0ecc6088d93ec69..9023a3409e3a17a7dff6e386b1ad6553305441a1 100644 (file)
@@ -2,7 +2,7 @@
 //
 // XRef.cc
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -325,6 +325,11 @@ GBool XRef::readXRef(Guint *pos) {
   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;
   }
index 8efe062efb0058ca4f19ea4850271358dbc7eb13..b1fb0a422405b5123c602205fb1549f7826f44af 100644 (file)
 //------------------------------------------------------------------------
 
 // 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"
@@ -28,7 +29,7 @@
 #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"
 
 //------------------------------------------------------------------------
index 46a43cffc251e04ec16a96d61c36ce07dd7206c4..7a67dd61cfbcd53feb4915668f76300e8b8bebe5 100644 (file)
@@ -4,7 +4,7 @@
 //
 // Miscellaneous file and directory name manipulation.
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
index e85fd5b054fb51427ae213ba1123b63235331e15..a70338ca3ce23bd4baaffcaa1690f63e4e4af042 100644 (file)
@@ -4,7 +4,7 @@
 //
 // Use gmalloc/gfree for C++ new/delete operators.
 //
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================