summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkramm <kramm>2004-09-17 16:24:55 +0000
committerkramm <kramm>2004-09-17 16:24:55 +0000
commitc7432833fe3a6469d63fad135151a92e12877b94 (patch)
tree6b54d1b3b34e1c6fbe6dc4cb40f110aa7db3ff21
parentb9ddd4a2ed601bc01ddacc69d2522687a93a94ce (diff)
upgrade to xpdf 3.00.xpdf-3-00
-rw-r--r--pdf2swf/xpdf/Annot.cc30
-rw-r--r--pdf2swf/xpdf/Annot.h6
-rw-r--r--pdf2swf/xpdf/Array.cc30
-rw-r--r--pdf2swf/xpdf/Array.h6
-rw-r--r--pdf2swf/xpdf/BuiltinFont.cc7
-rw-r--r--pdf2swf/xpdf/BuiltinFont.h6
-rw-r--r--pdf2swf/xpdf/BuiltinFontTables.cc1300
-rw-r--r--pdf2swf/xpdf/BuiltinFontTables.h2
-rw-r--r--pdf2swf/xpdf/CMap.cc33
-rw-r--r--pdf2swf/xpdf/CMap.h13
-rw-r--r--pdf2swf/xpdf/Catalog.cc33
-rw-r--r--pdf2swf/xpdf/Catalog.h14
-rw-r--r--pdf2swf/xpdf/CharCodeToUnicode.cc371
-rw-r--r--pdf2swf/xpdf/CharCodeToUnicode.h71
-rw-r--r--pdf2swf/xpdf/CharTypes.h2
-rw-r--r--pdf2swf/xpdf/Decrypt.cc98
-rw-r--r--pdf2swf/xpdf/Decrypt.h6
-rw-r--r--pdf2swf/xpdf/Dict.cc15
-rw-r--r--pdf2swf/xpdf/Dict.h6
-rw-r--r--pdf2swf/xpdf/Error.cc7
-rw-r--r--pdf2swf/xpdf/Error.h6
-rw-r--r--pdf2swf/xpdf/ErrorCodes.h14
-rw-r--r--pdf2swf/xpdf/FoFiBase.cc156
-rw-r--r--pdf2swf/xpdf/FoFiBase.h57
-rw-r--r--pdf2swf/xpdf/FoFiEncodings.cc994
-rw-r--r--pdf2swf/xpdf/FoFiEncodings.h36
-rw-r--r--pdf2swf/xpdf/FoFiTrueType.cc1438
-rw-r--r--pdf2swf/xpdf/FoFiTrueType.h133
-rw-r--r--pdf2swf/xpdf/FoFiType1.cc207
-rw-r--r--pdf2swf/xpdf/FoFiType1.h59
-rw-r--r--pdf2swf/xpdf/FoFiType1C.cc2385
-rw-r--r--pdf2swf/xpdf/FoFiType1C.h226
-rw-r--r--pdf2swf/xpdf/FontEncodingTables.cc32
-rw-r--r--pdf2swf/xpdf/FontEncodingTables.h2
-rw-r--r--pdf2swf/xpdf/Function.cc88
-rw-r--r--pdf2swf/xpdf/Function.h10
-rw-r--r--pdf2swf/xpdf/GHash.cc174
-rw-r--r--pdf2swf/xpdf/GHash.h13
-rw-r--r--pdf2swf/xpdf/GList.cc7
-rw-r--r--pdf2swf/xpdf/GList.h6
-rw-r--r--pdf2swf/xpdf/GMutex.h49
-rw-r--r--pdf2swf/xpdf/GString.cc13
-rw-r--r--pdf2swf/xpdf/GString.h6
-rw-r--r--pdf2swf/xpdf/Gfx.cc509
-rw-r--r--pdf2swf/xpdf/Gfx.h46
-rw-r--r--pdf2swf/xpdf/GfxFont.cc455
-rw-r--r--pdf2swf/xpdf/GfxFont.h29
-rw-r--r--pdf2swf/xpdf/GfxState.cc820
-rw-r--r--pdf2swf/xpdf/GfxState.h128
-rw-r--r--pdf2swf/xpdf/GlobalParams.cc897
-rw-r--r--pdf2swf/xpdf/GlobalParams.h132
-rw-r--r--pdf2swf/xpdf/JArithmeticDecoder.cc300
-rw-r--r--pdf2swf/xpdf/JArithmeticDecoder.h91
-rw-r--r--pdf2swf/xpdf/JBIG2Stream.cc3337
-rw-r--r--pdf2swf/xpdf/JBIG2Stream.h143
-rw-r--r--pdf2swf/xpdf/JPXStream.cc2822
-rw-r--r--pdf2swf/xpdf/JPXStream.h340
-rw-r--r--pdf2swf/xpdf/Lexer.cc7
-rw-r--r--pdf2swf/xpdf/Lexer.h6
-rw-r--r--pdf2swf/xpdf/Link.cc463
-rw-r--r--pdf2swf/xpdf/Link.h89
-rw-r--r--pdf2swf/xpdf/NameToCharCode.cc7
-rw-r--r--pdf2swf/xpdf/NameToCharCode.h6
-rw-r--r--pdf2swf/xpdf/NameToUnicodeTable.h56
-rw-r--r--pdf2swf/xpdf/Object.cc14
-rw-r--r--pdf2swf/xpdf/Object.h8
-rw-r--r--pdf2swf/xpdf/Outline.cc151
-rw-r--r--pdf2swf/xpdf/Outline.h76
-rw-r--r--pdf2swf/xpdf/OutputDev.cc12
-rw-r--r--pdf2swf/xpdf/OutputDev.h14
-rw-r--r--pdf2swf/xpdf/PDFDoc.cc86
-rw-r--r--pdf2swf/xpdf/PDFDoc.h45
-rw-r--r--pdf2swf/xpdf/PDFDocEncoding.cc44
-rw-r--r--pdf2swf/xpdf/PDFDocEncoding.h16
-rw-r--r--pdf2swf/xpdf/PSTokenizer.cc6
-rw-r--r--pdf2swf/xpdf/PSTokenizer.h6
-rw-r--r--pdf2swf/xpdf/Page.cc120
-rw-r--r--pdf2swf/xpdf/Page.h33
-rw-r--r--pdf2swf/xpdf/Parser.cc33
-rw-r--r--pdf2swf/xpdf/Parser.h6
-rw-r--r--pdf2swf/xpdf/Stream-CCITT.h2
-rw-r--r--pdf2swf/xpdf/Stream.cc2083
-rw-r--r--pdf2swf/xpdf/Stream.h159
-rw-r--r--pdf2swf/xpdf/UTF8.h2
-rw-r--r--pdf2swf/xpdf/UnicodeMap.cc87
-rw-r--r--pdf2swf/xpdf/UnicodeMap.h21
-rw-r--r--pdf2swf/xpdf/UnicodeMapTables.h2
-rw-r--r--pdf2swf/xpdf/XRef.cc698
-rw-r--r--pdf2swf/xpdf/XRef.h27
-rw-r--r--pdf2swf/xpdf/aconf.h1
-rw-r--r--pdf2swf/xpdf/config.h54
-rw-r--r--pdf2swf/xpdf/gfile.cc103
-rw-r--r--pdf2swf/xpdf/gfile.h7
-rw-r--r--pdf2swf/xpdf/gmem.h2
-rw-r--r--pdf2swf/xpdf/gtypes.h2
95 files changed, 20076 insertions, 2694 deletions
diff --git a/pdf2swf/xpdf/Annot.cc b/pdf2swf/xpdf/Annot.cc
index b9c606f4..245780da 100644
--- a/pdf2swf/xpdf/Annot.cc
+++ b/pdf2swf/xpdf/Annot.cc
@@ -2,15 +2,16 @@
//
// Annot.cc
//
-// Copyright 2000-2002 Glyph & Cog, LLC
+// Copyright 2000-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include "gmem.h"
#include "Object.h"
#include "Gfx.h"
@@ -96,7 +97,7 @@ void Annot::draw(Gfx *gfx) {
Annots::Annots(XRef *xref, Object *annotsObj) {
Annot *annot;
- Object obj1, obj2;
+ Object obj1;
int size;
int i;
@@ -107,21 +108,16 @@ Annots::Annots(XRef *xref, Object *annotsObj) {
if (annotsObj->isArray()) {
for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
if (annotsObj->arrayGet(i, &obj1)->isDict()) {
- obj1.dictLookup("Subtype", &obj2);
- if (obj2.isName("Widget") ||
- obj2.isName("Stamp")) {
- annot = new Annot(xref, obj1.getDict());
- if (annot->isOk()) {
- if (nAnnots >= size) {
- size += 16;
- annots = (Annot **)grealloc(annots, size * sizeof(Annot *));
- }
- annots[nAnnots++] = annot;
- } else {
- delete annot;
+ annot = new Annot(xref, obj1.getDict());
+ if (annot->isOk()) {
+ if (nAnnots >= size) {
+ size += 16;
+ annots = (Annot **)grealloc(annots, size * sizeof(Annot *));
}
+ annots[nAnnots++] = annot;
+ } else {
+ delete annot;
}
- obj2.free();
}
obj1.free();
}
diff --git a/pdf2swf/xpdf/Annot.h b/pdf2swf/xpdf/Annot.h
index 4113a0bd..89dde0f9 100644
--- a/pdf2swf/xpdf/Annot.h
+++ b/pdf2swf/xpdf/Annot.h
@@ -2,14 +2,16 @@
//
// Annot.h
//
-// Copyright 2000-2002 Glyph & Cog, LLC
+// Copyright 2000-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef ANNOT_H
#define ANNOT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Array.cc b/pdf2swf/xpdf/Array.cc
index fbdde49d..a6c6db19 100644
--- a/pdf2swf/xpdf/Array.cc
+++ b/pdf2swf/xpdf/Array.cc
@@ -2,15 +2,17 @@
//
// Array.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
+#include <stdlib.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
@@ -36,8 +38,12 @@ Array::~Array() {
}
void Array::add(Object *elem) {
- if (length + 1 > size) {
- size += 8;
+ if (length == size) {
+ if (length == 0) {
+ size = 8;
+ } else {
+ size *= 2;
+ }
elems = (Object *)grealloc(elems, size * sizeof(Object));
}
elems[length] = *elem;
@@ -45,9 +51,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);
}
diff --git a/pdf2swf/xpdf/Array.h b/pdf2swf/xpdf/Array.h
index a118f685..20ae05f2 100644
--- a/pdf2swf/xpdf/Array.h
+++ b/pdf2swf/xpdf/Array.h
@@ -2,14 +2,16 @@
//
// Array.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef ARRAY_H
#define ARRAY_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/BuiltinFont.cc b/pdf2swf/xpdf/BuiltinFont.cc
index 1b070646..a687e73a 100644
--- a/pdf2swf/xpdf/BuiltinFont.cc
+++ b/pdf2swf/xpdf/BuiltinFont.cc
@@ -2,15 +2,16 @@
//
// BuiltinFont.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <string.h>
#include "gmem.h"
diff --git a/pdf2swf/xpdf/BuiltinFont.h b/pdf2swf/xpdf/BuiltinFont.h
index a7953115..903ed19e 100644
--- a/pdf2swf/xpdf/BuiltinFont.h
+++ b/pdf2swf/xpdf/BuiltinFont.h
@@ -2,14 +2,16 @@
//
// BuiltinFont.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef BUILTINFONT_H
#define BUILTINFONT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/BuiltinFontTables.cc b/pdf2swf/xpdf/BuiltinFontTables.cc
index 845abcd3..9c362389 100644
--- a/pdf2swf/xpdf/BuiltinFontTables.cc
+++ b/pdf2swf/xpdf/BuiltinFontTables.cc
@@ -2,7 +2,7 @@
//
// BuiltinFontTables.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
@@ -13,30 +13,40 @@
static BuiltinFontWidth courierWidthsTab[] = {
{ "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
{ "comma", 600, NULL },
{ "cedilla", 600, NULL },
{ "plusminus", 600, NULL },
- { "arrowup", 600, NULL },
{ "circumflex", 600, NULL },
{ "dotaccent", 600, NULL },
- { "LL", 600, NULL },
+ { "edotaccent", 600, NULL },
{ "asciitilde", 600, NULL },
{ "colon", 600, NULL },
{ "onehalf", 600, NULL },
{ "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
{ "ntilde", 600, NULL },
- { "left", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
{ "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
{ "yen", 600, NULL },
{ "space", 600, NULL },
+ { "Omacron", 600, NULL },
{ "questiondown", 600, NULL },
{ "emdash", 600, NULL },
{ "Agrave", 600, NULL },
{ "three", 600, NULL },
{ "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
{ "A", 600, NULL },
{ "B", 600, NULL },
{ "C", 600, NULL },
+ { "aogonek", 600, NULL },
{ "D", 600, NULL },
{ "E", 600, NULL },
{ "onequarter", 600, NULL },
@@ -46,14 +56,18 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "I", 600, NULL },
{ "J", 600, NULL },
{ "K", 600, NULL },
+ { "iogonek", 600, NULL },
{ "L", 600, NULL },
{ "backslash", 600, NULL },
{ "periodcentered", 600, NULL },
{ "M", 600, NULL },
{ "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
{ "O", 600, NULL },
{ "P", 600, NULL },
{ "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
{ "R", 600, NULL },
{ "Aacute", 600, NULL },
{ "caron", 600, NULL },
@@ -62,9 +76,7 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "U", 600, NULL },
{ "agrave", 600, NULL },
{ "V", 600, NULL },
- { "tab", 600, NULL },
{ "W", 600, NULL },
- { "ll", 600, NULL },
{ "equal", 600, NULL },
{ "question", 600, NULL },
{ "X", 600, NULL },
@@ -72,6 +84,7 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "Z", 600, NULL },
{ "four", 600, NULL },
{ "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
{ "b", 600, NULL },
{ "c", 600, NULL },
{ "d", 600, NULL },
@@ -88,44 +101,57 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "l", 600, NULL },
{ "m", 600, NULL },
{ "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
{ "o", 600, NULL },
{ "ordfeminine", 600, NULL },
{ "ring", 600, NULL },
{ "p", 600, NULL },
{ "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
{ "r", 600, NULL },
{ "twosuperior", 600, NULL },
- { "largebullet", 600, NULL },
{ "aacute", 600, NULL },
{ "s", 600, NULL },
{ "OE", 600, NULL },
{ "t", 600, NULL },
{ "divide", 600, NULL },
{ "u", 600, NULL },
+ { "Ccaron", 600, NULL },
{ "v", 600, NULL },
{ "w", 600, NULL },
{ "x", 600, NULL },
{ "y", 600, NULL },
{ "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
{ "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
{ "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
{ "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
{ "Scaron", 600, NULL },
{ "Lslash", 600, NULL },
{ "semicolon", 600, NULL },
{ "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
{ "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
{ "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
{ "trademark", 600, NULL },
{ "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
{ "macron", 600, NULL },
{ "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
{ "ellipsis", 600, NULL },
{ "scaron", 600, NULL },
{ "AE", 600, NULL },
{ "Ucircumflex", 600, NULL },
{ "lslash", 600, NULL },
- { "lira", 600, NULL },
{ "quotedblleft", 600, NULL },
{ "hyphen", 600, NULL },
{ "guilsinglright", 600, NULL },
@@ -134,9 +160,11 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "exclamdown", 600, NULL },
{ "endash", 600, NULL },
{ "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
{ "ecircumflex", 600, NULL },
- { "copyright", 600, NULL },
{ "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
{ "Egrave", 600, NULL },
{ "slash", 600, NULL },
{ "Edieresis", 600, NULL },
@@ -144,14 +172,17 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "Idieresis", 600, NULL },
{ "parenleft", 600, NULL },
{ "one", 600, NULL },
- { "ucircumflex", 600, NULL },
+ { "emacron", 600, NULL },
{ "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
{ "bracketleft", 600, NULL },
{ "Ugrave", 600, NULL },
{ "quoteright", 600, NULL },
{ "Udieresis", 600, NULL },
{ "perthousand", 600, NULL },
{ "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
{ "Eacute", 600, NULL },
{ "adieresis", 600, NULL },
{ "egrave", 600, NULL },
@@ -167,139 +198,173 @@ static BuiltinFontWidth courierWidthsTab[] = {
{ "nine", 600, NULL },
{ "udieresis", 600, NULL },
{ "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
{ "threequarters", 600, NULL },
{ "guillemotright", 600, NULL },
- { "ydieresis", 600, NULL },
{ "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
{ "tilde", 600, NULL },
{ "at", 600, NULL },
{ "eacute", 600, NULL },
- { "Gcaron", 600, NULL },
{ "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
{ "zero", 600, NULL },
{ "multiply", 600, NULL },
- { "Scedilla", 600, NULL },
{ "eth", 600, NULL },
+ { "Scedilla", 600, NULL },
+ { "Racute", 600, NULL },
{ "Ograve", 600, NULL },
+ { "partialdiff", 600, NULL },
{ "uacute", 600, NULL },
{ "braceleft", 600, NULL },
{ "Thorn", 600, NULL },
{ "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
{ "ccedilla", 600, NULL },
- { "gcaron", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
+ { "scedilla", 600, NULL },
{ "Oacute", 600, NULL },
{ "Ocircumflex", 600, NULL },
- { "scedilla", 600, NULL },
{ "ogonek", 600, NULL },
- { "arrowdown", 600, NULL },
{ "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
{ "thorn", 600, NULL },
{ "degree", 600, NULL },
{ "registered", 600, NULL },
- { "percent", 600, NULL },
+ { "radical", 600, NULL },
{ "Aring", 600, NULL },
+ { "percent", 600, NULL },
{ "six", 600, NULL },
{ "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
{ "two", 600, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 600, NULL },
- { "oacute", 600, NULL },
+ { "Lacute", 600, NULL },
{ "ocircumflex", 600, NULL },
+ { "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
{ "asciicircum", 600, NULL },
{ "aring", 600, NULL },
- { "square", 600, NULL },
{ "grave", 600, NULL },
+ { "uogonek", 600, NULL },
{ "bracketright", 600, NULL },
{ "ampersand", 600, NULL },
{ "Iacute", 600, NULL },
+ { "lacute", 600, NULL },
{ "igrave", 600, NULL },
- { "return", 600, NULL },
+ { "Ncaron", 600, NULL },
{ "plus", 600, NULL },
+ { "uring", 600, NULL },
{ "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
{ "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
{ "threesuperior", 600, NULL },
{ "acute", 600, NULL },
- { "notegraphic", 600, NULL },
{ "section", 600, NULL },
- { "arrowleft", 600, NULL },
{ "dieresis", 600, NULL },
{ "quotedblbase", 600, NULL },
{ "iacute", 600, NULL },
- { "up", 600, NULL },
+ { "ncaron", 600, NULL },
{ "florin", 600, NULL },
{ "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
{ "fi", 600, NULL },
{ "fl", 600, NULL },
{ "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
{ "Icircumflex", 600, NULL },
{ "guillemotleft", 600, NULL },
{ "germandbls", 600, NULL },
{ "seven", 600, NULL },
- { "indent", 600, NULL },
- { "prescription", 600, NULL },
- { "dectab", 600, NULL },
+ { "Amacron", 600, NULL },
+ { "Sacute", 600, NULL },
{ "ordmasculine", 600, NULL },
{ "dotlessi", 600, NULL },
{ "sterling", 600, NULL },
- { "IJ", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
{ "acircumflex", 600, NULL },
- { "overscore", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
{ "braceright", 600, NULL },
{ "icircumflex", 600, NULL },
- { "graybox", 600, NULL },
{ "quotedblright", 600, NULL },
- { "center", 600, NULL },
- { "stop", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
{ "cent", 600, NULL },
{ "currency", 600, NULL },
{ "logicalnot", 600, NULL },
- { "Idot", 600, NULL },
- { "merge", 600, NULL },
+ { "zdotaccent", 600, NULL },
{ "Atilde", 600, NULL },
{ "breve", 600, NULL },
{ "bar", 600, NULL },
{ "fraction", 600, NULL },
{ "less", 600, NULL },
- { "down", 600, NULL },
+ { "ecaron", 600, NULL },
{ "guilsinglleft", 600, NULL },
{ "exclam", 600, NULL },
{ "period", 600, NULL },
- { "arrowright", 600, NULL },
- { "format", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
{ "greater", 600, NULL },
{ "atilde", 600, NULL },
- { "ij", 600, NULL },
{ "brokenbar", 600, NULL },
- { "arrowboth", 600, NULL },
{ "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
{ "onesuperior", 600, NULL }
};
static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
{ "comma", 600, NULL },
{ "cedilla", 600, NULL },
{ "plusminus", 600, NULL },
- { "arrowup", 600, NULL },
{ "circumflex", 600, NULL },
{ "dotaccent", 600, NULL },
- { "LL", 600, NULL },
+ { "edotaccent", 600, NULL },
{ "asciitilde", 600, NULL },
{ "colon", 600, NULL },
{ "onehalf", 600, NULL },
{ "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
{ "ntilde", 600, NULL },
- { "left", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
{ "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
{ "yen", 600, NULL },
{ "space", 600, NULL },
+ { "Omacron", 600, NULL },
{ "questiondown", 600, NULL },
{ "emdash", 600, NULL },
{ "Agrave", 600, NULL },
{ "three", 600, NULL },
{ "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
{ "A", 600, NULL },
{ "B", 600, NULL },
{ "C", 600, NULL },
+ { "aogonek", 600, NULL },
{ "D", 600, NULL },
{ "E", 600, NULL },
{ "onequarter", 600, NULL },
@@ -309,14 +374,18 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "I", 600, NULL },
{ "J", 600, NULL },
{ "K", 600, NULL },
+ { "iogonek", 600, NULL },
{ "backslash", 600, NULL },
{ "L", 600, NULL },
{ "periodcentered", 600, NULL },
{ "M", 600, NULL },
{ "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
{ "O", 600, NULL },
{ "P", 600, NULL },
{ "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
{ "R", 600, NULL },
{ "Aacute", 600, NULL },
{ "caron", 600, NULL },
@@ -325,9 +394,7 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "U", 600, NULL },
{ "agrave", 600, NULL },
{ "V", 600, NULL },
- { "tab", 600, NULL },
{ "W", 600, NULL },
- { "ll", 600, NULL },
{ "X", 600, NULL },
{ "question", 600, NULL },
{ "equal", 600, NULL },
@@ -335,6 +402,7 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "Z", 600, NULL },
{ "four", 600, NULL },
{ "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
{ "b", 600, NULL },
{ "c", 600, NULL },
{ "d", 600, NULL },
@@ -351,44 +419,57 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "l", 600, NULL },
{ "m", 600, NULL },
{ "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
{ "o", 600, NULL },
{ "ordfeminine", 600, NULL },
{ "ring", 600, NULL },
{ "p", 600, NULL },
{ "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
{ "r", 600, NULL },
{ "twosuperior", 600, NULL },
- { "largebullet", 600, NULL },
{ "aacute", 600, NULL },
{ "s", 600, NULL },
{ "OE", 600, NULL },
{ "t", 600, NULL },
{ "divide", 600, NULL },
{ "u", 600, NULL },
+ { "Ccaron", 600, NULL },
{ "v", 600, NULL },
{ "w", 600, NULL },
{ "x", 600, NULL },
{ "y", 600, NULL },
{ "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
{ "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
{ "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
{ "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
{ "Scaron", 600, NULL },
{ "Lslash", 600, NULL },
{ "semicolon", 600, NULL },
{ "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
{ "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
{ "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
{ "trademark", 600, NULL },
{ "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
{ "macron", 600, NULL },
{ "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
{ "ellipsis", 600, NULL },
{ "scaron", 600, NULL },
{ "AE", 600, NULL },
{ "Ucircumflex", 600, NULL },
{ "lslash", 600, NULL },
- { "lira", 600, NULL },
{ "quotedblleft", 600, NULL },
{ "guilsinglright", 600, NULL },
{ "hyphen", 600, NULL },
@@ -397,9 +478,11 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "exclamdown", 600, NULL },
{ "endash", 600, NULL },
{ "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
{ "ecircumflex", 600, NULL },
- { "copyright", 600, NULL },
{ "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
{ "Egrave", 600, NULL },
{ "slash", 600, NULL },
{ "Edieresis", 600, NULL },
@@ -407,14 +490,17 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "Idieresis", 600, NULL },
{ "parenleft", 600, NULL },
{ "one", 600, NULL },
- { "ucircumflex", 600, NULL },
+ { "emacron", 600, NULL },
{ "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
{ "bracketleft", 600, NULL },
{ "Ugrave", 600, NULL },
{ "quoteright", 600, NULL },
{ "Udieresis", 600, NULL },
{ "perthousand", 600, NULL },
{ "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
{ "Eacute", 600, NULL },
{ "adieresis", 600, NULL },
{ "egrave", 600, NULL },
@@ -430,139 +516,173 @@ static BuiltinFontWidth courierBoldWidthsTab[] = {
{ "five", 600, NULL },
{ "udieresis", 600, NULL },
{ "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
{ "threequarters", 600, NULL },
{ "guillemotright", 600, NULL },
- { "ydieresis", 600, NULL },
{ "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
{ "tilde", 600, NULL },
{ "at", 600, NULL },
{ "eacute", 600, NULL },
- { "Gcaron", 600, NULL },
{ "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
{ "multiply", 600, NULL },
{ "zero", 600, NULL },
{ "eth", 600, NULL },
{ "Scedilla", 600, NULL },
{ "Ograve", 600, NULL },
+ { "Racute", 600, NULL },
+ { "partialdiff", 600, NULL },
{ "uacute", 600, NULL },
{ "braceleft", 600, NULL },
{ "Thorn", 600, NULL },
{ "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
{ "ccedilla", 600, NULL },
- { "gcaron", 600, NULL },
- { "scedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
{ "Ocircumflex", 600, NULL },
{ "Oacute", 600, NULL },
- { "arrowdown", 600, NULL },
+ { "scedilla", 600, NULL },
{ "ogonek", 600, NULL },
{ "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
{ "thorn", 600, NULL },
{ "degree", 600, NULL },
{ "registered", 600, NULL },
+ { "radical", 600, NULL },
{ "Aring", 600, NULL },
{ "percent", 600, NULL },
{ "six", 600, NULL },
{ "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
{ "two", 600, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
{ "ocircumflex", 600, NULL },
{ "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
{ "asciicircum", 600, NULL },
- { "square", 600, NULL },
{ "aring", 600, NULL },
{ "grave", 600, NULL },
+ { "uogonek", 600, NULL },
{ "bracketright", 600, NULL },
{ "Iacute", 600, NULL },
{ "ampersand", 600, NULL },
{ "igrave", 600, NULL },
- { "return", 600, NULL },
+ { "lacute", 600, NULL },
+ { "Ncaron", 600, NULL },
{ "plus", 600, NULL },
+ { "uring", 600, NULL },
{ "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
{ "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
{ "threesuperior", 600, NULL },
{ "acute", 600, NULL },
- { "notegraphic", 600, NULL },
{ "section", 600, NULL },
- { "arrowleft", 600, NULL },
{ "dieresis", 600, NULL },
{ "iacute", 600, NULL },
{ "quotedblbase", 600, NULL },
- { "up", 600, NULL },
+ { "ncaron", 600, NULL },
{ "florin", 600, NULL },
{ "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
{ "fi", 600, NULL },
{ "fl", 600, NULL },
{ "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
{ "Icircumflex", 600, NULL },
{ "guillemotleft", 600, NULL },
{ "germandbls", 600, NULL },
+ { "Amacron", 600, NULL },
{ "seven", 600, NULL },
- { "prescription", 600, NULL },
- { "indent", 600, NULL },
- { "dectab", 600, NULL },
+ { "Sacute", 600, NULL },
{ "ordmasculine", 600, NULL },
{ "dotlessi", 600, NULL },
{ "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
{ "acircumflex", 600, NULL },
- { "IJ", 600, NULL },
- { "overscore", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
{ "icircumflex", 600, NULL },
{ "braceright", 600, NULL },
- { "graybox", 600, NULL },
{ "quotedblright", 600, NULL },
- { "center", 600, NULL },
- { "stop", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
{ "cent", 600, NULL },
{ "currency", 600, NULL },
{ "logicalnot", 600, NULL },
- { "merge", 600, NULL },
- { "Idot", 600, NULL },
+ { "zdotaccent", 600, NULL },
{ "Atilde", 600, NULL },
{ "breve", 600, NULL },
{ "bar", 600, NULL },
{ "fraction", 600, NULL },
{ "less", 600, NULL },
- { "down", 600, NULL },
+ { "ecaron", 600, NULL },
{ "guilsinglleft", 600, NULL },
{ "exclam", 600, NULL },
{ "period", 600, NULL },
- { "format", 600, NULL },
- { "arrowright", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
{ "greater", 600, NULL },
- { "ij", 600, NULL },
{ "atilde", 600, NULL },
{ "brokenbar", 600, NULL },
- { "arrowboth", 600, NULL },
{ "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
{ "onesuperior", 600, NULL }
};
static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
{ "comma", 600, NULL },
{ "cedilla", 600, NULL },
{ "plusminus", 600, NULL },
- { "arrowup", 600, NULL },
{ "circumflex", 600, NULL },
{ "dotaccent", 600, NULL },
- { "LL", 600, NULL },
+ { "edotaccent", 600, NULL },
{ "asciitilde", 600, NULL },
{ "colon", 600, NULL },
{ "onehalf", 600, NULL },
{ "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
{ "ntilde", 600, NULL },
- { "left", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
{ "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
{ "yen", 600, NULL },
{ "space", 600, NULL },
+ { "Omacron", 600, NULL },
{ "questiondown", 600, NULL },
{ "emdash", 600, NULL },
{ "Agrave", 600, NULL },
{ "three", 600, NULL },
{ "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
{ "A", 600, NULL },
{ "B", 600, NULL },
{ "C", 600, NULL },
+ { "aogonek", 600, NULL },
{ "D", 600, NULL },
{ "E", 600, NULL },
{ "onequarter", 600, NULL },
@@ -572,14 +692,18 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "I", 600, NULL },
{ "J", 600, NULL },
{ "K", 600, NULL },
+ { "iogonek", 600, NULL },
{ "backslash", 600, NULL },
{ "L", 600, NULL },
{ "periodcentered", 600, NULL },
{ "M", 600, NULL },
{ "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
{ "O", 600, NULL },
{ "P", 600, NULL },
{ "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
{ "R", 600, NULL },
{ "Aacute", 600, NULL },
{ "caron", 600, NULL },
@@ -588,9 +712,7 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "U", 600, NULL },
{ "agrave", 600, NULL },
{ "V", 600, NULL },
- { "tab", 600, NULL },
{ "W", 600, NULL },
- { "ll", 600, NULL },
{ "X", 600, NULL },
{ "question", 600, NULL },
{ "equal", 600, NULL },
@@ -598,6 +720,7 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "Z", 600, NULL },
{ "four", 600, NULL },
{ "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
{ "b", 600, NULL },
{ "c", 600, NULL },
{ "d", 600, NULL },
@@ -614,44 +737,57 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "l", 600, NULL },
{ "m", 600, NULL },
{ "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
{ "o", 600, NULL },
{ "ordfeminine", 600, NULL },
{ "ring", 600, NULL },
{ "p", 600, NULL },
{ "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
{ "r", 600, NULL },
{ "twosuperior", 600, NULL },
- { "largebullet", 600, NULL },
{ "aacute", 600, NULL },
{ "s", 600, NULL },
{ "OE", 600, NULL },
{ "t", 600, NULL },
{ "divide", 600, NULL },
{ "u", 600, NULL },
+ { "Ccaron", 600, NULL },
{ "v", 600, NULL },
{ "w", 600, NULL },
{ "x", 600, NULL },
{ "y", 600, NULL },
{ "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
{ "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
{ "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
{ "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
{ "Scaron", 600, NULL },
{ "Lslash", 600, NULL },
{ "semicolon", 600, NULL },
{ "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
{ "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
{ "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
{ "trademark", 600, NULL },
{ "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
{ "macron", 600, NULL },
{ "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
{ "ellipsis", 600, NULL },
{ "scaron", 600, NULL },
{ "AE", 600, NULL },
{ "Ucircumflex", 600, NULL },
{ "lslash", 600, NULL },
- { "lira", 600, NULL },
{ "quotedblleft", 600, NULL },
{ "guilsinglright", 600, NULL },
{ "hyphen", 600, NULL },
@@ -660,9 +796,11 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "exclamdown", 600, NULL },
{ "endash", 600, NULL },
{ "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
{ "ecircumflex", 600, NULL },
- { "copyright", 600, NULL },
{ "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
{ "Egrave", 600, NULL },
{ "slash", 600, NULL },
{ "Edieresis", 600, NULL },
@@ -670,14 +808,17 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "Idieresis", 600, NULL },
{ "parenleft", 600, NULL },
{ "one", 600, NULL },
- { "ucircumflex", 600, NULL },
+ { "emacron", 600, NULL },
{ "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
{ "bracketleft", 600, NULL },
{ "Ugrave", 600, NULL },
{ "quoteright", 600, NULL },
{ "Udieresis", 600, NULL },
{ "perthousand", 600, NULL },
{ "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
{ "Eacute", 600, NULL },
{ "adieresis", 600, NULL },
{ "egrave", 600, NULL },
@@ -693,139 +834,173 @@ static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
{ "five", 600, NULL },
{ "udieresis", 600, NULL },
{ "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
{ "threequarters", 600, NULL },
{ "guillemotright", 600, NULL },
- { "ydieresis", 600, NULL },
{ "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
{ "tilde", 600, NULL },
{ "at", 600, NULL },
{ "eacute", 600, NULL },
- { "Gcaron", 600, NULL },
{ "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
{ "multiply", 600, NULL },
{ "zero", 600, NULL },
{ "eth", 600, NULL },
{ "Scedilla", 600, NULL },
{ "Ograve", 600, NULL },
+ { "Racute", 600, NULL },
+ { "partialdiff", 600, NULL },
{ "uacute", 600, NULL },
{ "braceleft", 600, NULL },
{ "Thorn", 600, NULL },
{ "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
{ "ccedilla", 600, NULL },
- { "gcaron", 600, NULL },
- { "scedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
{ "Ocircumflex", 600, NULL },
{ "Oacute", 600, NULL },
- { "arrowdown", 600, NULL },
+ { "scedilla", 600, NULL },
{ "ogonek", 600, NULL },
{ "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
{ "thorn", 600, NULL },
{ "degree", 600, NULL },
{ "registered", 600, NULL },
+ { "radical", 600, NULL },
{ "Aring", 600, NULL },
{ "percent", 600, NULL },
{ "six", 600, NULL },
{ "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
{ "two", 600, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
{ "ocircumflex", 600, NULL },
{ "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
{ "asciicircum", 600, NULL },
- { "square", 600, NULL },
{ "aring", 600, NULL },
{ "grave", 600, NULL },
+ { "uogonek", 600, NULL },
{ "bracketright", 600, NULL },
{ "Iacute", 600, NULL },
{ "ampersand", 600, NULL },
{ "igrave", 600, NULL },
- { "return", 600, NULL },
+ { "lacute", 600, NULL },
+ { "Ncaron", 600, NULL },
{ "plus", 600, NULL },
+ { "uring", 600, NULL },
{ "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
{ "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
{ "threesuperior", 600, NULL },
{ "acute", 600, NULL },
- { "notegraphic", 600, NULL },
{ "section", 600, NULL },
- { "arrowleft", 600, NULL },
{ "dieresis", 600, NULL },
{ "iacute", 600, NULL },
{ "quotedblbase", 600, NULL },
- { "up", 600, NULL },
+ { "ncaron", 600, NULL },
{ "florin", 600, NULL },
{ "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
{ "fi", 600, NULL },
{ "fl", 600, NULL },
{ "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
{ "Icircumflex", 600, NULL },
{ "guillemotleft", 600, NULL },
{ "germandbls", 600, NULL },
+ { "Amacron", 600, NULL },
{ "seven", 600, NULL },
- { "prescription", 600, NULL },
- { "indent", 600, NULL },
- { "dectab", 600, NULL },
+ { "Sacute", 600, NULL },
{ "ordmasculine", 600, NULL },
{ "dotlessi", 600, NULL },
{ "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
{ "acircumflex", 600, NULL },
- { "IJ", 600, NULL },
- { "overscore", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
{ "icircumflex", 600, NULL },
{ "braceright", 600, NULL },
- { "graybox", 600, NULL },
{ "quotedblright", 600, NULL },
- { "center", 600, NULL },
- { "stop", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
{ "cent", 600, NULL },
{ "currency", 600, NULL },
{ "logicalnot", 600, NULL },
- { "merge", 600, NULL },
- { "Idot", 600, NULL },
+ { "zdotaccent", 600, NULL },
{ "Atilde", 600, NULL },
{ "breve", 600, NULL },
{ "bar", 600, NULL },
{ "fraction", 600, NULL },
{ "less", 600, NULL },
- { "down", 600, NULL },
+ { "ecaron", 600, NULL },
{ "guilsinglleft", 600, NULL },
{ "exclam", 600, NULL },
{ "period", 600, NULL },
- { "format", 600, NULL },
- { "arrowright", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
{ "greater", 600, NULL },
- { "ij", 600, NULL },
{ "atilde", 600, NULL },
{ "brokenbar", 600, NULL },
- { "arrowboth", 600, NULL },
{ "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
{ "onesuperior", 600, NULL }
};
static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
{ "comma", 600, NULL },
{ "cedilla", 600, NULL },
{ "plusminus", 600, NULL },
- { "arrowup", 600, NULL },
{ "circumflex", 600, NULL },
{ "dotaccent", 600, NULL },
- { "LL", 600, NULL },
+ { "edotaccent", 600, NULL },
{ "asciitilde", 600, NULL },
{ "colon", 600, NULL },
{ "onehalf", 600, NULL },
{ "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
{ "ntilde", 600, NULL },
- { "left", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
{ "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
{ "yen", 600, NULL },
{ "space", 600, NULL },
+ { "Omacron", 600, NULL },
{ "questiondown", 600, NULL },
{ "emdash", 600, NULL },
{ "Agrave", 600, NULL },
{ "three", 600, NULL },
{ "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
{ "A", 600, NULL },
{ "B", 600, NULL },
{ "C", 600, NULL },
+ { "aogonek", 600, NULL },
{ "D", 600, NULL },
{ "E", 600, NULL },
{ "onequarter", 600, NULL },
@@ -835,14 +1010,18 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "I", 600, NULL },
{ "J", 600, NULL },
{ "K", 600, NULL },
+ { "iogonek", 600, NULL },
{ "backslash", 600, NULL },
{ "L", 600, NULL },
{ "periodcentered", 600, NULL },
{ "M", 600, NULL },
{ "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
{ "O", 600, NULL },
{ "P", 600, NULL },
{ "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
{ "R", 600, NULL },
{ "Aacute", 600, NULL },
{ "caron", 600, NULL },
@@ -851,9 +1030,7 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "U", 600, NULL },
{ "agrave", 600, NULL },
{ "V", 600, NULL },
- { "tab", 600, NULL },
{ "W", 600, NULL },
- { "ll", 600, NULL },
{ "X", 600, NULL },
{ "question", 600, NULL },
{ "equal", 600, NULL },
@@ -861,6 +1038,7 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "Z", 600, NULL },
{ "four", 600, NULL },
{ "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
{ "b", 600, NULL },
{ "c", 600, NULL },
{ "d", 600, NULL },
@@ -877,44 +1055,57 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "l", 600, NULL },
{ "m", 600, NULL },
{ "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
{ "o", 600, NULL },
{ "ordfeminine", 600, NULL },
{ "ring", 600, NULL },
{ "p", 600, NULL },
{ "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
{ "r", 600, NULL },
{ "twosuperior", 600, NULL },
- { "largebullet", 600, NULL },
{ "aacute", 600, NULL },
{ "s", 600, NULL },
{ "OE", 600, NULL },
{ "t", 600, NULL },
{ "divide", 600, NULL },
{ "u", 600, NULL },
+ { "Ccaron", 600, NULL },
{ "v", 600, NULL },
{ "w", 600, NULL },
{ "x", 600, NULL },
{ "y", 600, NULL },
{ "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
{ "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
{ "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
{ "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
{ "Scaron", 600, NULL },
{ "Lslash", 600, NULL },
{ "semicolon", 600, NULL },
{ "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
{ "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
{ "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
{ "trademark", 600, NULL },
{ "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
{ "macron", 600, NULL },
{ "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
{ "ellipsis", 600, NULL },
{ "scaron", 600, NULL },
{ "AE", 600, NULL },
{ "Ucircumflex", 600, NULL },
{ "lslash", 600, NULL },
- { "lira", 600, NULL },
{ "quotedblleft", 600, NULL },
{ "guilsinglright", 600, NULL },
{ "hyphen", 600, NULL },
@@ -923,9 +1114,11 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "exclamdown", 600, NULL },
{ "endash", 600, NULL },
{ "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
{ "ecircumflex", 600, NULL },
- { "copyright", 600, NULL },
{ "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
{ "Egrave", 600, NULL },
{ "slash", 600, NULL },
{ "Edieresis", 600, NULL },
@@ -933,14 +1126,17 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "Idieresis", 600, NULL },
{ "parenleft", 600, NULL },
{ "one", 600, NULL },
- { "ucircumflex", 600, NULL },
+ { "emacron", 600, NULL },
{ "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
{ "bracketleft", 600, NULL },
{ "Ugrave", 600, NULL },
{ "quoteright", 600, NULL },
{ "Udieresis", 600, NULL },
{ "perthousand", 600, NULL },
{ "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
{ "Eacute", 600, NULL },
{ "adieresis", 600, NULL },
{ "egrave", 600, NULL },
@@ -956,136 +1152,173 @@ static BuiltinFontWidth courierObliqueWidthsTab[] = {
{ "five", 600, NULL },
{ "udieresis", 600, NULL },
{ "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
{ "threequarters", 600, NULL },
{ "guillemotright", 600, NULL },
- { "ydieresis", 600, NULL },
{ "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
{ "tilde", 600, NULL },
{ "at", 600, NULL },
{ "eacute", 600, NULL },
- { "Gcaron", 600, NULL },
{ "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
{ "multiply", 600, NULL },
{ "zero", 600, NULL },
{ "eth", 600, NULL },
{ "Scedilla", 600, NULL },
{ "Ograve", 600, NULL },
+ { "Racute", 600, NULL },
+ { "partialdiff", 600, NULL },
{ "uacute", 600, NULL },
{ "braceleft", 600, NULL },
{ "Thorn", 600, NULL },
{ "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
{ "ccedilla", 600, NULL },
- { "gcaron", 600, NULL },
- { "scedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
{ "Ocircumflex", 600, NULL },
{ "Oacute", 600, NULL },
- { "arrowdown", 600, NULL },
+ { "scedilla", 600, NULL },
{ "ogonek", 600, NULL },
{ "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
{ "thorn", 600, NULL },
{ "degree", 600, NULL },
{ "registered", 600, NULL },
+ { "radical", 600, NULL },
{ "Aring", 600, NULL },
{ "percent", 600, NULL },
{ "six", 600, NULL },
{ "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
{ "two", 600, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
{ "ocircumflex", 600, NULL },
{ "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
{ "asciicircum", 600, NULL },
- { "square", 600, NULL },
{ "aring", 600, NULL },
{ "grave", 600, NULL },
+ { "uogonek", 600, NULL },
{ "bracketright", 600, NULL },
{ "Iacute", 600, NULL },
{ "ampersand", 600, NULL },
{ "igrave", 600, NULL },
- { "return", 600, NULL },
+ { "lacute", 600, NULL },
+ { "Ncaron", 600, NULL },
{ "plus", 600, NULL },
+ { "uring", 600, NULL },
{ "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
{ "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
{ "threesuperior", 600, NULL },
{ "acute", 600, NULL },
- { "notegraphic", 600, NULL },
{ "section", 600, NULL },
- { "arrowleft", 600, NULL },
{ "dieresis", 600, NULL },
{ "iacute", 600, NULL },
{ "quotedblbase", 600, NULL },
- { "up", 600, NULL },
+ { "ncaron", 600, NULL },
{ "florin", 600, NULL },
{ "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
{ "fi", 600, NULL },
{ "fl", 600, NULL },
{ "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
{ "Icircumflex", 600, NULL },
{ "guillemotleft", 600, NULL },
{ "germandbls", 600, NULL },
+ { "Amacron", 600, NULL },
{ "seven", 600, NULL },
- { "prescription", 600, NULL },
- { "indent", 600, NULL },
- { "dectab", 600, NULL },
+ { "Sacute", 600, NULL },
{ "ordmasculine", 600, NULL },
{ "dotlessi", 600, NULL },
{ "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
{ "acircumflex", 600, NULL },
- { "IJ", 600, NULL },
- { "overscore", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
{ "icircumflex", 600, NULL },
{ "braceright", 600, NULL },
- { "graybox", 600, NULL },
{ "quotedblright", 600, NULL },
- { "center", 600, NULL },
- { "stop", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
{ "cent", 600, NULL },
{ "currency", 600, NULL },
{ "logicalnot", 600, NULL },
- { "merge", 600, NULL },
- { "Idot", 600, NULL },
+ { "zdotaccent", 600, NULL },
{ "Atilde", 600, NULL },
{ "breve", 600, NULL },
{ "bar", 600, NULL },
{ "fraction", 600, NULL },
{ "less", 600, NULL },
- { "down", 600, NULL },
+ { "ecaron", 600, NULL },
{ "guilsinglleft", 600, NULL },
{ "exclam", 600, NULL },
{ "period", 600, NULL },
- { "format", 600, NULL },
- { "arrowright", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
{ "greater", 600, NULL },
- { "ij", 600, NULL },
{ "atilde", 600, NULL },
{ "brokenbar", 600, NULL },
- { "arrowboth", 600, NULL },
{ "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
{ "onesuperior", 600, NULL }
};
static BuiltinFontWidth helveticaWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 333, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
{ "comma", 278, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 584, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
{ "asciitilde", 584, NULL },
{ "colon", 278, NULL },
{ "onehalf", 834, NULL },
{ "dollar", 556, NULL },
+ { "Lcaron", 556, NULL },
{ "ntilde", 556, NULL },
+ { "Aogonek", 667, NULL },
+ { "ncommaaccent", 556, NULL },
{ "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
{ "yen", 556, NULL },
{ "space", 278, NULL },
+ { "Omacron", 778, NULL },
{ "questiondown", 611, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 667, NULL },
{ "three", 556, NULL },
{ "numbersign", 556, NULL },
+ { "lcaron", 299, NULL },
{ "A", 667, NULL },
{ "B", 667, NULL },
{ "C", 722, NULL },
+ { "aogonek", 556, NULL },
{ "D", 722, NULL },
{ "E", 667, NULL },
{ "onequarter", 834, NULL },
@@ -1095,14 +1328,18 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "I", 278, NULL },
{ "J", 500, NULL },
{ "K", 667, NULL },
+ { "iogonek", 222, NULL },
{ "backslash", 278, NULL },
{ "L", 556, NULL },
{ "periodcentered", 278, NULL },
{ "M", 833, NULL },
{ "N", 722, NULL },
+ { "omacron", 556, NULL },
+ { "Tcommaaccent", 611, NULL },
{ "O", 778, NULL },
{ "P", 667, NULL },
{ "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 722, NULL },
{ "Aacute", 667, NULL },
{ "caron", 333, NULL },
@@ -1119,6 +1356,7 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "Z", 611, NULL },
{ "four", 556, NULL },
{ "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
{ "b", 556, NULL },
{ "c", 500, NULL },
{ "d", 556, NULL },
@@ -1135,11 +1373,13 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "l", 222, NULL },
{ "m", 833, NULL },
{ "n", 556, NULL },
+ { "tcommaaccent", 278, NULL },
{ "o", 556, NULL },
{ "ordfeminine", 370, NULL },
{ "ring", 333, NULL },
{ "p", 556, NULL },
{ "q", 556, NULL },
+ { "uhungarumlaut", 556, NULL },
{ "r", 333, NULL },
{ "twosuperior", 333, NULL },
{ "aacute", 556, NULL },
@@ -1148,24 +1388,37 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "t", 278, NULL },
{ "divide", 584, NULL },
{ "u", 556, NULL },
+ { "Ccaron", 722, NULL },
{ "v", 500, NULL },
{ "w", 722, NULL },
{ "x", 500, NULL },
{ "y", 500, NULL },
{ "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 355, NULL },
+ { "gcommaaccent", 556, NULL },
{ "mu", 556, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 667, NULL },
{ "Lslash", 556, NULL },
{ "semicolon", 278, NULL },
{ "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 500, NULL },
{ "Ecircumflex", 667, NULL },
+ { "gbreve", 556, NULL },
{ "trademark", 1000, NULL },
{ "daggerdbl", 556, NULL },
+ { "nacute", 556, NULL },
{ "macron", 333, NULL },
{ "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 500, NULL },
{ "AE", 1000, NULL },
@@ -1179,9 +1432,11 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "exclamdown", 333, NULL },
{ "endash", 556, NULL },
{ "oe", 944, NULL },
+ { "Abreve", 667, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 556, NULL },
- { "copyright", 737, NULL },
{ "Adieresis", 667, NULL },
+ { "copyright", 737, NULL },
{ "Egrave", 667, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 667, NULL },
@@ -1189,14 +1444,17 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "Idieresis", 278, NULL },
{ "parenleft", 333, NULL },
{ "one", 556, NULL },
- { "ucircumflex", 556, NULL },
+ { "emacron", 556, NULL },
{ "Odieresis", 778, NULL },
+ { "ucircumflex", 556, NULL },
{ "bracketleft", 278, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 222, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 667, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 556, NULL },
{ "Eacute", 667, NULL },
{ "adieresis", 556, NULL },
{ "egrave", 556, NULL },
@@ -1212,111 +1470,173 @@ static BuiltinFontWidth helveticaWidthsTab[] = {
{ "five", 556, NULL },
{ "udieresis", 556, NULL },
{ "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
{ "threequarters", 834, NULL },
{ "guillemotright", 556, NULL },
- { "ydieresis", 500, NULL },
{ "Ccedilla", 722, NULL },
+ { "ydieresis", 500, NULL },
{ "tilde", 333, NULL },
{ "at", 1015, NULL },
{ "eacute", 556, NULL },
{ "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 584, NULL },
{ "zero", 556, NULL },
{ "eth", 556, NULL },
+ { "Scedilla", 667, NULL },
{ "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 476, NULL },
{ "uacute", 556, NULL },
{ "braceleft", 334, NULL },
{ "Thorn", 667, NULL },
{ "zcaron", 500, NULL },
+ { "scommaaccent", 500, NULL },
{ "ccedilla", 500, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 556, NULL },
{ "Ocircumflex", 778, NULL },
{ "Oacute", 778, NULL },
+ { "scedilla", 500, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 556, NULL },
+ { "racute", 333, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
{ "thorn", 556, NULL },
{ "degree", 400, NULL },
{ "registered", 737, NULL },
+ { "radical", 453, NULL },
{ "Aring", 667, NULL },
{ "percent", 889, NULL },
{ "six", 556, NULL },
{ "paragraph", 537, NULL },
+ { "dcaron", 643, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 556, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 278, NULL },
+ { "Lacute", 556, NULL },
{ "ocircumflex", 556, NULL },
{ "oacute", 556, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 556, NULL },
+ { "tcaron", 317, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
{ "asciicircum", 469, NULL },
{ "aring", 556, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 556, NULL },
{ "bracketright", 278, NULL },
{ "Iacute", 278, NULL },
{ "ampersand", 667, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 222, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 584, NULL },
+ { "uring", 556, NULL },
{ "quotesinglbase", 222, NULL },
+ { "lcommaaccent", 222, NULL },
{ "Yacute", 667, NULL },
+ { "ohungarumlaut", 556, NULL },
{ "threesuperior", 333, NULL },
{ "acute", 333, NULL },
{ "section", 556, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 333, NULL },
+ { "ncaron", 556, NULL },
{ "florin", 556, NULL },
{ "yacute", 500, NULL },
+ { "Rcommaaccent", 722, NULL },
{ "fi", 500, NULL },
{ "fl", 500, NULL },
{ "Acircumflex", 667, NULL },
+ { "Cacute", 722, NULL },
{ "Icircumflex", 278, NULL },
{ "guillemotleft", 556, NULL },
{ "germandbls", 611, NULL },
+ { "Amacron", 667, NULL },
{ "seven", 556, NULL },
+ { "Sacute", 667, NULL },
{ "ordmasculine", 365, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 333, NULL },
+ { "Zdotaccent", 611, NULL },
{ "acircumflex", 556, NULL },
+ { "cacute", 500, NULL },
+ { "Ecaron", 667, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 334, NULL },
{ "quotedblright", 333, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 500, NULL },
+ { "imacron", 278, NULL },
{ "cent", 556, NULL },
{ "currency", 556, NULL },
{ "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
{ "Atilde", 667, NULL },
{ "breve", 333, NULL },
{ "bar", 260, NULL },
{ "fraction", 167, NULL },
{ "less", 584, NULL },
+ { "ecaron", 556, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 278, NULL },
{ "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 667, NULL },
{ "greater", 584, NULL },
{ "atilde", 556, NULL },
{ "brokenbar", 260, NULL },
{ "quoteleft", 222, NULL },
+ { "Edotaccent", 667, NULL },
{ "onesuperior", 333, NULL }
};
static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 556, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
{ "comma", 278, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 584, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
{ "asciitilde", 584, NULL },
{ "colon", 333, NULL },
{ "onehalf", 834, NULL },
{ "dollar", 556, NULL },
+ { "Lcaron", 611, NULL },
{ "ntilde", 611, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 611, NULL },
{ "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
{ "yen", 556, NULL },
{ "space", 278, NULL },
+ { "Omacron", 778, NULL },
{ "questiondown", 611, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 722, NULL },
{ "three", 556, NULL },
{ "numbersign", 556, NULL },
+ { "lcaron", 400, NULL },
{ "A", 722, NULL },
{ "B", 722, NULL },
{ "C", 722, NULL },
+ { "aogonek", 556, NULL },
{ "D", 722, NULL },
{ "E", 667, NULL },
{ "onequarter", 834, NULL },
@@ -1326,14 +1646,18 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "I", 278, NULL },
{ "J", 556, NULL },
{ "K", 722, NULL },
+ { "iogonek", 278, NULL },
{ "backslash", 278, NULL },
{ "L", 611, NULL },
{ "periodcentered", 278, NULL },
{ "M", 833, NULL },
{ "N", 722, NULL },
+ { "omacron", 611, NULL },
+ { "Tcommaaccent", 611, NULL },
{ "O", 778, NULL },
{ "P", 667, NULL },
{ "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 722, NULL },
{ "Aacute", 722, NULL },
{ "caron", 333, NULL },
@@ -1350,6 +1674,7 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "Z", 611, NULL },
{ "four", 556, NULL },
{ "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
{ "b", 611, NULL },
{ "c", 556, NULL },
{ "d", 611, NULL },
@@ -1366,11 +1691,13 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "l", 278, NULL },
{ "m", 889, NULL },
{ "n", 611, NULL },
+ { "tcommaaccent", 333, NULL },
{ "o", 611, NULL },
{ "ordfeminine", 370, NULL },
{ "ring", 333, NULL },
{ "p", 611, NULL },
{ "q", 611, NULL },
+ { "uhungarumlaut", 611, NULL },
{ "r", 389, NULL },
{ "twosuperior", 333, NULL },
{ "aacute", 556, NULL },
@@ -1379,24 +1706,37 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "t", 333, NULL },
{ "divide", 584, NULL },
{ "u", 611, NULL },
+ { "Ccaron", 722, NULL },
{ "v", 556, NULL },
{ "w", 778, NULL },
{ "x", 556, NULL },
{ "y", 556, NULL },
{ "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 474, NULL },
+ { "gcommaaccent", 611, NULL },
{ "mu", 611, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 667, NULL },
{ "Lslash", 611, NULL },
{ "semicolon", 333, NULL },
{ "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 556, NULL },
{ "Ecircumflex", 667, NULL },
+ { "gbreve", 611, NULL },
{ "trademark", 1000, NULL },
{ "daggerdbl", 556, NULL },
+ { "nacute", 611, NULL },
{ "macron", 333, NULL },
{ "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 556, NULL },
{ "AE", 1000, NULL },
@@ -1410,9 +1750,11 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "exclamdown", 333, NULL },
{ "endash", 556, NULL },
{ "oe", 944, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 556, NULL },
- { "copyright", 737, NULL },
{ "Adieresis", 722, NULL },
+ { "copyright", 737, NULL },
{ "Egrave", 667, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 667, NULL },
@@ -1420,14 +1762,17 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "Idieresis", 278, NULL },
{ "parenleft", 333, NULL },
{ "one", 556, NULL },
- { "ucircumflex", 611, NULL },
+ { "emacron", 556, NULL },
{ "Odieresis", 778, NULL },
+ { "ucircumflex", 611, NULL },
{ "bracketleft", 333, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 278, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 667, NULL },
+ { "umacron", 611, NULL },
+ { "abreve", 556, NULL },
{ "Eacute", 667, NULL },
{ "adieresis", 556, NULL },
{ "egrave", 556, NULL },
@@ -1443,111 +1788,174 @@ static BuiltinFontWidth helveticaBoldWidthsTab[] = {
{ "five", 556, NULL },
{ "udieresis", 611, NULL },
{ "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
{ "threequarters", 834, NULL },
{ "guillemotright", 556, NULL },
- { "ydieresis", 556, NULL },
{ "Ccedilla", 722, NULL },
+ { "ydieresis", 556, NULL },
{ "tilde", 333, NULL },
+ { "dbldaggerumlaut", 556, NULL },
{ "at", 975, NULL },
{ "eacute", 556, NULL },
{ "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 584, NULL },
{ "zero", 556, NULL },
{ "eth", 611, NULL },
+ { "Scedilla", 667, NULL },
{ "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 494, NULL },
{ "uacute", 611, NULL },
{ "braceleft", 389, NULL },
{ "Thorn", 667, NULL },
{ "zcaron", 500, NULL },
+ { "scommaaccent", 556, NULL },
{ "ccedilla", 556, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 611, NULL },
{ "Ocircumflex", 778, NULL },
{ "Oacute", 778, NULL },
+ { "scedilla", 556, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 611, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
{ "thorn", 611, NULL },
{ "degree", 400, NULL },
{ "registered", 737, NULL },
+ { "radical", 549, NULL },
{ "Aring", 722, NULL },
{ "percent", 889, NULL },
{ "six", 556, NULL },
{ "paragraph", 556, NULL },
+ { "dcaron", 743, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 556, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 278, NULL },
+ { "Lacute", 611, NULL },
{ "ocircumflex", 611, NULL },
{ "oacute", 611, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 389, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
{ "asciicircum", 584, NULL },
{ "aring", 556, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 611, NULL },
{ "bracketright", 333, NULL },
{ "Iacute", 278, NULL },
{ "ampersand", 722, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 584, NULL },
+ { "uring", 611, NULL },
{ "quotesinglbase", 278, NULL },
+ { "lcommaaccent", 278, NULL },
{ "Yacute", 667, NULL },
+ { "ohungarumlaut", 611, NULL },
{ "threesuperior", 333, NULL },
{ "acute", 333, NULL },
{ "section", 556, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 500, NULL },
+ { "ncaron", 611, NULL },
{ "florin", 556, NULL },
{ "yacute", 556, NULL },
+ { "Rcommaaccent", 722, NULL },
{ "fi", 611, NULL },
{ "fl", 611, NULL },
{ "Acircumflex", 722, NULL },
+ { "Cacute", 722, NULL },
{ "Icircumflex", 278, NULL },
{ "guillemotleft", 556, NULL },
{ "germandbls", 611, NULL },
+ { "Amacron", 722, NULL },
{ "seven", 556, NULL },
+ { "Sacute", 667, NULL },
{ "ordmasculine", 365, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 611, NULL },
{ "acircumflex", 556, NULL },
+ { "cacute", 556, NULL },
+ { "Ecaron", 667, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 389, NULL },
{ "quotedblright", 500, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 556, NULL },
+ { "imacron", 278, NULL },
{ "cent", 556, NULL },
{ "currency", 556, NULL },
{ "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
{ "Atilde", 722, NULL },
{ "breve", 333, NULL },
{ "bar", 280, NULL },
{ "fraction", 167, NULL },
{ "less", 584, NULL },
+ { "ecaron", 556, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 333, NULL },
{ "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 722, NULL },
{ "greater", 584, NULL },
{ "atilde", 556, NULL },
{ "brokenbar", 280, NULL },
{ "quoteleft", 278, NULL },
+ { "Edotaccent", 667, NULL },
{ "onesuperior", 333, NULL }
};
static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 556, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
{ "comma", 278, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 584, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
{ "asciitilde", 584, NULL },
{ "colon", 333, NULL },
{ "onehalf", 834, NULL },
{ "dollar", 556, NULL },
+ { "Lcaron", 611, NULL },
{ "ntilde", 611, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 611, NULL },
{ "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
{ "yen", 556, NULL },
{ "space", 278, NULL },
+ { "Omacron", 778, NULL },
{ "questiondown", 611, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 722, NULL },
{ "three", 556, NULL },
{ "numbersign", 556, NULL },
+ { "lcaron", 400, NULL },
{ "A", 722, NULL },
{ "B", 722, NULL },
{ "C", 722, NULL },
+ { "aogonek", 556, NULL },
{ "D", 722, NULL },
{ "E", 667, NULL },
{ "onequarter", 834, NULL },
@@ -1557,14 +1965,18 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "I", 278, NULL },
{ "J", 556, NULL },
{ "K", 722, NULL },
+ { "iogonek", 278, NULL },
{ "backslash", 278, NULL },
{ "L", 611, NULL },
{ "periodcentered", 278, NULL },
{ "M", 833, NULL },
{ "N", 722, NULL },
+ { "omacron", 611, NULL },
+ { "Tcommaaccent", 611, NULL },
{ "O", 778, NULL },
{ "P", 667, NULL },
{ "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 722, NULL },
{ "Aacute", 722, NULL },
{ "caron", 333, NULL },
@@ -1581,6 +1993,7 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "Z", 611, NULL },
{ "four", 556, NULL },
{ "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
{ "b", 611, NULL },
{ "c", 556, NULL },
{ "d", 611, NULL },
@@ -1597,11 +2010,13 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "l", 278, NULL },
{ "m", 889, NULL },
{ "n", 611, NULL },
+ { "tcommaaccent", 333, NULL },
{ "o", 611, NULL },
{ "ordfeminine", 370, NULL },
{ "ring", 333, NULL },
{ "p", 611, NULL },
{ "q", 611, NULL },
+ { "uhungarumlaut", 611, NULL },
{ "r", 389, NULL },
{ "twosuperior", 333, NULL },
{ "aacute", 556, NULL },
@@ -1610,24 +2025,37 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "t", 333, NULL },
{ "divide", 584, NULL },
{ "u", 611, NULL },
+ { "Ccaron", 722, NULL },
{ "v", 556, NULL },
{ "w", 778, NULL },
{ "x", 556, NULL },
{ "y", 556, NULL },
{ "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 474, NULL },
+ { "gcommaaccent", 611, NULL },
{ "mu", 611, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 667, NULL },
{ "Lslash", 611, NULL },
{ "semicolon", 333, NULL },
{ "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 556, NULL },
{ "Ecircumflex", 667, NULL },
+ { "gbreve", 611, NULL },
{ "trademark", 1000, NULL },
{ "daggerdbl", 556, NULL },
+ { "nacute", 611, NULL },
{ "macron", 333, NULL },
{ "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 556, NULL },
{ "AE", 1000, NULL },
@@ -1641,9 +2069,11 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "exclamdown", 333, NULL },
{ "endash", 556, NULL },
{ "oe", 944, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 556, NULL },
- { "copyright", 737, NULL },
{ "Adieresis", 722, NULL },
+ { "copyright", 737, NULL },
{ "Egrave", 667, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 667, NULL },
@@ -1651,14 +2081,17 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "Idieresis", 278, NULL },
{ "parenleft", 333, NULL },
{ "one", 556, NULL },
- { "ucircumflex", 611, NULL },
+ { "emacron", 556, NULL },
{ "Odieresis", 778, NULL },
+ { "ucircumflex", 611, NULL },
{ "bracketleft", 333, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 278, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 667, NULL },
+ { "umacron", 611, NULL },
+ { "abreve", 556, NULL },
{ "Eacute", 667, NULL },
{ "adieresis", 556, NULL },
{ "egrave", 556, NULL },
@@ -1674,111 +2107,173 @@ static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
{ "five", 556, NULL },
{ "udieresis", 611, NULL },
{ "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
{ "threequarters", 834, NULL },
{ "guillemotright", 556, NULL },
- { "ydieresis", 556, NULL },
{ "Ccedilla", 722, NULL },
+ { "ydieresis", 556, NULL },
{ "tilde", 333, NULL },
{ "at", 975, NULL },
{ "eacute", 556, NULL },
{ "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 584, NULL },
{ "zero", 556, NULL },
{ "eth", 611, NULL },
+ { "Scedilla", 667, NULL },
{ "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 494, NULL },
{ "uacute", 611, NULL },
{ "braceleft", 389, NULL },
{ "Thorn", 667, NULL },
{ "zcaron", 500, NULL },
+ { "scommaaccent", 556, NULL },
{ "ccedilla", 556, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 611, NULL },
{ "Ocircumflex", 778, NULL },
{ "Oacute", 778, NULL },
+ { "scedilla", 556, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 611, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
{ "thorn", 611, NULL },
{ "degree", 400, NULL },
{ "registered", 737, NULL },
+ { "radical", 549, NULL },
{ "Aring", 722, NULL },
{ "percent", 889, NULL },
{ "six", 556, NULL },
{ "paragraph", 556, NULL },
+ { "dcaron", 743, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 556, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 278, NULL },
+ { "Lacute", 611, NULL },
{ "ocircumflex", 611, NULL },
{ "oacute", 611, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 389, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
{ "asciicircum", 584, NULL },
{ "aring", 556, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 611, NULL },
{ "bracketright", 333, NULL },
{ "Iacute", 278, NULL },
{ "ampersand", 722, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 584, NULL },
+ { "uring", 611, NULL },
{ "quotesinglbase", 278, NULL },
+ { "lcommaaccent", 278, NULL },
{ "Yacute", 667, NULL },
+ { "ohungarumlaut", 611, NULL },
{ "threesuperior", 333, NULL },
{ "acute", 333, NULL },
{ "section", 556, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 500, NULL },
+ { "ncaron", 611, NULL },
{ "florin", 556, NULL },
{ "yacute", 556, NULL },
+ { "Rcommaaccent", 722, NULL },
{ "fi", 611, NULL },
{ "fl", 611, NULL },
{ "Acircumflex", 722, NULL },
+ { "Cacute", 722, NULL },
{ "Icircumflex", 278, NULL },
{ "guillemotleft", 556, NULL },
{ "germandbls", 611, NULL },
+ { "Amacron", 722, NULL },
{ "seven", 556, NULL },
+ { "Sacute", 667, NULL },
{ "ordmasculine", 365, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 611, NULL },
{ "acircumflex", 556, NULL },
+ { "cacute", 556, NULL },
+ { "Ecaron", 667, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 389, NULL },
{ "quotedblright", 500, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 556, NULL },
+ { "imacron", 278, NULL },
{ "cent", 556, NULL },
{ "currency", 556, NULL },
{ "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
{ "Atilde", 722, NULL },
{ "breve", 333, NULL },
{ "bar", 280, NULL },
{ "fraction", 167, NULL },
{ "less", 584, NULL },
+ { "ecaron", 556, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 333, NULL },
{ "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 722, NULL },
{ "greater", 584, NULL },
{ "atilde", 556, NULL },
{ "brokenbar", 280, NULL },
{ "quoteleft", 278, NULL },
+ { "Edotaccent", 667, NULL },
{ "onesuperior", 333, NULL }
};
static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 333, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
{ "comma", 278, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 584, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
{ "asciitilde", 584, NULL },
{ "colon", 278, NULL },
{ "onehalf", 834, NULL },
{ "dollar", 556, NULL },
+ { "Lcaron", 556, NULL },
{ "ntilde", 556, NULL },
+ { "Aogonek", 667, NULL },
+ { "ncommaaccent", 556, NULL },
{ "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
{ "yen", 556, NULL },
{ "space", 278, NULL },
+ { "Omacron", 778, NULL },
{ "questiondown", 611, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 667, NULL },
{ "three", 556, NULL },
{ "numbersign", 556, NULL },
+ { "lcaron", 299, NULL },
{ "A", 667, NULL },
{ "B", 667, NULL },
{ "C", 722, NULL },
+ { "aogonek", 556, NULL },
{ "D", 722, NULL },
{ "E", 667, NULL },
{ "onequarter", 834, NULL },
@@ -1788,14 +2283,18 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "I", 278, NULL },
{ "J", 500, NULL },
{ "K", 667, NULL },
+ { "iogonek", 222, NULL },
{ "backslash", 278, NULL },
{ "L", 556, NULL },
{ "periodcentered", 278, NULL },
{ "M", 833, NULL },
{ "N", 722, NULL },
+ { "omacron", 556, NULL },
+ { "Tcommaaccent", 611, NULL },
{ "O", 778, NULL },
{ "P", 667, NULL },
{ "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 722, NULL },
{ "Aacute", 667, NULL },
{ "caron", 333, NULL },
@@ -1812,6 +2311,7 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "Z", 611, NULL },
{ "four", 556, NULL },
{ "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
{ "b", 556, NULL },
{ "c", 500, NULL },
{ "d", 556, NULL },
@@ -1828,11 +2328,13 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "l", 222, NULL },
{ "m", 833, NULL },
{ "n", 556, NULL },
+ { "tcommaaccent", 278, NULL },
{ "o", 556, NULL },
{ "ordfeminine", 370, NULL },
{ "ring", 333, NULL },
{ "p", 556, NULL },
{ "q", 556, NULL },
+ { "uhungarumlaut", 556, NULL },
{ "r", 333, NULL },
{ "twosuperior", 333, NULL },
{ "aacute", 556, NULL },
@@ -1841,24 +2343,37 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "t", 278, NULL },
{ "divide", 584, NULL },
{ "u", 556, NULL },
+ { "Ccaron", 722, NULL },
{ "v", 500, NULL },
{ "w", 722, NULL },
{ "x", 500, NULL },
{ "y", 500, NULL },
{ "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 355, NULL },
+ { "gcommaaccent", 556, NULL },
{ "mu", 556, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 667, NULL },
{ "Lslash", 556, NULL },
{ "semicolon", 278, NULL },
{ "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 500, NULL },
{ "Ecircumflex", 667, NULL },
+ { "gbreve", 556, NULL },
{ "trademark", 1000, NULL },
{ "daggerdbl", 556, NULL },
+ { "nacute", 556, NULL },
{ "macron", 333, NULL },
{ "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 500, NULL },
{ "AE", 1000, NULL },
@@ -1872,9 +2387,11 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "exclamdown", 333, NULL },
{ "endash", 556, NULL },
{ "oe", 944, NULL },
+ { "Abreve", 667, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 556, NULL },
- { "copyright", 737, NULL },
{ "Adieresis", 667, NULL },
+ { "copyright", 737, NULL },
{ "Egrave", 667, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 667, NULL },
@@ -1882,14 +2399,17 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "Idieresis", 278, NULL },
{ "parenleft", 333, NULL },
{ "one", 556, NULL },
- { "ucircumflex", 556, NULL },
+ { "emacron", 556, NULL },
{ "Odieresis", 778, NULL },
+ { "ucircumflex", 556, NULL },
{ "bracketleft", 278, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 222, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 667, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 556, NULL },
{ "Eacute", 667, NULL },
{ "adieresis", 556, NULL },
{ "egrave", 556, NULL },
@@ -1905,85 +2425,134 @@ static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
{ "five", 556, NULL },
{ "udieresis", 556, NULL },
{ "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
{ "threequarters", 834, NULL },
{ "guillemotright", 556, NULL },
- { "ydieresis", 500, NULL },
{ "Ccedilla", 722, NULL },
+ { "ydieresis", 500, NULL },
{ "tilde", 333, NULL },
{ "at", 1015, NULL },
{ "eacute", 556, NULL },
{ "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 584, NULL },
{ "zero", 556, NULL },
{ "eth", 556, NULL },
+ { "Scedilla", 667, NULL },
{ "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 476, NULL },
{ "uacute", 556, NULL },
{ "braceleft", 334, NULL },
{ "Thorn", 667, NULL },
{ "zcaron", 500, NULL },
+ { "scommaaccent", 500, NULL },
{ "ccedilla", 500, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 556, NULL },
{ "Ocircumflex", 778, NULL },
{ "Oacute", 778, NULL },
+ { "scedilla", 500, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 556, NULL },
+ { "racute", 333, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
{ "thorn", 556, NULL },
{ "degree", 400, NULL },
{ "registered", 737, NULL },
+ { "radical", 453, NULL },
{ "Aring", 667, NULL },
{ "percent", 889, NULL },
{ "six", 556, NULL },
{ "paragraph", 537, NULL },
+ { "dcaron", 643, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 556, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 278, NULL },
+ { "Lacute", 556, NULL },
{ "ocircumflex", 556, NULL },
{ "oacute", 556, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 556, NULL },
+ { "tcaron", 317, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
{ "asciicircum", 469, NULL },
{ "aring", 556, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 556, NULL },
{ "bracketright", 278, NULL },
{ "Iacute", 278, NULL },
{ "ampersand", 667, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 222, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 584, NULL },
+ { "uring", 556, NULL },
{ "quotesinglbase", 222, NULL },
+ { "lcommaaccent", 222, NULL },
{ "Yacute", 667, NULL },
+ { "ohungarumlaut", 556, NULL },
{ "threesuperior", 333, NULL },
{ "acute", 333, NULL },
{ "section", 556, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 333, NULL },
+ { "ncaron", 556, NULL },
{ "florin", 556, NULL },
{ "yacute", 500, NULL },
+ { "Rcommaaccent", 722, NULL },
{ "fi", 500, NULL },
{ "fl", 500, NULL },
{ "Acircumflex", 667, NULL },
+ { "Cacute", 722, NULL },
{ "Icircumflex", 278, NULL },
{ "guillemotleft", 556, NULL },
{ "germandbls", 611, NULL },
+ { "Amacron", 667, NULL },
{ "seven", 556, NULL },
+ { "Sacute", 667, NULL },
{ "ordmasculine", 365, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 333, NULL },
+ { "Zdotaccent", 611, NULL },
{ "acircumflex", 556, NULL },
+ { "cacute", 500, NULL },
+ { "Ecaron", 667, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 334, NULL },
{ "quotedblright", 333, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 500, NULL },
+ { "imacron", 278, NULL },
{ "cent", 556, NULL },
{ "currency", 556, NULL },
{ "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
{ "Atilde", 667, NULL },
{ "breve", 333, NULL },
{ "bar", 260, NULL },
{ "fraction", 167, NULL },
{ "less", 584, NULL },
+ { "ecaron", 556, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 278, NULL },
{ "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 667, NULL },
{ "greater", 584, NULL },
{ "atilde", 556, NULL },
{ "brokenbar", 260, NULL },
{ "quoteleft", 222, NULL },
+ { "Edotaccent", 667, NULL },
{ "onesuperior", 333, NULL }
};
@@ -2098,6 +2667,7 @@ static BuiltinFontWidth symbolWidthsTab[] = {
{ "parenrighttp", 384, NULL },
{ "eta", 603, NULL },
{ "underscore", 500, NULL },
+ { "Euro", 750, NULL },
{ "multiply", 549, NULL },
{ "zero", 500, NULL },
{ "partialdiff", 494, NULL },
@@ -2181,27 +2751,40 @@ static BuiltinFontWidth symbolWidthsTab[] = {
static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 444, NULL },
+ { "kcommaaccent", 556, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 667, NULL },
{ "comma", 250, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 570, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
{ "asciitilde", 520, NULL },
{ "colon", 333, NULL },
{ "onehalf", 750, NULL },
{ "dollar", 500, NULL },
+ { "Lcaron", 667, NULL },
{ "ntilde", 556, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 556, NULL },
{ "minus", 570, NULL },
+ { "Iogonek", 389, NULL },
+ { "zacute", 444, NULL },
{ "yen", 500, NULL },
{ "space", 250, NULL },
+ { "Omacron", 778, NULL },
{ "questiondown", 500, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 722, NULL },
{ "three", 500, NULL },
{ "numbersign", 500, NULL },
+ { "lcaron", 394, NULL },
{ "A", 722, NULL },
{ "B", 667, NULL },
{ "C", 722, NULL },
+ { "aogonek", 500, NULL },
{ "D", 722, NULL },
{ "E", 667, NULL },
{ "onequarter", 750, NULL },
@@ -2211,14 +2794,18 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "I", 389, NULL },
{ "J", 500, NULL },
{ "K", 778, NULL },
+ { "iogonek", 278, NULL },
{ "backslash", 278, NULL },
{ "L", 667, NULL },
{ "periodcentered", 250, NULL },
{ "M", 944, NULL },
{ "N", 722, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 667, NULL },
{ "O", 778, NULL },
{ "P", 611, NULL },
{ "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 722, NULL },
{ "Aacute", 722, NULL },
{ "caron", 333, NULL },
@@ -2235,6 +2822,7 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "Z", 667, NULL },
{ "four", 500, NULL },
{ "a", 500, NULL },
+ { "Gcommaaccent", 778, NULL },
{ "b", 556, NULL },
{ "c", 444, NULL },
{ "d", 556, NULL },
@@ -2251,11 +2839,13 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "l", 278, NULL },
{ "m", 833, NULL },
{ "n", 556, NULL },
+ { "tcommaaccent", 333, NULL },
{ "o", 500, NULL },
{ "ordfeminine", 300, NULL },
{ "ring", 333, NULL },
{ "p", 556, NULL },
{ "q", 556, NULL },
+ { "uhungarumlaut", 556, NULL },
{ "r", 444, NULL },
{ "twosuperior", 300, NULL },
{ "aacute", 500, NULL },
@@ -2264,24 +2854,37 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "t", 333, NULL },
{ "divide", 570, NULL },
{ "u", 556, NULL },
+ { "Ccaron", 722, NULL },
{ "v", 500, NULL },
{ "w", 722, NULL },
{ "x", 500, NULL },
{ "y", 500, NULL },
{ "z", 444, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 389, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 555, NULL },
+ { "gcommaaccent", 500, NULL },
{ "mu", 556, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 556, NULL },
{ "Lslash", 667, NULL },
{ "semicolon", 333, NULL },
{ "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
{ "Ecircumflex", 667, NULL },
+ { "gbreve", 500, NULL },
{ "trademark", 1000, NULL },
{ "daggerdbl", 500, NULL },
+ { "nacute", 556, NULL },
{ "macron", 333, NULL },
{ "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 389, NULL },
{ "AE", 1000, NULL },
@@ -2295,9 +2898,11 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "exclamdown", 333, NULL },
{ "endash", 500, NULL },
{ "oe", 722, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 444, NULL },
- { "copyright", 747, NULL },
{ "Adieresis", 722, NULL },
+ { "copyright", 747, NULL },
{ "Egrave", 667, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 667, NULL },
@@ -2305,14 +2910,17 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "Idieresis", 389, NULL },
{ "parenleft", 333, NULL },
{ "one", 500, NULL },
- { "ucircumflex", 556, NULL },
+ { "emacron", 444, NULL },
{ "Odieresis", 778, NULL },
+ { "ucircumflex", 556, NULL },
{ "bracketleft", 333, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 333, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 722, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 500, NULL },
{ "Eacute", 667, NULL },
{ "adieresis", 500, NULL },
{ "egrave", 444, NULL },
@@ -2328,111 +2936,173 @@ static BuiltinFontWidth timesBoldWidthsTab[] = {
{ "five", 500, NULL },
{ "udieresis", 556, NULL },
{ "Zcaron", 667, NULL },
+ { "Scommaaccent", 556, NULL },
{ "threequarters", 750, NULL },
{ "guillemotright", 500, NULL },
- { "ydieresis", 500, NULL },
{ "Ccedilla", 722, NULL },
+ { "ydieresis", 500, NULL },
{ "tilde", 333, NULL },
{ "at", 930, NULL },
{ "eacute", 444, NULL },
{ "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 570, NULL },
{ "zero", 500, NULL },
{ "eth", 500, NULL },
+ { "Scedilla", 556, NULL },
{ "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 494, NULL },
{ "uacute", 556, NULL },
{ "braceleft", 394, NULL },
{ "Thorn", 611, NULL },
{ "zcaron", 444, NULL },
+ { "scommaaccent", 389, NULL },
{ "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 556, NULL },
{ "Ocircumflex", 778, NULL },
{ "Oacute", 778, NULL },
+ { "scedilla", 389, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 500, NULL },
+ { "racute", 444, NULL },
+ { "Tcaron", 667, NULL },
+ { "Eogonek", 667, NULL },
{ "thorn", 556, NULL },
{ "degree", 400, NULL },
{ "registered", 747, NULL },
+ { "radical", 549, NULL },
{ "Aring", 722, NULL },
{ "percent", 1000, NULL },
{ "six", 500, NULL },
{ "paragraph", 540, NULL },
+ { "dcaron", 672, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 500, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 389, NULL },
+ { "Lacute", 667, NULL },
{ "ocircumflex", 500, NULL },
{ "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 667, NULL },
+ { "tcaron", 416, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
{ "asciicircum", 581, NULL },
{ "aring", 500, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 556, NULL },
{ "bracketright", 333, NULL },
{ "Iacute", 389, NULL },
{ "ampersand", 833, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 570, NULL },
+ { "uring", 556, NULL },
{ "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
{ "Yacute", 722, NULL },
+ { "ohungarumlaut", 500, NULL },
{ "threesuperior", 300, NULL },
{ "acute", 333, NULL },
{ "section", 500, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 500, NULL },
+ { "ncaron", 556, NULL },
{ "florin", 500, NULL },
{ "yacute", 500, NULL },
+ { "Rcommaaccent", 722, NULL },
{ "fi", 556, NULL },
{ "fl", 556, NULL },
{ "Acircumflex", 722, NULL },
+ { "Cacute", 722, NULL },
{ "Icircumflex", 389, NULL },
{ "guillemotleft", 500, NULL },
{ "germandbls", 556, NULL },
+ { "Amacron", 722, NULL },
{ "seven", 500, NULL },
+ { "Sacute", 556, NULL },
{ "ordmasculine", 330, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 389, NULL },
+ { "rcommaaccent", 444, NULL },
+ { "Zdotaccent", 667, NULL },
{ "acircumflex", 500, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 667, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 394, NULL },
{ "quotedblright", 500, NULL },
+ { "amacron", 500, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
{ "cent", 500, NULL },
{ "currency", 500, NULL },
{ "logicalnot", 570, NULL },
+ { "zdotaccent", 444, NULL },
{ "Atilde", 722, NULL },
{ "breve", 333, NULL },
{ "bar", 220, NULL },
{ "fraction", 167, NULL },
{ "less", 570, NULL },
+ { "ecaron", 444, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 333, NULL },
{ "period", 250, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 778, NULL },
{ "greater", 570, NULL },
{ "atilde", 500, NULL },
{ "brokenbar", 220, NULL },
{ "quoteleft", 333, NULL },
+ { "Edotaccent", 667, NULL },
{ "onesuperior", 300, NULL }
};
static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
{ "comma", 250, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 570, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
{ "asciitilde", 570, NULL },
{ "colon", 333, NULL },
{ "onehalf", 750, NULL },
{ "dollar", 500, NULL },
+ { "Lcaron", 611, NULL },
{ "ntilde", 556, NULL },
+ { "Aogonek", 667, NULL },
+ { "ncommaaccent", 556, NULL },
{ "minus", 606, NULL },
+ { "Iogonek", 389, NULL },
+ { "zacute", 389, NULL },
{ "yen", 500, NULL },
{ "space", 250, NULL },
+ { "Omacron", 722, NULL },
{ "questiondown", 500, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 667, NULL },
{ "three", 500, NULL },
{ "numbersign", 500, NULL },
+ { "lcaron", 382, NULL },
{ "A", 667, NULL },
{ "B", 667, NULL },
{ "C", 667, NULL },
+ { "aogonek", 500, NULL },
{ "D", 722, NULL },
{ "E", 667, NULL },
{ "onequarter", 750, NULL },
@@ -2442,14 +3112,18 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "I", 389, NULL },
{ "J", 500, NULL },
{ "K", 667, NULL },
+ { "iogonek", 278, NULL },
{ "backslash", 278, NULL },
{ "L", 611, NULL },
{ "periodcentered", 250, NULL },
{ "M", 889, NULL },
{ "N", 722, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 611, NULL },
{ "O", 722, NULL },
{ "P", 611, NULL },
{ "Q", 722, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 667, NULL },
{ "Aacute", 667, NULL },
{ "caron", 333, NULL },
@@ -2466,6 +3140,7 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "Z", 611, NULL },
{ "four", 500, NULL },
{ "a", 500, NULL },
+ { "Gcommaaccent", 722, NULL },
{ "b", 500, NULL },
{ "c", 444, NULL },
{ "d", 500, NULL },
@@ -2482,11 +3157,13 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "l", 278, NULL },
{ "m", 778, NULL },
{ "n", 556, NULL },
+ { "tcommaaccent", 278, NULL },
{ "o", 500, NULL },
{ "ordfeminine", 266, NULL },
{ "ring", 333, NULL },
{ "p", 500, NULL },
{ "q", 500, NULL },
+ { "uhungarumlaut", 556, NULL },
{ "r", 389, NULL },
{ "twosuperior", 300, NULL },
{ "aacute", 500, NULL },
@@ -2495,24 +3172,37 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "t", 278, NULL },
{ "divide", 570, NULL },
{ "u", 556, NULL },
+ { "Ccaron", 667, NULL },
{ "v", 444, NULL },
{ "w", 667, NULL },
{ "x", 500, NULL },
{ "y", 444, NULL },
{ "z", 389, NULL },
+ { "Gbreve", 722, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 389, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 555, NULL },
+ { "gcommaaccent", 500, NULL },
{ "mu", 576, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 556, NULL },
{ "Lslash", 611, NULL },
{ "semicolon", 333, NULL },
{ "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
{ "Ecircumflex", 667, NULL },
+ { "gbreve", 500, NULL },
{ "trademark", 1000, NULL },
{ "daggerdbl", 500, NULL },
+ { "nacute", 556, NULL },
{ "macron", 333, NULL },
{ "Otilde", 722, NULL },
+ { "Emacron", 667, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 389, NULL },
{ "AE", 944, NULL },
@@ -2526,9 +3216,11 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "exclamdown", 389, NULL },
{ "endash", 500, NULL },
{ "oe", 722, NULL },
+ { "Abreve", 667, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 444, NULL },
- { "copyright", 747, NULL },
{ "Adieresis", 667, NULL },
+ { "copyright", 747, NULL },
{ "Egrave", 667, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 667, NULL },
@@ -2536,14 +3228,17 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "Idieresis", 389, NULL },
{ "parenleft", 333, NULL },
{ "one", 500, NULL },
- { "ucircumflex", 556, NULL },
+ { "emacron", 444, NULL },
{ "Odieresis", 722, NULL },
+ { "ucircumflex", 556, NULL },
{ "bracketleft", 333, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 333, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 611, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 500, NULL },
{ "Eacute", 667, NULL },
{ "adieresis", 500, NULL },
{ "egrave", 444, NULL },
@@ -2559,111 +3254,173 @@ static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
{ "five", 500, NULL },
{ "udieresis", 556, NULL },
{ "Zcaron", 611, NULL },
+ { "Scommaaccent", 556, NULL },
{ "threequarters", 750, NULL },
{ "guillemotright", 500, NULL },
- { "ydieresis", 444, NULL },
{ "Ccedilla", 667, NULL },
+ { "ydieresis", 444, NULL },
{ "tilde", 333, NULL },
{ "at", 832, NULL },
{ "eacute", 444, NULL },
{ "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 570, NULL },
{ "zero", 500, NULL },
{ "eth", 500, NULL },
+ { "Scedilla", 556, NULL },
{ "Ograve", 722, NULL },
+ { "Racute", 667, NULL },
+ { "partialdiff", 494, NULL },
{ "uacute", 556, NULL },
{ "braceleft", 348, NULL },
{ "Thorn", 611, NULL },
{ "zcaron", 389, NULL },
+ { "scommaaccent", 389, NULL },
{ "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 500, NULL },
{ "Ocircumflex", 722, NULL },
{ "Oacute", 722, NULL },
+ { "scedilla", 389, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 500, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
{ "thorn", 500, NULL },
{ "degree", 400, NULL },
{ "registered", 747, NULL },
+ { "radical", 549, NULL },
{ "Aring", 667, NULL },
{ "percent", 833, NULL },
{ "six", 500, NULL },
{ "paragraph", 500, NULL },
+ { "dcaron", 608, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 500, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 389, NULL },
+ { "Lacute", 611, NULL },
{ "ocircumflex", 500, NULL },
{ "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 366, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 722, NULL },
{ "asciicircum", 570, NULL },
{ "aring", 500, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 556, NULL },
{ "bracketright", 333, NULL },
{ "Iacute", 389, NULL },
{ "ampersand", 778, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 570, NULL },
+ { "uring", 556, NULL },
{ "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
{ "Yacute", 611, NULL },
+ { "ohungarumlaut", 500, NULL },
{ "threesuperior", 300, NULL },
{ "acute", 333, NULL },
{ "section", 500, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 500, NULL },
+ { "ncaron", 556, NULL },
{ "florin", 500, NULL },
{ "yacute", 444, NULL },
+ { "Rcommaaccent", 667, NULL },
{ "fi", 556, NULL },
{ "fl", 556, NULL },
{ "Acircumflex", 667, NULL },
+ { "Cacute", 667, NULL },
{ "Icircumflex", 389, NULL },
{ "guillemotleft", 500, NULL },
{ "germandbls", 500, NULL },
+ { "Amacron", 667, NULL },
{ "seven", 500, NULL },
+ { "Sacute", 556, NULL },
{ "ordmasculine", 300, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 389, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 611, NULL },
{ "acircumflex", 500, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 667, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 348, NULL },
{ "quotedblright", 500, NULL },
+ { "amacron", 500, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
{ "cent", 500, NULL },
{ "currency", 500, NULL },
{ "logicalnot", 606, NULL },
+ { "zdotaccent", 389, NULL },
{ "Atilde", 667, NULL },
{ "breve", 333, NULL },
{ "bar", 220, NULL },
{ "fraction", 167, NULL },
{ "less", 570, NULL },
+ { "ecaron", 444, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 389, NULL },
{ "period", 250, NULL },
+ { "Rcaron", 667, NULL },
+ { "Kcommaaccent", 667, NULL },
{ "greater", 570, NULL },
{ "atilde", 500, NULL },
{ "brokenbar", 220, NULL },
{ "quoteleft", 333, NULL },
+ { "Edotaccent", 667, NULL },
{ "onesuperior", 300, NULL }
};
static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "Ntilde", 667, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 444, NULL },
+ { "Ncommaaccent", 667, NULL },
+ { "Zacute", 556, NULL },
{ "comma", 250, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 675, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
{ "asciitilde", 541, NULL },
{ "colon", 333, NULL },
{ "onehalf", 750, NULL },
{ "dollar", 500, NULL },
+ { "Lcaron", 611, NULL },
{ "ntilde", 500, NULL },
+ { "Aogonek", 611, NULL },
+ { "ncommaaccent", 500, NULL },
{ "minus", 675, NULL },
+ { "Iogonek", 333, NULL },
+ { "zacute", 389, NULL },
{ "yen", 500, NULL },
{ "space", 250, NULL },
+ { "Omacron", 722, NULL },
{ "questiondown", 500, NULL },
{ "emdash", 889, NULL },
{ "Agrave", 611, NULL },
{ "three", 500, NULL },
{ "numbersign", 500, NULL },
+ { "lcaron", 300, NULL },
{ "A", 611, NULL },
{ "B", 611, NULL },
{ "C", 667, NULL },
+ { "aogonek", 500, NULL },
{ "D", 722, NULL },
{ "E", 611, NULL },
{ "onequarter", 750, NULL },
@@ -2673,14 +3430,18 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "I", 333, NULL },
{ "J", 444, NULL },
{ "K", 667, NULL },
+ { "iogonek", 278, NULL },
{ "backslash", 278, NULL },
{ "L", 556, NULL },
{ "periodcentered", 250, NULL },
{ "M", 833, NULL },
{ "N", 667, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 556, NULL },
{ "O", 722, NULL },
{ "P", 611, NULL },
{ "Q", 722, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 611, NULL },
{ "Aacute", 611, NULL },
{ "caron", 333, NULL },
@@ -2697,6 +3458,7 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "Z", 556, NULL },
{ "four", 500, NULL },
{ "a", 500, NULL },
+ { "Gcommaaccent", 722, NULL },
{ "b", 500, NULL },
{ "c", 444, NULL },
{ "d", 500, NULL },
@@ -2713,11 +3475,13 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "l", 278, NULL },
{ "m", 722, NULL },
{ "n", 500, NULL },
+ { "tcommaaccent", 278, NULL },
{ "o", 500, NULL },
{ "ordfeminine", 276, NULL },
{ "ring", 333, NULL },
{ "p", 500, NULL },
{ "q", 500, NULL },
+ { "uhungarumlaut", 500, NULL },
{ "r", 389, NULL },
{ "twosuperior", 300, NULL },
{ "aacute", 500, NULL },
@@ -2726,24 +3490,37 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "t", 278, NULL },
{ "divide", 675, NULL },
{ "u", 500, NULL },
+ { "Ccaron", 667, NULL },
{ "v", 444, NULL },
{ "w", 667, NULL },
{ "x", 444, NULL },
{ "y", 444, NULL },
{ "z", 389, NULL },
+ { "Gbreve", 722, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 333, NULL },
+ { "Nacute", 667, NULL },
{ "quotedbl", 420, NULL },
+ { "gcommaaccent", 500, NULL },
{ "mu", 500, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 500, NULL },
{ "Lslash", 556, NULL },
{ "semicolon", 333, NULL },
{ "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
{ "Ecircumflex", 611, NULL },
+ { "gbreve", 500, NULL },
{ "trademark", 980, NULL },
{ "daggerdbl", 500, NULL },
+ { "nacute", 500, NULL },
{ "macron", 333, NULL },
{ "Otilde", 722, NULL },
+ { "Emacron", 611, NULL },
{ "ellipsis", 889, NULL },
{ "scaron", 389, NULL },
{ "AE", 889, NULL },
@@ -2757,9 +3534,11 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "exclamdown", 389, NULL },
{ "endash", 500, NULL },
{ "oe", 667, NULL },
+ { "Abreve", 611, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 444, NULL },
- { "copyright", 760, NULL },
{ "Adieresis", 611, NULL },
+ { "copyright", 760, NULL },
{ "Egrave", 611, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 611, NULL },
@@ -2767,14 +3546,17 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "Idieresis", 333, NULL },
{ "parenleft", 333, NULL },
{ "one", 500, NULL },
- { "ucircumflex", 500, NULL },
+ { "emacron", 444, NULL },
{ "Odieresis", 722, NULL },
+ { "ucircumflex", 500, NULL },
{ "bracketleft", 389, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 333, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 556, NULL },
+ { "umacron", 500, NULL },
+ { "abreve", 500, NULL },
{ "Eacute", 611, NULL },
{ "adieresis", 500, NULL },
{ "egrave", 444, NULL },
@@ -2790,111 +3572,173 @@ static BuiltinFontWidth timesItalicWidthsTab[] = {
{ "five", 500, NULL },
{ "udieresis", 500, NULL },
{ "Zcaron", 556, NULL },
+ { "Scommaaccent", 500, NULL },
{ "threequarters", 750, NULL },
{ "guillemotright", 500, NULL },
- { "ydieresis", 444, NULL },
{ "Ccedilla", 667, NULL },
+ { "ydieresis", 444, NULL },
{ "tilde", 333, NULL },
{ "at", 920, NULL },
{ "eacute", 444, NULL },
{ "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 675, NULL },
{ "zero", 500, NULL },
{ "eth", 500, NULL },
+ { "Scedilla", 500, NULL },
{ "Ograve", 722, NULL },
+ { "Racute", 611, NULL },
+ { "partialdiff", 476, NULL },
{ "uacute", 500, NULL },
{ "braceleft", 400, NULL },
{ "Thorn", 611, NULL },
{ "zcaron", 389, NULL },
+ { "scommaaccent", 389, NULL },
{ "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 500, NULL },
{ "Ocircumflex", 722, NULL },
{ "Oacute", 722, NULL },
+ { "scedilla", 389, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 500, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 556, NULL },
+ { "Eogonek", 611, NULL },
{ "thorn", 500, NULL },
{ "degree", 400, NULL },
{ "registered", 760, NULL },
+ { "radical", 453, NULL },
{ "Aring", 611, NULL },
{ "percent", 833, NULL },
{ "six", 500, NULL },
{ "paragraph", 523, NULL },
+ { "dcaron", 544, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 500, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 333, NULL },
+ { "Lacute", 556, NULL },
{ "ocircumflex", 500, NULL },
{ "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 556, NULL },
+ { "tcaron", 300, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 722, NULL },
{ "asciicircum", 422, NULL },
{ "aring", 500, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 500, NULL },
{ "bracketright", 389, NULL },
{ "Iacute", 333, NULL },
{ "ampersand", 778, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 667, NULL },
{ "plus", 675, NULL },
+ { "uring", 500, NULL },
{ "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
{ "Yacute", 556, NULL },
+ { "ohungarumlaut", 500, NULL },
{ "threesuperior", 300, NULL },
{ "acute", 333, NULL },
{ "section", 500, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 556, NULL },
+ { "ncaron", 500, NULL },
{ "florin", 500, NULL },
{ "yacute", 444, NULL },
+ { "Rcommaaccent", 611, NULL },
{ "fi", 500, NULL },
{ "fl", 500, NULL },
{ "Acircumflex", 611, NULL },
+ { "Cacute", 667, NULL },
{ "Icircumflex", 333, NULL },
{ "guillemotleft", 500, NULL },
{ "germandbls", 500, NULL },
+ { "Amacron", 611, NULL },
{ "seven", 500, NULL },
+ { "Sacute", 500, NULL },
{ "ordmasculine", 310, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 333, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 556, NULL },
{ "acircumflex", 500, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 611, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 400, NULL },
{ "quotedblright", 556, NULL },
+ { "amacron", 500, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
{ "cent", 500, NULL },
{ "currency", 500, NULL },
{ "logicalnot", 675, NULL },
+ { "zdotaccent", 389, NULL },
{ "Atilde", 611, NULL },
{ "breve", 333, NULL },
{ "bar", 275, NULL },
{ "fraction", 167, NULL },
{ "less", 675, NULL },
+ { "ecaron", 444, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 333, NULL },
{ "period", 250, NULL },
+ { "Rcaron", 611, NULL },
+ { "Kcommaaccent", 667, NULL },
{ "greater", 675, NULL },
{ "atilde", 500, NULL },
{ "brokenbar", 275, NULL },
{ "quoteleft", 333, NULL },
+ { "Edotaccent", 611, NULL },
{ "onesuperior", 300, NULL }
};
static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "Ntilde", 722, NULL },
+ { "rcaron", 333, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
{ "comma", 250, NULL },
{ "cedilla", 333, NULL },
{ "plusminus", 564, NULL },
{ "circumflex", 333, NULL },
{ "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
{ "asciitilde", 541, NULL },
{ "colon", 278, NULL },
{ "onehalf", 750, NULL },
{ "dollar", 500, NULL },
+ { "Lcaron", 611, NULL },
{ "ntilde", 500, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 500, NULL },
{ "minus", 564, NULL },
+ { "Iogonek", 333, NULL },
+ { "zacute", 444, NULL },
{ "yen", 500, NULL },
{ "space", 250, NULL },
+ { "Omacron", 722, NULL },
{ "questiondown", 444, NULL },
{ "emdash", 1000, NULL },
{ "Agrave", 722, NULL },
{ "three", 500, NULL },
{ "numbersign", 500, NULL },
+ { "lcaron", 344, NULL },
{ "A", 722, NULL },
{ "B", 667, NULL },
{ "C", 667, NULL },
+ { "aogonek", 444, NULL },
{ "D", 722, NULL },
{ "E", 611, NULL },
{ "onequarter", 750, NULL },
@@ -2904,14 +3748,18 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "I", 333, NULL },
{ "J", 389, NULL },
{ "K", 722, NULL },
+ { "iogonek", 278, NULL },
{ "backslash", 278, NULL },
{ "L", 611, NULL },
{ "periodcentered", 250, NULL },
{ "M", 889, NULL },
{ "N", 722, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 611, NULL },
{ "O", 722, NULL },
{ "P", 556, NULL },
{ "Q", 722, NULL },
+ { "Uhungarumlaut", 722, NULL },
{ "R", 667, NULL },
{ "Aacute", 722, NULL },
{ "caron", 333, NULL },
@@ -2928,6 +3776,7 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "Z", 611, NULL },
{ "four", 500, NULL },
{ "a", 444, NULL },
+ { "Gcommaaccent", 722, NULL },
{ "b", 500, NULL },
{ "c", 444, NULL },
{ "d", 500, NULL },
@@ -2944,11 +3793,13 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "l", 278, NULL },
{ "m", 778, NULL },
{ "n", 500, NULL },
+ { "tcommaaccent", 278, NULL },
{ "o", 500, NULL },
{ "ordfeminine", 276, NULL },
{ "ring", 333, NULL },
{ "p", 500, NULL },
{ "q", 500, NULL },
+ { "uhungarumlaut", 500, NULL },
{ "r", 333, NULL },
{ "twosuperior", 300, NULL },
{ "aacute", 444, NULL },
@@ -2957,24 +3808,37 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "t", 278, NULL },
{ "divide", 564, NULL },
{ "u", 500, NULL },
+ { "Ccaron", 667, NULL },
{ "v", 500, NULL },
{ "w", 722, NULL },
{ "x", 500, NULL },
{ "y", 500, NULL },
{ "z", 444, NULL },
+ { "Gbreve", 722, NULL },
+ { "commaaccent", 250, NULL },
{ "hungarumlaut", 333, NULL },
+ { "Idotaccent", 333, NULL },
+ { "Nacute", 722, NULL },
{ "quotedbl", 408, NULL },
+ { "gcommaaccent", 500, NULL },
{ "mu", 500, NULL },
+ { "greaterequal", 549, NULL },
{ "Scaron", 556, NULL },
{ "Lslash", 611, NULL },
{ "semicolon", 278, NULL },
{ "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
{ "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
{ "Ecircumflex", 611, NULL },
+ { "gbreve", 500, NULL },
{ "trademark", 980, NULL },
{ "daggerdbl", 500, NULL },
+ { "nacute", 500, NULL },
{ "macron", 333, NULL },
{ "Otilde", 722, NULL },
+ { "Emacron", 611, NULL },
{ "ellipsis", 1000, NULL },
{ "scaron", 389, NULL },
{ "AE", 889, NULL },
@@ -2988,9 +3852,11 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "exclamdown", 333, NULL },
{ "endash", 500, NULL },
{ "oe", 722, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
{ "ecircumflex", 444, NULL },
- { "copyright", 760, NULL },
{ "Adieresis", 722, NULL },
+ { "copyright", 760, NULL },
{ "Egrave", 611, NULL },
{ "slash", 278, NULL },
{ "Edieresis", 611, NULL },
@@ -2998,14 +3864,17 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "Idieresis", 333, NULL },
{ "parenleft", 333, NULL },
{ "one", 500, NULL },
- { "ucircumflex", 500, NULL },
+ { "emacron", 444, NULL },
{ "Odieresis", 722, NULL },
+ { "ucircumflex", 500, NULL },
{ "bracketleft", 333, NULL },
{ "Ugrave", 722, NULL },
{ "quoteright", 333, NULL },
{ "Udieresis", 722, NULL },
{ "perthousand", 1000, NULL },
{ "Ydieresis", 722, NULL },
+ { "umacron", 500, NULL },
+ { "abreve", 444, NULL },
{ "Eacute", 611, NULL },
{ "adieresis", 444, NULL },
{ "egrave", 444, NULL },
@@ -3021,85 +3890,134 @@ static BuiltinFontWidth timesRomanWidthsTab[] = {
{ "five", 500, NULL },
{ "udieresis", 500, NULL },
{ "Zcaron", 611, NULL },
+ { "Scommaaccent", 556, NULL },
{ "threequarters", 750, NULL },
{ "guillemotright", 500, NULL },
- { "ydieresis", 500, NULL },
{ "Ccedilla", 667, NULL },
+ { "ydieresis", 500, NULL },
{ "tilde", 333, NULL },
{ "at", 921, NULL },
{ "eacute", 444, NULL },
{ "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
{ "multiply", 564, NULL },
{ "zero", 500, NULL },
{ "eth", 500, NULL },
+ { "Scedilla", 556, NULL },
{ "Ograve", 722, NULL },
+ { "Racute", 667, NULL },
+ { "partialdiff", 476, NULL },
{ "uacute", 500, NULL },
{ "braceleft", 480, NULL },
{ "Thorn", 556, NULL },
{ "zcaron", 444, NULL },
+ { "scommaaccent", 389, NULL },
{ "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 500, NULL },
{ "Ocircumflex", 722, NULL },
{ "Oacute", 722, NULL },
+ { "scedilla", 389, NULL },
{ "ogonek", 333, NULL },
{ "ograve", 500, NULL },
+ { "racute", 333, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 611, NULL },
{ "thorn", 500, NULL },
{ "degree", 400, NULL },
{ "registered", 760, NULL },
+ { "radical", 453, NULL },
{ "Aring", 722, NULL },
{ "percent", 833, NULL },
{ "six", 500, NULL },
{ "paragraph", 453, NULL },
+ { "dcaron", 588, NULL },
+ { "Uogonek", 722, NULL },
{ "two", 500, NULL },
+ { "summation", 600, NULL },
{ "Igrave", 333, NULL },
+ { "Lacute", 611, NULL },
{ "ocircumflex", 500, NULL },
{ "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 326, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 722, NULL },
{ "asciicircum", 469, NULL },
{ "aring", 444, NULL },
{ "grave", 333, NULL },
+ { "uogonek", 500, NULL },
{ "bracketright", 333, NULL },
{ "Iacute", 333, NULL },
{ "ampersand", 778, NULL },
{ "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
{ "plus", 564, NULL },
+ { "uring", 500, NULL },
{ "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
{ "Yacute", 722, NULL },
+ { "ohungarumlaut", 500, NULL },
{ "threesuperior", 300, NULL },
{ "acute", 333, NULL },
{ "section", 500, NULL },
{ "dieresis", 333, NULL },
{ "iacute", 278, NULL },
{ "quotedblbase", 444, NULL },
+ { "ncaron", 500, NULL },
{ "florin", 500, NULL },
{ "yacute", 500, NULL },
+ { "Rcommaaccent", 667, NULL },
{ "fi", 556, NULL },
{ "fl", 556, NULL },
{ "Acircumflex", 722, NULL },
+ { "Cacute", 667, NULL },
{ "Icircumflex", 333, NULL },
{ "guillemotleft", 500, NULL },
{ "germandbls", 500, NULL },
+ { "Amacron", 722, NULL },
{ "seven", 500, NULL },
+ { "Sacute", 556, NULL },
{ "ordmasculine", 310, NULL },
{ "dotlessi", 278, NULL },
{ "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 333, NULL },
+ { "rcommaaccent", 333, NULL },
+ { "Zdotaccent", 611, NULL },
{ "acircumflex", 444, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 611, NULL },
{ "icircumflex", 278, NULL },
{ "braceright", 480, NULL },
{ "quotedblright", 444, NULL },
+ { "amacron", 444, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
{ "cent", 500, NULL },
{ "currency", 500, NULL },
{ "logicalnot", 564, NULL },
+ { "zdotaccent", 444, NULL },
{ "Atilde", 722, NULL },
{ "breve", 333, NULL },
{ "bar", 200, NULL },
{ "fraction", 167, NULL },
{ "less", 564, NULL },
+ { "ecaron", 444, NULL },
{ "guilsinglleft", 333, NULL },
{ "exclam", 333, NULL },
{ "period", 250, NULL },
+ { "Rcaron", 667, NULL },
+ { "Kcommaaccent", 722, NULL },
{ "greater", 564, NULL },
{ "atilde", 444, NULL },
{ "brokenbar", 200, NULL },
{ "quoteleft", 333, NULL },
+ { "Edotaccent", 611, NULL },
{ "onesuperior", 300, NULL }
};
@@ -3278,10 +4196,10 @@ static BuiltinFontWidth zapfDingbatsWidthsTab[] = {
{ "a203", 762, NULL },
{ "a123", 788, NULL },
{ "a204", 759, NULL },
- { "a205", 509, NULL },
{ "a124", 788, NULL },
- { "a206", 410, NULL },
+ { "a205", 509, NULL },
{ "a125", 788, NULL },
+ { "a206", 410, NULL },
{ "a126", 788, NULL },
{ "a127", 788, NULL },
{ "a128", 788, NULL },
@@ -3309,19 +4227,19 @@ static BuiltinFontWidth zapfDingbatsWidthsTab[] = {
};
BuiltinFont builtinFonts[] = {
- { "Courier", standardEncoding, 624, -207, { -40, -290, 640, 795}, NULL },
- { "Courier-Bold", standardEncoding, 674, -257, {-100, -350, 700, 855}, NULL },
- { "Courier-BoldOblique", standardEncoding, 674, -257, {-145, -350, 817, 855}, NULL },
- { "Courier-Oblique", standardEncoding, 624, -207, { -85, -290, 759, 795}, NULL },
- { "Helvetica", standardEncoding, 729, -219, {-174, -220, 1001, 944}, NULL },
- { "Helvetica-Bold", standardEncoding, 729, -219, {-173, -221, 1003, 936}, NULL },
- { "Helvetica-BoldOblique", standardEncoding, 729, -219, {-177, -221, 1107, 936}, NULL },
- { "Helvetica-Oblique", standardEncoding, 729, -219, {-178, -220, 1108, 944}, NULL },
+ { "Courier", standardEncoding, 629, -157, { -23, -250, 715, 805}, NULL },
+ { "Courier-Bold", standardEncoding, 629, -157, {-113, -250, 749, 801}, NULL },
+ { "Courier-BoldOblique", standardEncoding, 629, -157, { -57, -250, 869, 801}, NULL },
+ { "Courier-Oblique", standardEncoding, 629, -157, { -27, -250, 849, 805}, NULL },
+ { "Helvetica", standardEncoding, 718, -207, {-166, -225, 1000, 931}, NULL },
+ { "Helvetica-Bold", standardEncoding, 718, -207, {-170, -228, 1003, 962}, NULL },
+ { "Helvetica-BoldOblique", standardEncoding, 718, -207, {-174, -228, 1114, 962}, NULL },
+ { "Helvetica-Oblique", standardEncoding, 718, -207, {-170, -225, 1116, 931}, NULL },
{ "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL },
- { "Times-Bold", standardEncoding, 670, -210, {-172, -256, 1008, 965}, NULL },
- { "Times-BoldItalic", standardEncoding, 682, -203, {-168, -232, 1014, 894}, NULL },
- { "Times-Italic", standardEncoding, 684, -206, {-176, -252, 990, 930}, NULL },
- { "Times-Roman", standardEncoding, 682, -217, {-170, -223, 1024, 896}, NULL },
+ { "Times-Bold", standardEncoding, 683, -217, {-168, -218, 1000, 935}, NULL },
+ { "Times-BoldItalic", standardEncoding, 683, -217, {-200, -218, 996, 921}, NULL },
+ { "Times-Italic", standardEncoding, 683, -217, {-169, -217, 1010, 883}, NULL },
+ { "Times-Roman", standardEncoding, 683, -217, {-168, -218, 1000, 898}, NULL },
{ "ZapfDingbats", zapfDingbatsEncoding, 820, -143, { -1, -143, 981, 820}, NULL }
};
@@ -3341,19 +4259,19 @@ BuiltinFont *builtinFontSubst[] = {
};
void initBuiltinFontTables() {
- builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 260);
- builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 260);
- builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 260);
- builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 260);
- builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 228);
- builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 228);
- builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 228);
- builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 228);
- builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 189);
- builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 228);
- builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 228);
- builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 228);
- builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 228);
+ builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 315);
+ builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 315);
+ builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 315);
+ builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 315);
+ builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 315);
+ builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 316);
+ builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 315);
+ builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 315);
+ builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 190);
+ builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 315);
+ builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 315);
+ builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 315);
+ builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 315);
builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202);
}
diff --git a/pdf2swf/xpdf/BuiltinFontTables.h b/pdf2swf/xpdf/BuiltinFontTables.h
index 3a8892e5..eb45549e 100644
--- a/pdf2swf/xpdf/BuiltinFontTables.h
+++ b/pdf2swf/xpdf/BuiltinFontTables.h
@@ -2,7 +2,7 @@
//
// BuiltinFontTables.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
diff --git a/pdf2swf/xpdf/CMap.cc b/pdf2swf/xpdf/CMap.cc
index b49cffdc..25f3af75 100644
--- a/pdf2swf/xpdf/CMap.cc
+++ b/pdf2swf/xpdf/CMap.cc
@@ -2,15 +2,16 @@
//
// CMap.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -143,6 +144,9 @@ CMap::CMap(GString *collectionA, GString *cMapNameA) {
vector[i].cid = 0;
}
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
@@ -151,6 +155,9 @@ CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
wMode = wModeA;
vector = NULL;
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
void CMap::useCMap(CMapCache *cache, char *useName) {
@@ -251,6 +258,9 @@ CMap::~CMap() {
if (vector) {
freeCMapVector(vector);
}
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
}
void CMap::freeCMapVector(CMapVectorEntry *vec) {
@@ -265,11 +275,26 @@ void CMap::freeCMapVector(CMapVectorEntry *vec) {
}
void CMap::incRefCnt() {
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
++refCnt;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
}
void CMap::decRefCnt() {
- if (--refCnt == 0) {
+ GBool done;
+
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ done = --refCnt == 0;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+ if (done) {
delete this;
}
}
diff --git a/pdf2swf/xpdf/CMap.h b/pdf2swf/xpdf/CMap.h
index fe49acf7..eff2a819 100644
--- a/pdf2swf/xpdf/CMap.h
+++ b/pdf2swf/xpdf/CMap.h
@@ -2,20 +2,26 @@
//
// CMap.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef CMAP_H
#define CMAP_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
#include "CharTypes.h"
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
class GString;
struct CMapVectorEntry;
class CMapCache;
@@ -67,6 +73,9 @@ private:
CMapVectorEntry *vector; // vector for first byte (NULL for
// identity CMap)
int refCnt;
+#ifdef MULTITHREADED
+ GMutex mutex;
+#endif
};
//------------------------------------------------------------------------
diff --git a/pdf2swf/xpdf/Catalog.cc b/pdf2swf/xpdf/Catalog.cc
index 1212e2eb..c645fd00 100644
--- a/pdf2swf/xpdf/Catalog.cc
+++ b/pdf2swf/xpdf/Catalog.cc
@@ -2,15 +2,16 @@
//
// Catalog.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
@@ -26,7 +27,7 @@
// Catalog
//------------------------------------------------------------------------
-Catalog::Catalog(XRef *xrefA, GBool printCommands) {
+Catalog::Catalog(XRef *xrefA) {
Object catDict, pagesDict;
Object obj, obj2;
int numPages0;
@@ -55,12 +56,13 @@ Catalog::Catalog(XRef *xrefA, GBool printCommands) {
goto err2;
}
pagesDict.dictLookup("Count", &obj);
- if (!obj.isInt()) {
+ // some PDF files actually use real numbers here ("/Count 9.0")
+ if (!obj.isNum()) {
error(-1, "Page count in top-level pages object is wrong type (%s)",
obj.getTypeName());
goto err3;
}
- pagesSize = numPages0 = obj.getInt();
+ pagesSize = numPages0 = (int)obj.getNum();
obj.free();
pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
@@ -69,7 +71,7 @@ Catalog::Catalog(XRef *xrefA, GBool printCommands) {
pageRefs[i].num = -1;
pageRefs[i].gen = -1;
}
- numPages = readPageTree(pagesDict.getDict(), NULL, 0, printCommands);
+ numPages = readPageTree(pagesDict.getDict(), NULL, 0);
if (numPages != numPages0) {
error(-1, "Page count in top-level pages object is incorrect");
}
@@ -100,6 +102,9 @@ Catalog::Catalog(XRef *xrefA, GBool printCommands) {
// get the structure tree root
catDict.dictLookup("StructTreeRoot", &structTreeRoot);
+ // get the outline dictionary
+ catDict.dictLookup("Outlines", &outline);
+
catDict.free();
return;
@@ -133,6 +138,7 @@ Catalog::~Catalog() {
}
metadata.free();
structTreeRoot.free();
+ outline.free();
}
GString *Catalog::readMetadata() {
@@ -159,8 +165,7 @@ GString *Catalog::readMetadata() {
return s;
}
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
- GBool printCommands) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
Object kids;
Object kid;
Object kidRef;
@@ -179,7 +184,7 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
kids.arrayGet(i, &kid);
if (kid.isDict("Page")) {
attrs2 = new PageAttrs(attrs1, kid.getDict());
- page = new Page(xref, start+1, kid.getDict(), attrs2, printCommands);
+ page = new Page(xref, start+1, kid.getDict(), attrs2);
if (!page->isOk()) {
++start;
goto err3;
@@ -205,7 +210,7 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
// This should really be isDict("Pages"), but I've seen at least one
// PDF file where the /Type entry is missing.
} else if (kid.isDict()) {
- if ((start = readPageTree(kid.getDict(), attrs1, start, printCommands))
+ if ((start = readPageTree(kid.getDict(), attrs1, start))
< 0)
goto err2;
} else {
@@ -276,6 +281,10 @@ LinkDest *Catalog::findDest(GString *name) {
error(-1, "Bad named destination value");
}
obj1.free();
+ if (dest && !dest->isOk()) {
+ delete dest;
+ dest = NULL;
+ }
return dest;
}
@@ -299,8 +308,8 @@ Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
} else if (cmp < 0) {
done = gTrue;
}
- name1.free();
}
+ name1.free();
}
names.free();
if (!found)
diff --git a/pdf2swf/xpdf/Catalog.h b/pdf2swf/xpdf/Catalog.h
index afad803f..8ab7c61c 100644
--- a/pdf2swf/xpdf/Catalog.h
+++ b/pdf2swf/xpdf/Catalog.h
@@ -2,14 +2,16 @@
//
// Catalog.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef CATALOG_H
#define CATALOG_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -28,7 +30,7 @@ class Catalog {
public:
// Constructor.
- Catalog(XRef *xrefA, GBool printCommands = gFalse);
+ Catalog(XRef *xrefA);
// Destructor.
~Catalog();
@@ -63,6 +65,8 @@ public:
// NULL if <name> is not a destination.
LinkDest *findDest(GString *name);
+ Object *getOutline() { return &outline; }
+
private:
XRef *xref; // the xref table for this PDF file
@@ -75,10 +79,10 @@ private:
GString *baseURI; // base URI for URI-type links
Object metadata; // metadata stream
Object structTreeRoot; // structure tree root dictionary
+ Object outline; // outline dictionary
GBool ok; // true if catalog is valid
- int readPageTree(Dict *pages, PageAttrs *attrs, int start,
- GBool printCommands);
+ int readPageTree(Dict *pages, PageAttrs *attrs, int start);
Object *findDestInTree(Object *tree, GString *name, Object *obj);
};
diff --git a/pdf2swf/xpdf/CharCodeToUnicode.cc b/pdf2swf/xpdf/CharCodeToUnicode.cc
index 912981e9..2e2ad478 100644
--- a/pdf2swf/xpdf/CharCodeToUnicode.cc
+++ b/pdf2swf/xpdf/CharCodeToUnicode.cc
@@ -2,15 +2,16 @@
//
// CharCodeToUnicode.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <string.h>
#include "gmem.h"
@@ -53,7 +54,8 @@ static int getCharFromFile(void *data) {
//------------------------------------------------------------------------
-CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *collectionA) {
+CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
+ GString *collection) {
FILE *f;
Unicode *mapA;
CharCode size, mapLenA;
@@ -61,9 +63,9 @@ CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *collectionA) {
Unicode u;
CharCodeToUnicode *ctu;
- if (!(f = globalParams->getCIDToUnicodeFile(collectionA))) {
- error(-1, "Couldn't find cidToUnicode file for the '%s' collection",
- collectionA->getCString());
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ error(-1, "Couldn't open cidToUnicode file '%s'",
+ fileName->getCString());
return NULL;
}
@@ -79,21 +81,110 @@ CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *collectionA) {
if (sscanf(buf, "%x", &u) == 1) {
mapA[mapLenA] = u;
} else {
- error(-1, "Bad line (%d) in cidToUnicode file for the '%s' collection",
- (int)(mapLenA + 1), collectionA->getCString());
+ error(-1, "Bad line (%d) in cidToUnicode file '%s'",
+ (int)(mapLenA + 1), fileName->getCString());
mapA[mapLenA] = 0;
}
++mapLenA;
}
+ fclose(f);
- ctu = new CharCodeToUnicode(collectionA->copy(), mapA, mapLenA, gTrue,
- NULL, 0);
+ ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue,
+ NULL, 0, 0);
+ gfree(mapA);
+ return ctu;
+}
+
+CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
+ GString *fileName) {
+ FILE *f;
+ Unicode *mapA;
+ CharCodeToUnicodeString *sMapA;
+ CharCode size, oldSize, len, sMapSizeA, sMapLenA;
+ char buf[256];
+ char *tok;
+ Unicode u0;
+ Unicode uBuf[maxUnicodeString];
+ CharCodeToUnicode *ctu;
+ int line, n, i;
+
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ error(-1, "Couldn't open unicodeToUnicode file '%s'",
+ fileName->getCString());
+ return NULL;
+ }
+
+ size = 4096;
+ mapA = (Unicode *)gmalloc(size * sizeof(Unicode));
+ memset(mapA, 0, size * sizeof(Unicode));
+ len = 0;
+ sMapA = NULL;
+ sMapSizeA = sMapLenA = 0;
+
+ line = 0;
+ while (getLine(buf, sizeof(buf), f)) {
+ ++line;
+ if (!(tok = strtok(buf, " \t\r\n")) ||
+ sscanf(tok, "%x", &u0) != 1) {
+ error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
+ line, fileName->getCString());
+ continue;
+ }
+ n = 0;
+ while (n < maxUnicodeString) {
+ if (!(tok = strtok(NULL, " \t\r\n"))) {
+ break;
+ }
+ if (sscanf(tok, "%x", &uBuf[n]) != 1) {
+ error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
+ line, fileName->getCString());
+ break;
+ }
+ ++n;
+ }
+ if (n < 1) {
+ error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
+ line, fileName->getCString());
+ continue;
+ }
+ if (u0 >= size) {
+ oldSize = size;
+ while (u0 >= size) {
+ size *= 2;
+ }
+ mapA = (Unicode *)grealloc(mapA, size * sizeof(Unicode));
+ memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode));
+ }
+ if (n == 1) {
+ mapA[u0] = uBuf[0];
+ } else {
+ mapA[u0] = 0;
+ if (sMapLenA == sMapSizeA) {
+ sMapSizeA += 16;
+ sMapA = (CharCodeToUnicodeString *)
+ grealloc(sMapA, sMapSizeA * sizeof(CharCodeToUnicodeString));
+ }
+ sMapA[sMapLenA].c = u0;
+ for (i = 0; i < n; ++i) {
+ sMapA[sMapLenA].u[i] = uBuf[i];
+ }
+ sMapA[sMapLenA].len = n;
+ ++sMapLenA;
+ }
+ if (u0 >= len) {
+ len = u0 + 1;
+ }
+ }
+ fclose(f);
+
+ ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue,
+ sMapA, sMapLenA, sMapSizeA);
gfree(mapA);
return ctu;
}
CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) {
- return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0);
+ return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0);
}
CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) {
@@ -106,16 +197,20 @@ CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) {
return ctu;
}
+void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) {
+ char *p;
+
+ p = buf->getCString();
+ parseCMap1(&getCharFromString, &p, nBits);
+}
+
void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
int nBits) {
PSTokenizer *pst;
char tok1[256], tok2[256], tok3[256];
int nDigits, n1, n2, n3;
- CharCode oldLen, i;
+ CharCode i;
CharCode code1, code2;
- Unicode u;
- char uHex[5];
- int j;
GString *name;
FILE *f;
@@ -156,38 +251,7 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
continue;
}
- if (code1 >= mapLen) {
- oldLen = mapLen;
- mapLen = (code1 + 256) & ~255;
- map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
- for (i = oldLen; i < mapLen; ++i) {
- map[i] = 0;
- }
- }
- if (n2 == 6) {
- if (sscanf(tok2 + 1, "%x", &u) != 1) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
- continue;
- }
- map[code1] = u;
- } else {
- map[code1] = 0;
- if (sMapLen == sMapSize) {
- sMapSize += 8;
- sMap = (CharCodeToUnicodeString *)
- grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
- }
- sMap[sMapLen].c = code1;
- sMap[sMapLen].len = (n2 - 2) / 4;
- for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
- strncpy(uHex, tok2 + 1 + j*4, 4);
- uHex[4] = '\0';
- if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
- error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
- }
- }
- ++sMapLen;
- }
+ addMapping(code1, tok2 + 1, n2 - 1, 0);
}
pst->getToken(tok1, sizeof(tok1), &n1);
} else if (!strcmp(tok2, "beginbfrange")) {
@@ -203,53 +267,39 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
break;
}
if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
- n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>' &&
- tok3[0] == '<' && tok3[n3 - 1] == '>')) {
+ n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
- tok1[n1 - 1] = tok2[n2 - 1] = tok3[n3 - 1] = '\0';
+ tok1[n1 - 1] = tok2[n2 - 1] = '\0';
if (sscanf(tok1 + 1, "%x", &code1) != 1 ||
sscanf(tok2 + 1, "%x", &code2) != 1) {
error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
- if (code2 >= mapLen) {
- oldLen = mapLen;
- mapLen = (code2 + 256) & ~255;
- map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
- for (i = oldLen; i < mapLen; ++i) {
- map[i] = 0;
- }
- }
- if (n3 == 6) {
- if (sscanf(tok3 + 1, "%x", &u) != 1) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- continue;
- }
- for (; code1 <= code2; ++code1) {
- map[code1] = u++;
- }
- } else {
- if (sMapLen + (int)(code2 - code1 + 1) > sMapSize) {
- sMapSize = (sMapSize + (code2 - code1 + 1) + 7) & ~7;
- sMap = (CharCodeToUnicodeString *)
- grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
+ if (!strcmp(tok3, "[")) {
+ i = 0;
+ while (pst->getToken(tok1, sizeof(tok1), &n1) &&
+ code1 + i <= code2) {
+ if (!strcmp(tok1, "]")) {
+ break;
+ }
+ if (tok1[0] == '<' && tok1[n1 - 1] == '>') {
+ tok1[n1 - 1] = '\0';
+ addMapping(code1 + i, tok1 + 1, n1 - 2, 0);
+ } else {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ }
+ ++i;
}
+ } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') {
+ tok3[n3 - 1] = '\0';
for (i = 0; code1 <= code2; ++code1, ++i) {
- map[code1] = 0;
- sMap[sMapLen].c = code1;
- sMap[sMapLen].len = (n3 - 2) / 4;
- for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
- strncpy(uHex, tok3 + 1 + j*4, 4);
- uHex[4] = '\0';
- if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
- error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
- }
- }
- sMap[sMapLen].u[sMap[sMapLen].len - 1] += i;
- ++sMapLen;
+ addMapping(code1, tok3 + 1, n3 - 2, i);
}
+
+ } else {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
}
}
pst->getToken(tok1, sizeof(tok1), &n1);
@@ -260,10 +310,52 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
delete pst;
}
-CharCodeToUnicode::CharCodeToUnicode(GString *collectionA) {
+void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
+ int offset) {
+ CharCode oldLen, i;
+ Unicode u;
+ char uHex[5];
+ int j;
+
+ if (code >= mapLen) {
+ oldLen = mapLen;
+ mapLen = (code + 256) & ~255;
+ map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
+ for (i = oldLen; i < mapLen; ++i) {
+ map[i] = 0;
+ }
+ }
+ if (n <= 4) {
+ if (sscanf(uStr, "%x", &u) != 1) {
+ error(-1, "Illegal entry in ToUnicode CMap");
+ return;
+ }
+ map[code] = u + offset;
+ } else {
+ if (sMapLen >= sMapSize) {
+ sMapSize = sMapSize + 16;
+ sMap = (CharCodeToUnicodeString *)
+ grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
+ }
+ map[code] = 0;
+ sMap[sMapLen].c = code;
+ sMap[sMapLen].len = n / 4;
+ for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
+ strncpy(uHex, uStr + j*4, 4);
+ uHex[4] = '\0';
+ if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
+ error(-1, "Illegal entry in ToUnicode CMap");
+ }
+ }
+ sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset;
+ ++sMapLen;
+ }
+}
+
+CharCodeToUnicode::CharCodeToUnicode(GString *tagA) {
CharCode i;
- collection = collectionA;
+ tag = tagA;
mapLen = 256;
map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
for (i = 0; i < mapLen; ++i) {
@@ -272,13 +364,16 @@ CharCodeToUnicode::CharCodeToUnicode(GString *collectionA) {
sMap = NULL;
sMapLen = sMapSize = 0;
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
-CharCodeToUnicode::CharCodeToUnicode(GString *collectionA, Unicode *mapA,
+CharCodeToUnicode::CharCodeToUnicode(GString *tagA, Unicode *mapA,
CharCode mapLenA, GBool copyMap,
CharCodeToUnicodeString *sMapA,
- int sMapLenA) {
- collection = collectionA;
+ int sMapLenA, int sMapSizeA) {
+ tag = tagA;
mapLen = mapLenA;
if (copyMap) {
map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
@@ -287,32 +382,75 @@ CharCodeToUnicode::CharCodeToUnicode(GString *collectionA, Unicode *mapA,
map = mapA;
}
sMap = sMapA;
- sMapLen = sMapSize = sMapLenA;
+ sMapLen = sMapLenA;
+ sMapSize = sMapSizeA;
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
CharCodeToUnicode::~CharCodeToUnicode() {
- if (collection) {
- delete collection;
+ if (tag) {
+ delete tag;
}
gfree(map);
if (sMap) {
gfree(sMap);
}
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
}
void CharCodeToUnicode::incRefCnt() {
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
++refCnt;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
}
void CharCodeToUnicode::decRefCnt() {
- if (--refCnt == 0) {
+ GBool done;
+
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ done = --refCnt == 0;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+ if (done) {
delete this;
}
}
-GBool CharCodeToUnicode::match(GString *collectionA) {
- return collection && !collection->cmp(collectionA);
+GBool CharCodeToUnicode::match(GString *tagA) {
+ return tag && !tag->cmp(tagA);
+}
+
+void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) {
+ int i;
+
+ if (len == 1) {
+ map[c] = u[0];
+ } else {
+ map[c] = 0;
+ if (sMapLen == sMapSize) {
+ sMapSize += 8;
+ sMap = (CharCodeToUnicodeString *)
+ grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
+ }
+ sMap[sMapLen].c = c;
+ sMap[sMapLen].len = len;
+ for (i = 0; i < len && i < maxUnicodeString; ++i) {
+ sMap[sMapLen].u[i] = u[i];
+ }
+ ++sMapLen;
+ }
}
int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
@@ -338,34 +476,37 @@ int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
//------------------------------------------------------------------------
-CIDToUnicodeCache::CIDToUnicodeCache() {
+CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) {
int i;
- for (i = 0; i < cidToUnicodeCacheSize; ++i) {
+ size = sizeA;
+ cache = (CharCodeToUnicode **)gmalloc(size * sizeof(CharCodeToUnicode *));
+ for (i = 0; i < size; ++i) {
cache[i] = NULL;
}
}
-CIDToUnicodeCache::~CIDToUnicodeCache() {
+CharCodeToUnicodeCache::~CharCodeToUnicodeCache() {
int i;
- for (i = 0; i < cidToUnicodeCacheSize; ++i) {
+ for (i = 0; i < size; ++i) {
if (cache[i]) {
cache[i]->decRefCnt();
}
}
+ gfree(cache);
}
-CharCodeToUnicode *CIDToUnicodeCache::getCIDToUnicode(GString *collection) {
+CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GString *tag) {
CharCodeToUnicode *ctu;
int i, j;
- if (cache[0] && cache[0]->match(collection)) {
+ if (cache[0] && cache[0]->match(tag)) {
cache[0]->incRefCnt();
return cache[0];
}
- for (i = 1; i < cidToUnicodeCacheSize; ++i) {
- if (cache[i] && cache[i]->match(collection)) {
+ for (i = 1; i < size; ++i) {
+ if (cache[i] && cache[i]->match(tag)) {
ctu = cache[i];
for (j = i; j >= 1; --j) {
cache[j] = cache[j - 1];
@@ -375,16 +516,18 @@ CharCodeToUnicode *CIDToUnicodeCache::getCIDToUnicode(GString *collection) {
return ctu;
}
}
- if ((ctu = CharCodeToUnicode::parseCIDToUnicode(collection))) {
- if (cache[cidToUnicodeCacheSize - 1]) {
- cache[cidToUnicodeCacheSize - 1]->decRefCnt();
- }
- for (j = cidToUnicodeCacheSize - 1; j >= 1; --j) {
- cache[j] = cache[j - 1];
- }
- cache[0] = ctu;
- ctu->incRefCnt();
- return ctu;
- }
return NULL;
}
+
+void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) {
+ int i;
+
+ if (cache[size - 1]) {
+ cache[size - 1]->decRefCnt();
+ }
+ for (i = size - 1; i >= 1; --i) {
+ cache[i] = cache[i - 1];
+ }
+ cache[0] = ctu;
+ ctu->incRefCnt();
+}
diff --git a/pdf2swf/xpdf/CharCodeToUnicode.h b/pdf2swf/xpdf/CharCodeToUnicode.h
index 06916c8f..605e2bd1 100644
--- a/pdf2swf/xpdf/CharCodeToUnicode.h
+++ b/pdf2swf/xpdf/CharCodeToUnicode.h
@@ -4,19 +4,25 @@
//
// Mapping from character codes to Unicode.
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef CHARCODETOUNICODE_H
#define CHARCODETOUNICODE_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "CharTypes.h"
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
struct CharCodeToUnicodeString;
//------------------------------------------------------------------------
@@ -24,10 +30,16 @@ struct CharCodeToUnicodeString;
class CharCodeToUnicode {
public:
- // Create the CID-to-Unicode mapping specified by <collection>.
- // This reads a .cidToUnicode file from disk. Sets the initial
- // reference count to 1. Returns NULL on failure.
- static CharCodeToUnicode *parseCIDToUnicode(GString *collectionA);
+ // Read the CID-to-Unicode mapping for <collection> from the file
+ // specified by <fileName>. Sets the initial reference count to 1.
+ // Returns NULL on failure.
+ static CharCodeToUnicode *parseCIDToUnicode(GString *fileName,
+ GString *collection);
+
+ // Create a Unicode-to-Unicode mapping from the file specified by
+ // <fileName>. Sets the initial reference count to 1. Returns NULL
+ // on failure.
+ static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName);
// Create the CharCode-to-Unicode mapping for an 8-bit font.
// <toUnicode> is an array of 256 Unicode indexes. Sets the initial
@@ -37,13 +49,20 @@ public:
// Parse a ToUnicode CMap for an 8- or 16-bit font.
static CharCodeToUnicode *parseCMap(GString *buf, int nBits);
+ // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into
+ // <this>.
+ void mergeCMap(GString *buf, int nBits);
+
~CharCodeToUnicode();
void incRefCnt();
void decRefCnt();
- // Return true if this mapping matches the specified <collectionA>.
- GBool match(GString *collectionA);
+ // Return true if this mapping matches the specified <tagA>.
+ GBool match(GString *tagA);
+
+ // Set the mapping for <c>.
+ void setMapping(CharCode c, Unicode *u, int len);
// Map a CharCode to Unicode.
int mapToUnicode(CharCode c, Unicode *u, int size);
@@ -51,38 +70,44 @@ public:
private:
void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits);
- CharCodeToUnicode(GString *collectionA);
- CharCodeToUnicode(GString *collectionA, Unicode *mapA,
+ void addMapping(CharCode code, char *uStr, int n, int offset);
+ CharCodeToUnicode(GString *tagA);
+ CharCodeToUnicode(GString *tagA, Unicode *mapA,
CharCode mapLenA, GBool copyMap,
- CharCodeToUnicodeString *sMapA, int sMapLenA);
+ CharCodeToUnicodeString *sMapA,
+ int sMapLenA, int sMapSizeA);
- GString *collection;
+ GString *tag;
Unicode *map;
CharCode mapLen;
CharCodeToUnicodeString *sMap;
int sMapLen, sMapSize;
int refCnt;
+#ifdef MULTITHREADED
+ GMutex mutex;
+#endif
};
//------------------------------------------------------------------------
-#define cidToUnicodeCacheSize 4
-
-class CIDToUnicodeCache {
+class CharCodeToUnicodeCache {
public:
- CIDToUnicodeCache();
- ~CIDToUnicodeCache();
+ CharCodeToUnicodeCache(int sizeA);
+ ~CharCodeToUnicodeCache();
+
+ // Get the CharCodeToUnicode object for <tag>. Increments its
+ // reference count; there will be one reference for the cache plus
+ // one for the caller of this function. Returns NULL on failure.
+ CharCodeToUnicode *getCharCodeToUnicode(GString *tag);
- // Get the CharCodeToUnicode object for <collection>. Increments
- // its reference count; there will be one reference for the cache
- // plus one for the caller of this function. Returns NULL on
- // failure.
- CharCodeToUnicode *getCIDToUnicode(GString *collection);
+ // Insert <ctu> into the cache, in the most-recently-used position.
+ void add(CharCodeToUnicode *ctu);
private:
- CharCodeToUnicode *cache[cidToUnicodeCacheSize];
+ CharCodeToUnicode **cache;
+ int size;
};
#endif
diff --git a/pdf2swf/xpdf/CharTypes.h b/pdf2swf/xpdf/CharTypes.h
index bae2f267..d0df630d 100644
--- a/pdf2swf/xpdf/CharTypes.h
+++ b/pdf2swf/xpdf/CharTypes.h
@@ -2,7 +2,7 @@
//
// CharTypes.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
diff --git a/pdf2swf/xpdf/Decrypt.cc b/pdf2swf/xpdf/Decrypt.cc
index 8de40911..dab07509 100644
--- a/pdf2swf/xpdf/Decrypt.cc
+++ b/pdf2swf/xpdf/Decrypt.cc
@@ -2,15 +2,16 @@
//
// Decrypt.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include "gmem.h"
#include "Decrypt.h"
@@ -65,13 +66,15 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
int permissions, GString *fileID,
GString *ownerPassword, GString *userPassword,
Guchar *fileKey, GBool *ownerPasswordOk) {
- Guchar test[32];
+ Guchar test[32], test2[32];
GString *userPassword2;
Guchar fState[256];
+ Guchar tmpKey[16];
Guchar fx, fy;
- int len, i;
+ int len, i, j;
// try using the supplied owner password to generate the user password
+ *ownerPasswordOk = gFalse;
if (ownerPassword) {
len = ownerPassword->getLength();
if (len < 32) {
@@ -80,29 +83,40 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
} else {
memcpy(test, ownerPassword->getCString(), 32);
}
- } else {
- memcpy(test, passwordPad, 32);
- }
- md5(test, 32, test);
- if (encRevision == 3) {
- for (i = 0; i < 50; ++i) {
- md5(test, 16, test);
+ md5(test, 32, test);
+ if (encRevision == 3) {
+ for (i = 0; i < 50; ++i) {
+ md5(test, 16, test);
+ }
+ }
+ if (encRevision == 2) {
+ rc4InitKey(test, keyLength, fState);
+ fx = fy = 0;
+ for (i = 0; i < 32; ++i) {
+ test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
+ }
+ } else {
+ memcpy(test2, ownerKey->getCString(), 32);
+ for (i = 19; i >= 0; --i) {
+ for (j = 0; j < keyLength; ++j) {
+ tmpKey[j] = test[j] ^ i;
+ }
+ rc4InitKey(tmpKey, keyLength, fState);
+ fx = fy = 0;
+ for (j = 0; j < 32; ++j) {
+ test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
+ }
+ }
+ }
+ userPassword2 = new GString((char *)test2, 32);
+ if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+ permissions, fileID, userPassword2, fileKey)) {
+ *ownerPasswordOk = gTrue;
+ delete userPassword2;
+ return gTrue;
}
- }
- rc4InitKey(test, keyLength, fState);
- fx = fy = 0;
- for (i = 0; i < 32; ++i) {
- test[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
- }
- userPassword2 = new GString((char *)test, 32);
- if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
- permissions, fileID, userPassword2, fileKey)) {
- *ownerPasswordOk = gTrue;
delete userPassword2;
- return gTrue;
}
- *ownerPasswordOk = gFalse;
- delete userPassword2;
// try using the supplied user password
return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
@@ -143,7 +157,7 @@ GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
md5(buf, 68 + fileID->getLength(), fileKey);
if (encRevision == 3) {
for (i = 0; i < 50; ++i) {
- md5(fileKey, 16, fileKey);
+ md5(fileKey, keyLength, fileKey);
}
}
@@ -366,20 +380,20 @@ static void md5(Guchar *msg, int msgLen, Guchar *digest) {
}
// break digest into bytes
- digest[0] = a & 0xff;
- digest[1] = (a >>= 8) & 0xff;
- digest[2] = (a >>= 8) & 0xff;
- digest[3] = (a >>= 8) & 0xff;
- digest[4] = b & 0xff;
- digest[5] = (b >>= 8) & 0xff;
- digest[6] = (b >>= 8) & 0xff;
- digest[7] = (b >>= 8) & 0xff;
- digest[8] = c & 0xff;
- digest[9] = (c >>= 8) & 0xff;
- digest[10] = (c >>= 8) & 0xff;
- digest[11] = (c >>= 8) & 0xff;
- digest[12] = d & 0xff;
- digest[13] = (d >>= 8) & 0xff;
- digest[14] = (d >>= 8) & 0xff;
- digest[15] = (d >>= 8) & 0xff;
+ digest[0] = (Guchar)(a & 0xff);
+ digest[1] = (Guchar)((a >>= 8) & 0xff);
+ digest[2] = (Guchar)((a >>= 8) & 0xff);
+ digest[3] = (Guchar)((a >>= 8) & 0xff);
+ digest[4] = (Guchar)(b & 0xff);
+ digest[5] = (Guchar)((b >>= 8) & 0xff);
+ digest[6] = (Guchar)((b >>= 8) & 0xff);
+ digest[7] = (Guchar)((b >>= 8) & 0xff);
+ digest[8] = (Guchar)(c & 0xff);
+ digest[9] = (Guchar)((c >>= 8) & 0xff);
+ digest[10] = (Guchar)((c >>= 8) & 0xff);
+ digest[11] = (Guchar)((c >>= 8) & 0xff);
+ digest[12] = (Guchar)(d & 0xff);
+ digest[13] = (Guchar)((d >>= 8) & 0xff);
+ digest[14] = (Guchar)((d >>= 8) & 0xff);
+ digest[15] = (Guchar)((d >>= 8) & 0xff);
}
diff --git a/pdf2swf/xpdf/Decrypt.h b/pdf2swf/xpdf/Decrypt.h
index 52afb2f6..71f94574 100644
--- a/pdf2swf/xpdf/Decrypt.h
+++ b/pdf2swf/xpdf/Decrypt.h
@@ -2,14 +2,16 @@
//
// Decrypt.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef DECRYPT_H
#define DECRYPT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Dict.cc b/pdf2swf/xpdf/Dict.cc
index 5eb077e0..62745907 100644
--- a/pdf2swf/xpdf/Dict.cc
+++ b/pdf2swf/xpdf/Dict.cc
@@ -2,15 +2,16 @@
//
// Dict.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
@@ -40,8 +41,12 @@ Dict::~Dict() {
}
void Dict::add(char *key, Object *val) {
- if (length + 1 > size) {
- size += 8;
+ if (length == size) {
+ if (length == 0) {
+ size = 8;
+ } else {
+ size *= 2;
+ }
entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
}
entries[length].key = key;
diff --git a/pdf2swf/xpdf/Dict.h b/pdf2swf/xpdf/Dict.h
index b9945144..08f55ecd 100644
--- a/pdf2swf/xpdf/Dict.h
+++ b/pdf2swf/xpdf/Dict.h
@@ -2,14 +2,16 @@
//
// Dict.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef DICT_H
#define DICT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Error.cc b/pdf2swf/xpdf/Error.cc
index 3eae5c9c..c03f75f4 100644
--- a/pdf2swf/xpdf/Error.cc
+++ b/pdf2swf/xpdf/Error.cc
@@ -2,15 +2,16 @@
//
// Error.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
diff --git a/pdf2swf/xpdf/Error.h b/pdf2swf/xpdf/Error.h
index 77801c59..0ce55e9a 100644
--- a/pdf2swf/xpdf/Error.h
+++ b/pdf2swf/xpdf/Error.h
@@ -2,14 +2,16 @@
//
// Error.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef ERROR_H
#define ERROR_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/ErrorCodes.h b/pdf2swf/xpdf/ErrorCodes.h
index 4e0d38a6..b28528df 100644
--- a/pdf2swf/xpdf/ErrorCodes.h
+++ b/pdf2swf/xpdf/ErrorCodes.h
@@ -2,7 +2,7 @@
//
// ErrorCodes.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
@@ -21,4 +21,16 @@
#define errEncrypted 4 // file was encrypted and password was
// incorrect or not supplied
+#define errHighlightFile 5 // nonexistent or invalid highlight file
+
+#define errBadPrinter 6 // invalid printer
+
+#define errPrinting 7 // error during printing
+
+#define errPermission 8 // PDF file doesn't allow that operation
+
+#define errBadPageNum 9 // invalid page number
+
+#define errFileIO 10 // file I/O error
+
#endif
diff --git a/pdf2swf/xpdf/FoFiBase.cc b/pdf2swf/xpdf/FoFiBase.cc
new file mode 100644
index 00000000..28d0b8ca
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiBase.cc
@@ -0,0 +1,156 @@
+//========================================================================
+//
+// FoFiBase.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include "gmem.h"
+#include "FoFiBase.h"
+
+//------------------------------------------------------------------------
+// FoFiBase
+//------------------------------------------------------------------------
+
+FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) {
+ fileData = file = (Guchar *)fileA;
+ len = lenA;
+ freeFileData = freeFileDataA;
+}
+
+FoFiBase::~FoFiBase() {
+ if (freeFileData) {
+ gfree(fileData);
+ }
+}
+
+char *FoFiBase::readFile(char *fileName, int *fileLen) {
+ FILE *f;
+ char *buf;
+ int n;
+
+ if (!(f = fopen(fileName, "rb"))) {
+ return NULL;
+ }
+ fseek(f, 0, SEEK_END);
+ n = (int)ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = (char *)gmalloc(n);
+ if ((int)fread(buf, 1, n, f) != n) {
+ gfree(buf);
+ fclose(f);
+ return NULL;
+ }
+ fclose(f);
+ *fileLen = n;
+ return buf;
+}
+
+int FoFiBase::getS8(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ if (x & 0x80) {
+ x |= ~0xff;
+ }
+ return x;
+}
+
+int FoFiBase::getU8(int pos, GBool *ok) {
+ if (pos < 0 || pos >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ return file[pos];
+}
+
+int FoFiBase::getS16BE(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos+1 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ if (x & 0x8000) {
+ x |= ~0xffff;
+ }
+ return x;
+}
+
+int FoFiBase::getU16BE(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos+1 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ return x;
+}
+
+int FoFiBase::getS32BE(int pos, GBool *ok) {
+ int x;
+
+ if (pos < 0 || pos+3 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ x = (x << 8) + file[pos+2];
+ x = (x << 8) + file[pos+3];
+ if (x & 0x80000000) {
+ x |= ~0xffffffff;
+ }
+ return x;
+}
+
+Guint FoFiBase::getU32BE(int pos, GBool *ok) {
+ Guint x;
+
+ if (pos < 0 || pos+3 >= len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = file[pos];
+ x = (x << 8) + file[pos+1];
+ x = (x << 8) + file[pos+2];
+ x = (x << 8) + file[pos+3];
+ return x;
+}
+
+Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) {
+ Guint x;
+ int i;
+
+ if (pos < 0 || pos + size > len) {
+ *ok = gFalse;
+ return 0;
+ }
+ x = 0;
+ for (i = 0; i < size; ++i) {
+ x = (x << 8) + file[pos + i];
+ }
+ return x;
+}
+
+GBool FoFiBase::checkRegion(int pos, int size) {
+ return pos >= 0 &&
+ pos + size >= pos &&
+ pos + size <= len;
+}
diff --git a/pdf2swf/xpdf/FoFiBase.h b/pdf2swf/xpdf/FoFiBase.h
new file mode 100644
index 00000000..b78840b2
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiBase.h
@@ -0,0 +1,57 @@
+//========================================================================
+//
+// FoFiBase.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFIBASE_H
+#define FOFIBASE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+
+typedef void (*FoFiOutputFunc)(void *stream, char *data, int len);
+
+//------------------------------------------------------------------------
+// FoFiBase
+//------------------------------------------------------------------------
+
+class FoFiBase {
+public:
+
+ virtual ~FoFiBase();
+
+protected:
+
+ FoFiBase(char *fileA, int lenA, GBool freeFileDataA);
+ static char *readFile(char *fileName, int *fileLen);
+
+ // S = signed / U = unsigned
+ // 8/16/32/Var = word length, in bytes
+ // BE = big endian
+ int getS8(int pos, GBool *ok);
+ int getU8(int pos, GBool *ok);
+ int getS16BE(int pos, GBool *ok);
+ int getU16BE(int pos, GBool *ok);
+ int getS32BE(int pos, GBool *ok);
+ Guint getU32BE(int pos, GBool *ok);
+ Guint getUVarBE(int pos, int size, GBool *ok);
+
+ GBool checkRegion(int pos, int size);
+
+ Guchar *fileData;
+ Guchar *file;
+ int len;
+ GBool freeFileData;
+};
+
+#endif
diff --git a/pdf2swf/xpdf/FoFiEncodings.cc b/pdf2swf/xpdf/FoFiEncodings.cc
new file mode 100644
index 00000000..37a17f5d
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiEncodings.cc
@@ -0,0 +1,994 @@
+//========================================================================
+//
+// FoFiEncodings.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include "FoFiEncodings.h"
+
+//------------------------------------------------------------------------
+// Type 1 and 1C font data
+//------------------------------------------------------------------------
+
+char *fofiType1StandardEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdown",
+ "cent",
+ "sterling",
+ "fraction",
+ "yen",
+ "florin",
+ "section",
+ "currency",
+ "quotesingle",
+ "quotedblleft",
+ "guillemotleft",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ NULL,
+ "endash",
+ "dagger",
+ "daggerdbl",
+ "periodcentered",
+ NULL,
+ "paragraph",
+ "bullet",
+ "quotesinglbase",
+ "quotedblbase",
+ "quotedblright",
+ "guillemotright",
+ "ellipsis",
+ "perthousand",
+ NULL,
+ "questiondown",
+ NULL,
+ "grave",
+ "acute",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "dieresis",
+ NULL,
+ "ring",
+ "cedilla",
+ NULL,
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "emdash",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "AE",
+ NULL,
+ "ordfeminine",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Lslash",
+ "Oslash",
+ "OE",
+ "ordmasculine",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ae",
+ NULL,
+ NULL,
+ NULL,
+ "dotlessi",
+ NULL,
+ NULL,
+ "lslash",
+ "oslash",
+ "oe",
+ "germandbls",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+char *fofiType1ExpertEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ NULL,
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "comma",
+ "hyphen",
+ "period",
+ "fraction",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "colon",
+ "semicolon",
+ "commasuperior",
+ "threequartersemdash",
+ "periodsuperior",
+ "questionsmall",
+ NULL,
+ "asuperior",
+ "bsuperior",
+ "centsuperior",
+ "dsuperior",
+ "esuperior",
+ NULL,
+ NULL,
+ NULL,
+ "isuperior",
+ NULL,
+ NULL,
+ "lsuperior",
+ "msuperior",
+ "nsuperior",
+ "osuperior",
+ NULL,
+ NULL,
+ "rsuperior",
+ "ssuperior",
+ "tsuperior",
+ NULL,
+ "ff",
+ "fi",
+ "fl",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ NULL,
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hyphensuperior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdownsmall",
+ "centoldstyle",
+ "Lslashsmall",
+ NULL,
+ NULL,
+ "Scaronsmall",
+ "Zcaronsmall",
+ "Dieresissmall",
+ "Brevesmall",
+ "Caronsmall",
+ NULL,
+ "Dotaccentsmall",
+ NULL,
+ NULL,
+ "Macronsmall",
+ NULL,
+ NULL,
+ "figuredash",
+ "hypheninferior",
+ NULL,
+ NULL,
+ "Ogoneksmall",
+ "Ringsmall",
+ "Cedillasmall",
+ NULL,
+ NULL,
+ NULL,
+ "onequarter",
+ "onehalf",
+ "threequarters",
+ "questiondownsmall",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ NULL,
+ NULL,
+ "zerosuperior",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "eightsuperior",
+ "ninesuperior",
+ "zeroinferior",
+ "oneinferior",
+ "twoinferior",
+ "threeinferior",
+ "fourinferior",
+ "fiveinferior",
+ "sixinferior",
+ "seveninferior",
+ "eightinferior",
+ "nineinferior",
+ "centinferior",
+ "dollarinferior",
+ "periodinferior",
+ "commainferior",
+ "Agravesmall",
+ "Aacutesmall",
+ "Acircumflexsmall",
+ "Atildesmall",
+ "Adieresissmall",
+ "Aringsmall",
+ "AEsmall",
+ "Ccedillasmall",
+ "Egravesmall",
+ "Eacutesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Igravesmall",
+ "Iacutesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ethsmall",
+ "Ntildesmall",
+ "Ogravesmall",
+ "Oacutesmall",
+ "Ocircumflexsmall",
+ "Otildesmall",
+ "Odieresissmall",
+ "OEsmall",
+ "Oslashsmall",
+ "Ugravesmall",
+ "Uacutesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ "Yacutesmall",
+ "Thornsmall",
+ "Ydieresissmall"
+};
+
+//------------------------------------------------------------------------
+// Type 1C font data
+//------------------------------------------------------------------------
+
+char *fofiType1CStdStrings[391] = {
+ ".notdef",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "exclamdown",
+ "cent",
+ "sterling",
+ "fraction",
+ "yen",
+ "florin",
+ "section",
+ "currency",
+ "quotesingle",
+ "quotedblleft",
+ "guillemotleft",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "endash",
+ "dagger",
+ "daggerdbl",
+ "periodcentered",
+ "paragraph",
+ "bullet",
+ "quotesinglbase",
+ "quotedblbase",
+ "quotedblright",
+ "guillemotright",
+ "ellipsis",
+ "perthousand",
+ "questiondown",
+ "grave",
+ "acute",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "dieresis",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "emdash",
+ "AE",
+ "ordfeminine",
+ "Lslash",
+ "Oslash",
+ "OE",
+ "ordmasculine",
+ "ae",
+ "dotlessi",
+ "lslash",
+ "oslash",
+ "oe",
+ "germandbls",
+ "onesuperior",
+ "logicalnot",
+ "mu",
+ "trademark",
+ "Eth",
+ "onehalf",
+ "plusminus",
+ "Thorn",
+ "onequarter",
+ "divide",
+ "brokenbar",
+ "degree",
+ "thorn",
+ "threequarters",
+ "twosuperior",
+ "registered",
+ "minus",
+ "eth",
+ "multiply",
+ "threesuperior",
+ "copyright",
+ "Aacute",
+ "Acircumflex",
+ "Adieresis",
+ "Agrave",
+ "Aring",
+ "Atilde",
+ "Ccedilla",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Ntilde",
+ "Oacute",
+ "Ocircumflex",
+ "Odieresis",
+ "Ograve",
+ "Otilde",
+ "Scaron",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Ugrave",
+ "Yacute",
+ "Ydieresis",
+ "Zcaron",
+ "aacute",
+ "acircumflex",
+ "adieresis",
+ "agrave",
+ "aring",
+ "atilde",
+ "ccedilla",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "egrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "igrave",
+ "ntilde",
+ "oacute",
+ "ocircumflex",
+ "odieresis",
+ "ograve",
+ "otilde",
+ "scaron",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "ugrave",
+ "yacute",
+ "ydieresis",
+ "zcaron",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "commasuperior",
+ "threequartersemdash",
+ "periodsuperior",
+ "questionsmall",
+ "asuperior",
+ "bsuperior",
+ "centsuperior",
+ "dsuperior",
+ "esuperior",
+ "isuperior",
+ "lsuperior",
+ "msuperior",
+ "nsuperior",
+ "osuperior",
+ "rsuperior",
+ "ssuperior",
+ "tsuperior",
+ "ff",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hyphensuperior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ "exclamdownsmall",
+ "centoldstyle",
+ "Lslashsmall",
+ "Scaronsmall",
+ "Zcaronsmall",
+ "Dieresissmall",
+ "Brevesmall",
+ "Caronsmall",
+ "Dotaccentsmall",
+ "Macronsmall",
+ "figuredash",
+ "hypheninferior",
+ "Ogoneksmall",
+ "Ringsmall",
+ "Cedillasmall",
+ "questiondownsmall",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ "zerosuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "eightsuperior",
+ "ninesuperior",
+ "zeroinferior",
+ "oneinferior",
+ "twoinferior",
+ "threeinferior",
+ "fourinferior",
+ "fiveinferior",
+ "sixinferior",
+ "seveninferior",
+ "eightinferior",
+ "nineinferior",
+ "centinferior",
+ "dollarinferior",
+ "periodinferior",
+ "commainferior",
+ "Agravesmall",
+ "Aacutesmall",
+ "Acircumflexsmall",
+ "Atildesmall",
+ "Adieresissmall",
+ "Aringsmall",
+ "AEsmall",
+ "Ccedillasmall",
+ "Egravesmall",
+ "Eacutesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Igravesmall",
+ "Iacutesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ethsmall",
+ "Ntildesmall",
+ "Ogravesmall",
+ "Oacutesmall",
+ "Ocircumflexsmall",
+ "Otildesmall",
+ "Odieresissmall",
+ "OEsmall",
+ "Oslashsmall",
+ "Ugravesmall",
+ "Uacutesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ "Yacutesmall",
+ "Thornsmall",
+ "Ydieresissmall",
+ "001.000",
+ "001.001",
+ "001.002",
+ "001.003",
+ "Black",
+ "Bold",
+ "Book",
+ "Light",
+ "Medium",
+ "Regular",
+ "Roman",
+ "Semibold"
+};
+
+Gushort fofiType1CISOAdobeCharset[229] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228
+};
+
+Gushort fofiType1CExpertCharset[166] = {
+ 0, 1, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
+ 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
+ 261, 262, 263, 264, 265, 266, 109, 110, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+ 158, 155, 163, 319, 320, 321, 322, 323, 324, 325,
+ 326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+ 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+ 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
+ 373, 374, 375, 376, 377, 378
+};
+
+Gushort fofiType1CExpertSubsetCharset[87] = {
+ 0, 1, 231, 232, 235, 236, 237, 238, 13, 14,
+ 15, 99, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 27, 28, 249, 250, 251, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 109, 110, 267, 268, 269, 270, 272, 300, 301,
+ 302, 305, 314, 315, 158, 155, 163, 320, 321, 322,
+ 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
+ 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
+ 340, 341, 342, 343, 344, 345, 346
+};
diff --git a/pdf2swf/xpdf/FoFiEncodings.h b/pdf2swf/xpdf/FoFiEncodings.h
new file mode 100644
index 00000000..50e285d7
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiEncodings.h
@@ -0,0 +1,36 @@
+//========================================================================
+//
+// FoFiEncodings.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFIENCODINGS_H
+#define FOFIENCODINGS_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// Type 1 and 1C font data
+//------------------------------------------------------------------------
+
+extern char *fofiType1StandardEncoding[256];
+extern char *fofiType1ExpertEncoding[256];
+
+//------------------------------------------------------------------------
+// Type 1C font data
+//------------------------------------------------------------------------
+
+extern char *fofiType1CStdStrings[391];
+extern Gushort fofiType1CISOAdobeCharset[229];
+extern Gushort fofiType1CExpertCharset[166];
+extern Gushort fofiType1CExpertSubsetCharset[87];
+
+#endif
diff --git a/pdf2swf/xpdf/FoFiTrueType.cc b/pdf2swf/xpdf/FoFiTrueType.cc
new file mode 100644
index 00000000..a4cf43cb
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiTrueType.cc
@@ -0,0 +1,1438 @@
+//========================================================================
+//
+// FoFiTrueType.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include "gtypes.h"
+#include "gmem.h"
+#include "GString.h"
+#include "GHash.h"
+#include "FoFiTrueType.h"
+
+//
+// Terminology
+// -----------
+//
+// character code = number used as an element of a text string
+//
+// character name = glyph name = name for a particular glyph within a
+// font
+//
+// glyph index = GID = position (within some internal table in the font)
+// where the instructions to draw a particular glyph are
+// stored
+//
+// Type 1 fonts
+// ------------
+//
+// Type 1 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+// Encoding[charCode] = charName
+//
+// CharStrings: dictionary of instructions, keyed by character names,
+// maps character name to glyph data
+//
+// CharStrings[charName] = glyphData
+//
+// TrueType fonts
+// --------------
+//
+// TrueType fonts contain:
+//
+// 'cmap' table: mapping from character code to glyph index; there may
+// be multiple cmaps in a TrueType font
+//
+// cmap[charCode] = gid
+//
+// 'post' table: mapping from glyph index to glyph name
+//
+// post[gid] = glyphName
+//
+// Type 42 fonts
+// -------------
+//
+// Type 42 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+// Encoding[charCode] = charName
+//
+// CharStrings: dictionary of glyph indexes, keyed by character names,
+// maps character name to glyph index
+//
+// CharStrings[charName] = gid
+//
+
+//------------------------------------------------------------------------
+
+struct TrueTypeTable {
+ Guint tag;
+ Guint checksum;
+ int offset;
+ int origOffset;
+ int len;
+};
+
+struct TrueTypeCmap {
+ int platform;
+ int encoding;
+ int offset;
+ int len;
+ int fmt;
+};
+
+struct TrueTypeLoca {
+ int idx;
+ int origOffset;
+ int newOffset;
+ int len;
+};
+
+#define cmapTag 0x636d6170
+#define glyfTag 0x676c7966
+#define locaTag 0x6c6f6361
+#define nameTag 0x6e616d65
+#define postTag 0x706f7374
+
+static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
+ TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
+ TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
+
+ if (loca1->origOffset == loca2->origOffset) {
+ return loca1->idx - loca2->idx;
+ }
+ return loca1->origOffset - loca2->origOffset;
+}
+
+static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
+ TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
+ TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
+
+ return loca1->idx - loca2->idx;
+}
+
+static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
+ TrueTypeTable *tab1 = (TrueTypeTable *)p1;
+ TrueTypeTable *tab2 = (TrueTypeTable *)p2;
+
+ return (int)tab1->tag - (int)tab2->tag;
+}
+
+//------------------------------------------------------------------------
+
+struct T42Table {
+ char *tag; // 4-byte tag
+ GBool required; // required by the TrueType spec?
+};
+
+// TrueType tables to be embedded in Type 42 fonts.
+// NB: the table names must be in alphabetical order here.
+#define nT42Tables 11
+static T42Table t42Tables[nT42Tables] = {
+ { "cvt ", gTrue },
+ { "fpgm", gTrue },
+ { "glyf", gTrue },
+ { "head", gTrue },
+ { "hhea", gTrue },
+ { "hmtx", gTrue },
+ { "loca", gTrue },
+ { "maxp", gTrue },
+ { "prep", gTrue },
+ { "vhea", gFalse },
+ { "vmtx", gFalse }
+};
+#define t42HeadTable 3
+#define t42LocaTable 6
+#define t42GlyfTable 2
+
+//------------------------------------------------------------------------
+
+// Glyph names in some arbitrary standard order that Apple uses for
+// their TrueType fonts.
+static char *macGlyphNames[258] = {
+ ".notdef", "null", "CR", "space",
+ "exclam", "quotedbl", "numbersign", "dollar",
+ "percent", "ampersand", "quotesingle", "parenleft",
+ "parenright", "asterisk", "plus", "comma",
+ "hyphen", "period", "slash", "zero",
+ "one", "two", "three", "four",
+ "five", "six", "seven", "eight",
+ "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at",
+ "A", "B", "C", "D",
+ "E", "F", "G", "H",
+ "I", "J", "K", "L",
+ "M", "N", "O", "P",
+ "Q", "R", "S", "T",
+ "U", "V", "W", "X",
+ "Y", "Z", "bracketleft", "backslash",
+ "bracketright", "asciicircum", "underscore", "grave",
+ "a", "b", "c", "d",
+ "e", "f", "g", "h",
+ "i", "j", "k", "l",
+ "m", "n", "o", "p",
+ "q", "r", "s", "t",
+ "u", "v", "w", "x",
+ "y", "z", "braceleft", "bar",
+ "braceright", "asciitilde", "Adieresis", "Aring",
+ "Ccedilla", "Eacute", "Ntilde", "Odieresis",
+ "Udieresis", "aacute", "agrave", "acircumflex",
+ "adieresis", "atilde", "aring", "ccedilla",
+ "eacute", "egrave", "ecircumflex", "edieresis",
+ "iacute", "igrave", "icircumflex", "idieresis",
+ "ntilde", "oacute", "ograve", "ocircumflex",
+ "odieresis", "otilde", "uacute", "ugrave",
+ "ucircumflex", "udieresis", "dagger", "degree",
+ "cent", "sterling", "section", "bullet",
+ "paragraph", "germandbls", "registered", "copyright",
+ "trademark", "acute", "dieresis", "notequal",
+ "AE", "Oslash", "infinity", "plusminus",
+ "lessequal", "greaterequal", "yen", "mu1",
+ "partialdiff", "summation", "product", "pi",
+ "integral", "ordfeminine", "ordmasculine", "Ohm",
+ "ae", "oslash", "questiondown", "exclamdown",
+ "logicalnot", "radical", "florin", "approxequal",
+ "increment", "guillemotleft", "guillemotright", "ellipsis",
+ "nbspace", "Agrave", "Atilde", "Otilde",
+ "OE", "oe", "endash", "emdash",
+ "quotedblleft", "quotedblright", "quoteleft", "quoteright",
+ "divide", "lozenge", "ydieresis", "Ydieresis",
+ "fraction", "currency", "guilsinglleft", "guilsinglright",
+ "fi", "fl", "daggerdbl", "periodcentered",
+ "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
+ "Ecircumflex", "Aacute", "Edieresis", "Egrave",
+ "Iacute", "Icircumflex", "Idieresis", "Igrave",
+ "Oacute", "Ocircumflex", "applelogo", "Ograve",
+ "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
+ "circumflex", "tilde", "overscore", "breve",
+ "dotaccent", "ring", "cedilla", "hungarumlaut",
+ "ogonek", "caron", "Lslash", "lslash",
+ "Scaron", "scaron", "Zcaron", "zcaron",
+ "brokenbar", "Eth", "eth", "Yacute",
+ "yacute", "Thorn", "thorn", "minus",
+ "multiply", "onesuperior", "twosuperior", "threesuperior",
+ "onehalf", "onequarter", "threequarters", "franc",
+ "Gbreve", "gbreve", "Idot", "Scedilla",
+ "scedilla", "Cacute", "cacute", "Ccaron",
+ "ccaron", "dmacron"
+};
+
+//------------------------------------------------------------------------
+// FoFiTrueType
+//------------------------------------------------------------------------
+
+FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) {
+ FoFiTrueType *ff;
+
+ ff = new FoFiTrueType(fileA, lenA, gFalse);
+ if (!ff->parsedOk) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiTrueType *FoFiTrueType::load(char *fileName) {
+ FoFiTrueType *ff;
+ char *fileA;
+ int lenA;
+
+ if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
+ return NULL;
+ }
+ ff = new FoFiTrueType(fileA, lenA, gTrue);
+ if (!ff->parsedOk) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA):
+ FoFiBase(fileA, lenA, freeFileDataA)
+{
+ tables = NULL;
+ nTables = 0;
+ cmaps = NULL;
+ nCmaps = 0;
+ nameToGID = NULL;
+ parsedOk = gFalse;
+
+ parse();
+}
+
+FoFiTrueType::~FoFiTrueType() {
+ gfree(tables);
+ gfree(cmaps);
+ delete nameToGID;
+}
+
+int FoFiTrueType::getNumCmaps() {
+ return nCmaps;
+}
+
+int FoFiTrueType::getCmapPlatform(int i) {
+ return cmaps[i].platform;
+}
+
+int FoFiTrueType::getCmapEncoding(int i) {
+ return cmaps[i].encoding;
+}
+
+int FoFiTrueType::findCmap(int platform, int encoding) {
+ int i;
+
+ for (i = 0; i < nCmaps; ++i) {
+ if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
+ Gushort gid;
+ int segCnt, segEnd, segStart, segDelta, segOffset;
+ int cmapFirst, cmapLen;
+ int pos, a, b, m;
+ GBool ok;
+
+ if (i < 0 || i >= nCmaps) {
+ return 0;
+ }
+ ok = gTrue;
+ pos = cmaps[i].offset;
+ switch (cmaps[i].fmt) {
+ case 0:
+ if (c < 0 || c >= cmaps[i].len - 6) {
+ return 0;
+ }
+ gid = getU8(cmaps[i].offset + 6 + c, &ok);
+ break;
+ case 4:
+ segCnt = getU16BE(pos + 6, &ok) / 2;
+ a = -1;
+ b = segCnt - 1;
+ segEnd = getU16BE(pos + 14 + 2*b, &ok);
+ if (c > segEnd) {
+ // malformed font -- the TrueType spec requires the last segEnd
+ // to be 0xffff
+ return 0;
+ }
+ // invariant: seg[a].end < code <= seg[b].end
+ while (b - a > 1 && ok) {
+ m = (a + b) / 2;
+ segEnd = getU16BE(pos + 14 + 2*m, &ok);
+ if (segEnd < c) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
+ segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
+ segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
+ if (c < segStart) {
+ return 0;
+ }
+ if (segOffset == 0) {
+ gid = (c + segDelta) & 0xffff;
+ } else {
+ gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
+ segOffset + 2 * (c - segStart), &ok);
+ if (gid != 0) {
+ gid = (gid + segDelta) & 0xffff;
+ }
+ }
+ break;
+ case 6:
+ cmapFirst = getU16BE(pos + 6, &ok);
+ cmapLen = getU16BE(pos + 8, &ok);
+ if (c < cmapFirst || c >= cmapFirst + cmapLen) {
+ return 0;
+ }
+ gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
+ break;
+ default:
+ return 0;
+ }
+ if (!ok) {
+ return 0;
+ }
+ return gid;
+}
+
+int FoFiTrueType::mapNameToGID(char *name) {
+ if (!nameToGID) {
+ return 0;
+ }
+ return nameToGID->lookupInt(name);
+}
+
+int FoFiTrueType::getEmbeddingRights() {
+ int i, fsType;
+ GBool ok;
+
+ if ((i = seekTable("OS/2")) < 0) {
+ return 4;
+ }
+ ok = gTrue;
+ fsType = getU16BE(tables[i].offset + 8, &ok);
+ if (!ok) {
+ return 4;
+ }
+ if (fsType & 0x0008) {
+ return 2;
+ }
+ if (fsType & 0x0004) {
+ return 1;
+ }
+ if (fsType & 0x0002) {
+ return 0;
+ }
+ return 3;
+}
+
+void FoFiTrueType::convertToType42(char *psName, char **encoding,
+ Gushort *codeToGID,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[512];
+ GBool ok;
+
+ // write the header
+ ok = gTrue;
+ sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "10 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+
+ // write the guts of the dictionary
+ cvtEncoding(encoding, outputFunc, outputStream);
+ cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
+ cvtSfnts(outputFunc, outputStream, NULL);
+
+ // end the dictionary and define the font
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+}
+
+void FoFiTrueType::convertToCIDType2(char *psName,
+ Gushort *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[512];
+ Gushort cid;
+ GBool ok;
+ int i, j, k;
+
+ // write the header
+ ok = gTrue;
+ sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "20 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/CIDFontName /", 14);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
+ (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
+ (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
+ (*outputFunc)(outputStream, " end def\n", 10);
+ (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
+ if (cidMap) {
+ sprintf(buf, "/CIDCount %d def\n", nCIDs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (nCIDs > 32767) {
+ (*outputFunc)(outputStream, "/CIDMap [", 9);
+ for (i = 0; i < nCIDs; i += 32768 - 16) {
+ (*outputFunc)(outputStream, "<\n", 2);
+ for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
+ (*outputFunc)(outputStream, " ", 2);
+ for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
+ cid = cidMap[i+j+k];
+ sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ (*outputFunc)(outputStream, " >", 3);
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ (*outputFunc)(outputStream, "] def\n", 6);
+ } else {
+ (*outputFunc)(outputStream, "/CIDMap <\n", 10);
+ for (i = 0; i < nCIDs; i += 16) {
+ (*outputFunc)(outputStream, " ", 2);
+ for (j = 0; j < 16 && i+j < nCIDs; ++j) {
+ cid = cidMap[i+j];
+ sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ (*outputFunc)(outputStream, "> def\n", 6);
+ }
+ } else {
+ // direct mapping - just fill the string(s) with s[i]=i
+ sprintf(buf, "/CIDCount %d def\n", nGlyphs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (nGlyphs > 32767) {
+ (*outputFunc)(outputStream, "/CIDMap [\n", 10);
+ for (i = 0; i < nGlyphs; i += 32767) {
+ j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
+ sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
+ " 255 and put\n", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, " } for\n", 8);
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ } else {
+ sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream,
+ " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
+ (*outputFunc)(outputStream,
+ " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
+ (*outputFunc)(outputStream, " } for\n", 8);
+ (*outputFunc)(outputStream, "def\n", 4);
+ }
+ }
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+ (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
+ (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
+ (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
+ (*outputFunc)(outputStream, " end readonly def\n", 19);
+
+ // write the guts of the dictionary
+ cvtSfnts(outputFunc, outputStream, NULL);
+
+ // end the dictionary and define the font
+ (*outputFunc)(outputStream,
+ "CIDFontName currentdict end /CIDFont defineresource pop\n",
+ 56);
+}
+
+void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[512];
+ GString *sfntsName;
+ int n, i, j;
+
+ // write the Type 42 sfnts array
+ sfntsName = (new GString(psName))->append("_sfnts");
+ cvtSfnts(outputFunc, outputStream, sfntsName);
+ delete sfntsName;
+
+ // write the descendant Type 42 fonts
+ n = cidMap ? nCIDs : nGlyphs;
+ for (i = 0; i < n; i += 256) {
+ (*outputFunc)(outputStream, "10 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ sprintf(buf, "_%02x def\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+ (*outputFunc)(outputStream, "/sfnts ", 7);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, "_sfnts def\n", 11);
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ for (j = 0; j < 256 && i+j < n; ++j) {
+ sprintf(buf, "dup %d /c%02x put\n", j, j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
+ for (j = 0; j < 256 && i+j < n; ++j) {
+ sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+ (*outputFunc)(outputStream,
+ "FontName currentdict end definefont pop\n", 40);
+ }
+
+ // write the Type 0 parent font
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
+ (*outputFunc)(outputStream, "/Encoding [\n", 12);
+ for (i = 0; i < n; i += 256) {
+ sprintf(buf, "%d\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "/FDepVector [\n", 14);
+ for (i = 0; i < n; i += 256) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ sprintf(buf, "_%02x findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+}
+
+void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ static char cmapTab[20] = {
+ 0, 0, // table version number
+ 0, 1, // number of encoding tables
+ 0, 1, // platform ID
+ 0, 0, // encoding ID
+ 0, 0, 0, 12, // offset of subtable
+ 0, 0, // subtable format
+ 0, 1, // subtable length
+ 0, 1, // subtable version
+ 0, // map char 0 -> glyph 0
+ 0 // pad to multiple of four bytes
+ };
+ static char nameTab[8] = {
+ 0, 0, // format
+ 0, 0, // number of name records
+ 0, 6, // offset to start of string storage
+ 0, 0 // pad to multiple of four bytes
+ };
+ static char postTab[32] = {
+ 0, 1, 0, 0, // format
+ 0, 0, 0, 0, // italic angle
+ 0, 0, // underline position
+ 0, 0, // underline thickness
+ 0, 0, 0, 0, // fixed pitch
+ 0, 0, 0, 0, // min Type 42 memory
+ 0, 0, 0, 0, // max Type 42 memory
+ 0, 0, 0, 0, // min Type 1 memory
+ 0, 0, 0, 0 // max Type 1 memory
+ };
+ GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
+ int nZeroLengthTables;
+ TrueTypeLoca *locaTable;
+ TrueTypeTable *newTables;
+ int nNewTables, cmapIdx, cmapLen, glyfLen;
+ char *tableDir;
+ char locaBuf[4];
+ GBool ok;
+ Guint t;
+ int pos, i, j, k, n;
+
+ // check for missing tables
+ missingCmap = (cmapIdx = seekTable("cmap")) < 0;
+ missingName = seekTable("name") < 0;
+ missingPost = seekTable("post") < 0;
+
+ // read the loca table, check to see if it's sorted
+ locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca));
+ unsortedLoca = gFalse;
+ i = seekTable("loca");
+ pos = tables[i].offset;
+ ok = gTrue;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
+ } else {
+ locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
+ }
+ if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
+ unsortedLoca = gTrue;
+ }
+ locaTable[i].idx = i;
+ }
+
+ // check for zero-length tables
+ nZeroLengthTables = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (tables[i].len == 0) {
+ ++nZeroLengthTables;
+ }
+ }
+
+ // check for an incorrect cmap table length
+ badCmapLen = gFalse;
+ cmapLen = 0; // make gcc happy
+ if (!missingCmap) {
+ cmapLen = cmaps[0].offset + cmaps[0].len;
+ for (i = 1; i < nCmaps; ++i) {
+ if (cmaps[i].offset + cmaps[i].len > cmapLen) {
+ cmapLen = cmaps[i].offset + cmaps[i].len;
+ }
+ }
+ cmapLen -= tables[cmapIdx].offset;
+ if (cmapLen > tables[cmapIdx].len) {
+ badCmapLen = gTrue;
+ }
+ }
+
+ // if nothing is broken, just write the TTF file as is
+ if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
+ !badCmapLen && nZeroLengthTables == 0) {
+ (*outputFunc)(outputStream, (char *)file, len);
+ goto done1;
+ }
+
+ // sort the 'loca' table: 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, cmpTrueTypeLocaOffset uses offset 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)
+ glyfLen = 0; // make gcc happy
+ if (unsortedLoca) {
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaOffset);
+ for (i = 0; i < nGlyphs; ++i) {
+ locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
+ }
+ locaTable[nGlyphs].len = 0;
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaIdx);
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ locaTable[i].newOffset = pos;
+ pos += locaTable[i].len;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ }
+ glyfLen = pos;
+ }
+
+ // construct the new table directory:
+ // - keep all original tables with non-zero length
+ // - fix the cmap table's length, if necessary
+ // - add missing tables
+ // - sort the table by tag
+ // - compute new table positions, including 4-byte alignment
+ nNewTables = nTables - nZeroLengthTables +
+ (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
+ (missingPost ? 1 : 0);
+ newTables = (TrueTypeTable *)gmalloc(nNewTables * sizeof(TrueTypeTable));
+ j = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (tables[i].len > 0) {
+ newTables[j] = tables[i];
+ newTables[j].origOffset = tables[i].offset;
+ if (newTables[j].tag == cmapTag && badCmapLen) {
+ newTables[j].len = cmapLen;
+ } else if (newTables[j].tag == locaTag && unsortedLoca) {
+ newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ } else if (newTables[j].tag == glyfTag && unsortedLoca) {
+ newTables[j].len = glyfLen;
+ }
+ ++j;
+ }
+ }
+ if (missingCmap) {
+ newTables[j].tag = cmapTag;
+ newTables[j].checksum = 0; //~ should compute the checksum
+ newTables[j].len = sizeof(cmapTab);
+ ++j;
+ }
+ if (missingName) {
+ newTables[j].tag = nameTag;
+ newTables[j].checksum = 0; //~ should compute the checksum
+ newTables[j].len = sizeof(nameTab);
+ ++j;
+ }
+ if (missingPost) {
+ newTables[j].tag = postTag;
+ newTables[j].checksum = 0; //~ should compute the checksum
+ newTables[j].len = sizeof(postTab);
+ ++j;
+ }
+ qsort(newTables, nNewTables, sizeof(TrueTypeTable),
+ &cmpTrueTypeTableTag);
+ pos = 12 + nNewTables * 16;
+ for (i = 0; i < nNewTables; ++i) {
+ newTables[i].offset = pos;
+ pos += newTables[i].len;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ }
+
+ // write the table directory
+ tableDir = (char *)gmalloc(12 + nNewTables * 16);
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = (char)((nNewTables >> 8) & 0xff); // numTables
+ tableDir[5] = (char)(nNewTables & 0xff);
+ for (i = -1, t = (Guint)nNewTables; 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 = nNewTables * 16 - t;
+ tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
+ tableDir[11] = (char)(t & 0xff);
+ pos = 12;
+ for (i = 0; i < nNewTables; ++i) {
+ tableDir[pos ] = (char)(newTables[i].tag >> 24);
+ tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
+ tableDir[pos+ 2] = (char)(newTables[i].tag >> 8);
+ tableDir[pos+ 3] = (char) newTables[i].tag;
+ tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
+ tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
+ tableDir[pos+ 6] = (char)(newTables[i].checksum >> 8);
+ tableDir[pos+ 7] = (char) newTables[i].checksum;
+ tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
+ tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
+ tableDir[pos+10] = (char)(newTables[i].offset >> 8);
+ tableDir[pos+11] = (char) newTables[i].offset;
+ tableDir[pos+12] = (char)(newTables[i].len >> 24);
+ tableDir[pos+13] = (char)(newTables[i].len >> 16);
+ tableDir[pos+14] = (char)(newTables[i].len >> 8);
+ tableDir[pos+15] = (char) newTables[i].len;
+ pos += 16;
+ }
+ (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
+
+ // write the tables
+ for (i = 0; i < nNewTables; ++i) {
+ if (newTables[i].tag == cmapTag && missingCmap) {
+ (*outputFunc)(outputStream, cmapTab, newTables[i].len);
+ } else if (newTables[i].tag == nameTag && missingName) {
+ (*outputFunc)(outputStream, nameTab, newTables[i].len);
+ } else if (newTables[i].tag == postTag && missingPost) {
+ (*outputFunc)(outputStream, postTab, newTables[i].len);
+ } else if (newTables[i].tag == locaTag && unsortedLoca) {
+ for (j = 0; j <= nGlyphs; ++j) {
+ if (locaFmt) {
+ locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
+ locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
+ locaBuf[2] = (char)(locaTable[j].newOffset >> 8);
+ locaBuf[3] = (char) locaTable[j].newOffset;
+ (*outputFunc)(outputStream, locaBuf, 4);
+ } else {
+ locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
+ locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
+ (*outputFunc)(outputStream, locaBuf, 2);
+ }
+ }
+ } else if (newTables[i].tag == glyfTag && unsortedLoca) {
+ pos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ n = locaTable[j].len;
+ if (n > 0) {
+ k = locaTable[j].origOffset;
+ if (checkRegion(pos + k, n)) {
+ (*outputFunc)(outputStream, (char *)file + pos + k, n);
+ } else {
+ for (k = 0; k < n; ++k) {
+ (*outputFunc)(outputStream, "\0", 1);
+ }
+ }
+ if ((k = locaTable[j].len & 3)) {
+ (*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
+ }
+ }
+ }
+ } else {
+ if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
+ (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
+ newTables[i].len);
+ } else {
+ for (j = 0; j < newTables[i].len; ++j) {
+ (*outputFunc)(outputStream, "\0", 1);
+ }
+ }
+ }
+ if (newTables[i].len & 3) {
+ (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
+ }
+ }
+
+ gfree(tableDir);
+ gfree(newTables);
+ done1:
+ gfree(locaTable);
+}
+
+void FoFiTrueType::cvtEncoding(char **encoding,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char *name;
+ char buf[64];
+ int i;
+
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ if (encoding) {
+ for (i = 0; i < 256; ++i) {
+ if (!(name = encoding[i])) {
+ name = ".notdef";
+ }
+ sprintf(buf, "dup %d /", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, " put\n", 5);
+ }
+ } else {
+ for (i = 0; i < 256; ++i) {
+ sprintf(buf, "dup %d /c%02x put\n", i, i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+}
+
+void FoFiTrueType::cvtCharStrings(char **encoding,
+ Gushort *codeToGID,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char *name;
+ char buf[64], buf2[16];
+ int i, k;
+
+ // always define '.notdef'
+ (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
+
+ // if there's no 'cmap' table, punt
+ if (nCmaps == 0) {
+ goto err;
+ }
+
+ // map char name to glyph index:
+ // 1. use encoding to map name to char code
+ // 2. use codeToGID to map char code to glyph index
+ // 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 (encoding) {
+ name = encoding[i];
+ } else {
+ sprintf(buf2, "c%02x", i);
+ name = buf2;
+ }
+ if (name && strcmp(name, ".notdef")) {
+ k = codeToGID[i];
+ // 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 > 0 && k < nGlyphs) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name, strlen(name));
+ sprintf(buf, " %d def\n", k);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ }
+
+ err:
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+}
+
+void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
+ void *outputStream, GString *name) {
+ Guchar headData[54];
+ TrueTypeLoca *locaTable;
+ Guchar *locaData;
+ TrueTypeTable newTables[nT42Tables];
+ Guchar tableDir[12 + nT42Tables*16];
+ GBool ok;
+ Guint checksum;
+ int nNewTables;
+ int length, pos, glyfPos, i, j, k;
+
+ // construct the 'head' table, zero out the font checksum
+ i = seekTable("head");
+ pos = tables[i].offset;
+ if (!checkRegion(pos, 54)) {
+ return;
+ }
+ memcpy(headData, file + pos, 54);
+ headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
+
+ // read the original 'loca' table, pad entries out to 4 bytes, 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 offset 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)
+ locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca));
+ i = seekTable("loca");
+ pos = tables[i].offset;
+ ok = gTrue;
+ for (i = 0; i <= nGlyphs; ++i) {
+ locaTable[i].idx = i;
+ if (locaFmt) {
+ locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
+ } else {
+ locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
+ }
+ }
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaOffset);
+ for (i = 0; i < nGlyphs; ++i) {
+ locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
+ }
+ locaTable[nGlyphs].len = 0;
+ qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaIdx);
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ locaTable[i].newOffset = pos;
+ pos += locaTable[i].len;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ }
+
+ // construct the new 'loca' table
+ locaData = (Guchar *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
+ for (i = 0; i <= nGlyphs; ++i) {
+ pos = locaTable[i].newOffset;
+ if (locaFmt) {
+ locaData[4*i ] = (Guchar)(pos >> 24);
+ locaData[4*i+1] = (Guchar)(pos >> 16);
+ locaData[4*i+2] = (Guchar)(pos >> 8);
+ locaData[4*i+3] = (Guchar) pos;
+ } else {
+ locaData[2*i ] = (Guchar)(pos >> 9);
+ locaData[2*i+1] = (Guchar)(pos >> 1);
+ }
+ }
+
+ // count the number of tables
+ nNewTables = 0;
+ for (i = 0; i < nT42Tables; ++i) {
+ if (t42Tables[i].required ||
+ seekTable(t42Tables[i].tag) >= 0) {
+ ++nNewTables;
+ }
+ }
+
+ // construct the new table headers, including table checksums
+ // (pad each table out to a multiple of 4 bytes)
+ pos = 12 + nNewTables*16;
+ k = 0;
+ for (i = 0; i < nT42Tables; ++i) {
+ length = -1;
+ checksum = 0; // make gcc happy
+ if (i == t42HeadTable) {
+ length = 54;
+ checksum = computeTableChecksum(headData, 54);
+ } else if (i == t42LocaTable) {
+ length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ checksum = computeTableChecksum(locaData, length);
+ } else if (i == t42GlyfTable) {
+ length = 0;
+ checksum = 0;
+ glyfPos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ length += locaTable[j].len;
+ if (length & 3) {
+ length += 4 - (length & 3);
+ }
+ if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
+ checksum +=
+ computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
+ locaTable[j].len);
+ }
+ }
+ } else {
+ if ((j = seekTable(t42Tables[i].tag)) >= 0) {
+ length = tables[j].len;
+ if (checkRegion(tables[j].offset, length)) {
+ checksum = computeTableChecksum(file + tables[j].offset, length);
+ }
+ } else if (t42Tables[i].required) {
+ //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
+ //~ t42Tables[i].tag);
+ length = 0;
+ checksum = 0;
+ }
+ }
+ if (length >= 0) {
+ newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
+ ((t42Tables[i].tag[1] & 0xff) << 16) |
+ ((t42Tables[i].tag[2] & 0xff) << 8) |
+ (t42Tables[i].tag[3] & 0xff);
+ newTables[k].checksum = checksum;
+ newTables[k].offset = pos;
+ newTables[k].len = length;
+ pos += length;
+ if (pos & 3) {
+ pos += 4 - (length & 3);
+ }
+ ++k;
+ }
+ }
+
+ // construct the table directory
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = 0; // numTables
+ tableDir[5] = nNewTables;
+ tableDir[6] = 0; // searchRange
+ tableDir[7] = (Guchar)128;
+ tableDir[8] = 0; // entrySelector
+ tableDir[9] = 3;
+ tableDir[10] = 0; // rangeShift
+ tableDir[11] = (Guchar)(16 * nNewTables - 128);
+ pos = 12;
+ for (i = 0; i < nNewTables; ++i) {
+ tableDir[pos ] = (Guchar)(newTables[i].tag >> 24);
+ tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
+ tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8);
+ tableDir[pos+ 3] = (Guchar) newTables[i].tag;
+ tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
+ tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
+ tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8);
+ tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
+ tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
+ tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
+ tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8);
+ tableDir[pos+11] = (Guchar) newTables[i].offset;
+ tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
+ tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
+ tableDir[pos+14] = (Guchar)(newTables[i].len >> 8);
+ tableDir[pos+15] = (Guchar) newTables[i].len;
+ pos += 16;
+ }
+
+ // compute the font checksum and store it in the head table
+ checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
+ for (i = 0; i < nNewTables; ++i) {
+ checksum += newTables[i].checksum;
+ }
+ checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
+ headData[ 8] = (Guchar)(checksum >> 24);
+ headData[ 9] = (Guchar)(checksum >> 16);
+ headData[10] = (Guchar)(checksum >> 8);
+ headData[11] = (Guchar) checksum;
+
+ // start the sfnts array
+ if (name) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, " [\n", 3);
+ } else {
+ (*outputFunc)(outputStream, "/sfnts [\n", 9);
+ }
+
+ // write the table directory
+ dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
+
+ // write the tables
+ for (i = 0; i < nNewTables; ++i) {
+ if (i == t42HeadTable) {
+ dumpString(headData, 54, outputFunc, outputStream);
+ } else if (i == t42LocaTable) {
+ length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ dumpString(locaData, length, outputFunc, outputStream);
+ } else if (i == t42GlyfTable) {
+ glyfPos = tables[seekTable("glyf")].offset;
+ for (j = 0; j < nGlyphs; ++j) {
+ if (locaTable[j].len > 0 &&
+ checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
+ dumpString(file + glyfPos + locaTable[j].origOffset,
+ locaTable[j].len, outputFunc, outputStream);
+ }
+ }
+ } else {
+ // length == 0 means the table is missing and the error was
+ // already reported during the construction of the table
+ // headers
+ if ((length = newTables[i].len) > 0) {
+ if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
+ checkRegion(tables[j].offset, tables[j].len)) {
+ dumpString(file + tables[j].offset, tables[j].len,
+ outputFunc, outputStream);
+ }
+ }
+ }
+ }
+
+ // end the sfnts array
+ (*outputFunc)(outputStream, "] def\n", 6);
+
+ gfree(locaData);
+ gfree(locaTable);
+}
+
+void FoFiTrueType::dumpString(Guchar *s, int length,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[64];
+ int pad, i, j;
+
+ (*outputFunc)(outputStream, "<", 1);
+ for (i = 0; i < length; i += 32) {
+ for (j = 0; j < 32 && i+j < length; ++j) {
+ sprintf(buf, "%02X", s[i+j] & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (i % (65536 - 32) == 65536 - 64) {
+ (*outputFunc)(outputStream, ">\n<", 3);
+ } else if (i+32 < length) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ }
+ if (length & 3) {
+ pad = 4 - (length & 3);
+ for (i = 0; i < pad; ++i) {
+ (*outputFunc)(outputStream, "00", 2);
+ }
+ }
+ // add an extra zero byte because the Adobe Type 42 spec says so
+ (*outputFunc)(outputStream, "00>\n", 4);
+}
+
+Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
+ Guint checksum, word;
+ int i;
+
+ checksum = 0;
+ for (i = 0; i+3 < length; i += 4) {
+ word = ((data[i ] & 0xff) << 24) +
+ ((data[i+1] & 0xff) << 16) +
+ ((data[i+2] & 0xff) << 8) +
+ (data[i+3] & 0xff);
+ checksum += word;
+ }
+ if (length & 3) {
+ word = 0;
+ i = length & ~3;
+ switch (length & 3) {
+ case 3:
+ word |= (data[i+2] & 0xff) << 8;
+ case 2:
+ word |= (data[i+1] & 0xff) << 16;
+ case 1:
+ word |= (data[i ] & 0xff) << 24;
+ break;
+ }
+ checksum += word;
+ }
+ return checksum;
+}
+
+void FoFiTrueType::parse() {
+ int pos, i, j;
+
+ parsedOk = gTrue;
+
+ // read the table directory
+ nTables = getU16BE(4, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ tables = (TrueTypeTable *)gmalloc(nTables * sizeof(TrueTypeTable));
+ pos = 12;
+ for (i = 0; i < nTables; ++i) {
+ tables[i].tag = getU32BE(pos, &parsedOk);
+ tables[i].checksum = getU32BE(pos + 4, &parsedOk);
+ tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
+ tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
+ if (tables[i].offset + tables[i].len < tables[i].offset ||
+ tables[i].offset + tables[i].len > len) {
+ parsedOk = gFalse;
+ }
+ pos += 16;
+ }
+ if (!parsedOk) {
+ return;
+ }
+
+ // check for tables that are required by both the TrueType spec and
+ // the Type 42 spec
+ if (seekTable("head") < 0 ||
+ seekTable("hhea") < 0 ||
+ seekTable("loca") < 0 ||
+ seekTable("maxp") < 0 ||
+ seekTable("glyf") < 0 ||
+ seekTable("hmtx") < 0) {
+ parsedOk = gFalse;
+ return;
+ }
+
+ // read the cmaps
+ if ((i = seekTable("cmap")) >= 0) {
+ pos = tables[i].offset + 2;
+ nCmaps = getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ return;
+ }
+ cmaps = (TrueTypeCmap *)gmalloc(nCmaps * sizeof(TrueTypeCmap));
+ for (j = 0; j < nCmaps; ++j) {
+ cmaps[j].platform = getU16BE(pos, &parsedOk);
+ cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
+ cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
+ pos += 8;
+ cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
+ cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
+ }
+ if (!parsedOk) {
+ return;
+ }
+ } else {
+ nCmaps = 0;
+ }
+
+ // get the number of glyphs from the maxp table
+ i = seekTable("maxp");
+ nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+
+ // get the bbox and loca table format from the head table
+ i = seekTable("head");
+ bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
+ bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
+ bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
+ bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
+ locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+
+ // read the post table
+ readPostTable();
+ if (!parsedOk) {
+ return;
+ }
+}
+
+void FoFiTrueType::readPostTable() {
+ GString *name;
+ int tablePos, postFmt, stringIdx, stringPos;
+ int i, j, n, m;
+
+ if ((i = seekTable("post")) < 0) {
+ return;
+ }
+ tablePos = tables[i].offset;
+ postFmt = getU32BE(tablePos, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (postFmt == 0x00010000) {
+ nameToGID = new GHash(gTrue);
+ for (i = 0; i < 258; ++i) {
+ nameToGID->add(new GString(macGlyphNames[i]), i);
+ }
+ } else if (postFmt == 0x00020000) {
+ nameToGID = new GHash(gTrue);
+ n = getU16BE(tablePos + 32, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (n > nGlyphs) {
+ n = nGlyphs;
+ }
+ stringIdx = 0;
+ stringPos = tablePos + 34 + 2*n;
+ for (i = 0; i < n; ++i) {
+ j = getU16BE(tablePos + 34 + 2*i, &parsedOk);
+ if (j < 258) {
+ nameToGID->removeInt(macGlyphNames[j]);
+ nameToGID->add(new GString(macGlyphNames[j]), i);
+ } else {
+ j -= 258;
+ if (j != stringIdx) {
+ for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
+ stringIdx < j;
+ ++stringIdx, stringPos += 1 + getU8(stringPos, &parsedOk)) ;
+ if (!parsedOk) {
+ return;
+ }
+ }
+ m = getU8(stringPos, &parsedOk);
+ if (!parsedOk || !checkRegion(stringPos + 1, m)) {
+ parsedOk = gFalse;
+ return;
+ }
+ name = new GString((char *)&file[stringPos + 1], m);
+ nameToGID->removeInt(name);
+ nameToGID->add(name, i);
+ ++stringIdx;
+ stringPos += 1 + m;
+ }
+ }
+ } else if (postFmt == 0x00028000) {
+ nameToGID = new GHash(gTrue);
+ for (i = 0; i < nGlyphs; ++i) {
+ j = getU8(tablePos + 32 + i, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (j < 258) {
+ nameToGID->removeInt(macGlyphNames[j]);
+ nameToGID->add(new GString(macGlyphNames[j]), i);
+ }
+ }
+ }
+}
+
+int FoFiTrueType::seekTable(char *tag) {
+ Guint tagI;
+ int i;
+
+ tagI = ((tag[0] & 0xff) << 24) |
+ ((tag[1] & 0xff) << 16) |
+ ((tag[2] & 0xff) << 8) |
+ (tag[3] & 0xff);
+ for (i = 0; i < nTables; ++i) {
+ if (tables[i].tag == tagI) {
+ return i;
+ }
+ }
+ return -1;
+}
diff --git a/pdf2swf/xpdf/FoFiTrueType.h b/pdf2swf/xpdf/FoFiTrueType.h
new file mode 100644
index 00000000..ea05eec4
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiTrueType.h
@@ -0,0 +1,133 @@
+//========================================================================
+//
+// FoFiTrueType.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFITRUETYPE_H
+#define FOFITRUETYPE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "FoFiBase.h"
+
+class GHash;
+struct TrueTypeTable;
+struct TrueTypeCmap;
+
+//------------------------------------------------------------------------
+// FoFiTrueType
+//------------------------------------------------------------------------
+
+class FoFiTrueType: public FoFiBase {
+public:
+
+ // Create a FoFiTrueType object from a memory buffer.
+ static FoFiTrueType *make(char *fileA, int lenA);
+
+ // Create a FoFiTrueType object from a file on disk.
+ static FoFiTrueType *load(char *fileName);
+
+ virtual ~FoFiTrueType();
+
+ // Return the number of cmaps defined by this font.
+ int getNumCmaps();
+
+ // Return the platform ID of the <i>th cmap.
+ int getCmapPlatform(int i);
+
+ // Return the encoding ID of the <i>th cmap.
+ int getCmapEncoding(int i);
+
+ // Return the index of the cmap for <platform>, <encoding>. Returns
+ // -1 if there is no corresponding cmap.
+ int findCmap(int platform, int encoding);
+
+ // Return the GID corresponding to <c> according to the <i>th cmap.
+ Gushort mapCodeToGID(int i, int c);
+
+ // Returns the GID corresponding to <name> according to the post
+ // table. Returns 0 if there is no mapping for <name> or if the
+ // font does not have a post table.
+ int mapNameToGID(char *name);
+
+ // Returns the least restrictive embedding licensing right (as
+ // defined by the TrueType spec):
+ // * 4: OS/2 table is missing or invalid
+ // * 3: installable embedding
+ // * 2: editable embedding
+ // * 1: preview & print embedding
+ // * 0: restricted license embedding
+ int getEmbeddingRights();
+
+ // Convert to a Type 42 font, suitable for embedding in a PostScript
+ // file. <psName> will be used as the PostScript font name (so we
+ // don't need to depend on the 'name' table in the font). The
+ // <encoding> array specifies the mapping from char codes to names.
+ // If <encoding> is NULL, the encoding is unknown or undefined. The
+ // <codeToGID> array specifies the mapping from char codes to GIDs.
+ void convertToType42(char *psName, char **encoding,
+ Gushort *codeToGID,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 2 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name (so we don't need to depend on the 'name' table in the
+ // font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
+ // entries.
+ void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name (so we don't need to depend on the 'name'
+ // table in the font). The <cidMap> array maps CIDs to GIDs; it has
+ // <nCIDs> entries.
+ void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Write a clean TTF file, filling in missing tables and correcting
+ // various other errors. If the font is complete and correct, it
+ // will be written unmodified.
+ void writeTTF(FoFiOutputFunc outputFunc, void *outputStream);
+
+private:
+
+ FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA);
+ void cvtEncoding(char **encoding,
+ FoFiOutputFunc outputFunc,
+ void *outputStream);
+ void cvtCharStrings(char **encoding,
+ Gushort *codeToGID,
+ FoFiOutputFunc outputFunc,
+ void *outputStream);
+ void cvtSfnts(FoFiOutputFunc outputFunc,
+ void *outputStream, GString *name);
+ void dumpString(Guchar *s, int length,
+ FoFiOutputFunc outputFunc,
+ void *outputStream);
+ Guint computeTableChecksum(Guchar *data, int length);
+ void parse();
+ void readPostTable();
+ int seekTable(char *tag);
+
+ TrueTypeTable *tables;
+ int nTables;
+ TrueTypeCmap *cmaps;
+ int nCmaps;
+ int nGlyphs;
+ int locaFmt;
+ int bbox[4];
+ GHash *nameToGID;
+
+ GBool parsedOk;
+};
+
+#endif
diff --git a/pdf2swf/xpdf/FoFiType1.cc b/pdf2swf/xpdf/FoFiType1.cc
new file mode 100644
index 00000000..fe54a632
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiType1.cc
@@ -0,0 +1,207 @@
+//========================================================================
+//
+// FoFiType1.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "FoFiEncodings.h"
+#include "FoFiType1.h"
+
+//------------------------------------------------------------------------
+// FoFiType1
+//------------------------------------------------------------------------
+
+FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
+ return new FoFiType1(fileA, lenA, gFalse);
+}
+
+FoFiType1 *FoFiType1::load(char *fileName) {
+ char *fileA;
+ int lenA;
+
+ if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
+ return NULL;
+ }
+ return new FoFiType1(fileA, lenA, gTrue);
+}
+
+FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
+ FoFiBase(fileA, lenA, freeFileDataA)
+{
+ name = NULL;
+ encoding = NULL;
+ parsed = gFalse;
+}
+
+FoFiType1::~FoFiType1() {
+ int i;
+
+ if (name) {
+ gfree(name);
+ }
+ if (encoding && encoding != fofiType1StandardEncoding) {
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+}
+
+char *FoFiType1::getName() {
+ if (!parsed) {
+ parse();
+ }
+ return name;
+}
+
+char **FoFiType1::getEncoding() {
+ if (!parsed) {
+ parse();
+ }
+ return encoding;
+}
+
+void FoFiType1::writeEncoded(char **newEncoding,
+ FoFiOutputFunc outputFunc, void *outputStream) {
+ char buf[512];
+ char *line;
+ int i;
+
+ // copy everything up to the encoding
+ for (line = (char *)file;
+ line && strncmp(line, "/Encoding", 9);
+ line = getNextLine(line)) ;
+ if (!line) {
+ // no encoding - just copy the whole font file
+ (*outputFunc)(outputStream, (char *)file, len);
+ return;
+ }
+ (*outputFunc)(outputStream, (char *)file, line - (char *)file);
+
+ // write the new encoding
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ (*outputFunc)(outputStream,
+ "0 1 255 {1 index exch /.notdef put} for\n", 40);
+ for (i = 0; i < 256; ++i) {
+ if (newEncoding[i]) {
+ sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+
+ // copy everything after the encoding
+ if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
+ line = getNextLine(line);
+ } else {
+ for (line = getNextLine(line);
+ line && strncmp(line, "readonly def", 12);
+ line = getNextLine(line)) ;
+ }
+ if (line) {
+ (*outputFunc)(outputStream, line, ((char *)file + len) - line);
+ }
+}
+
+char *FoFiType1::getNextLine(char *line) {
+ while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
+ ++line;
+ }
+ if (line < (char *)file + len && *line == '\x0d') {
+ ++line;
+ }
+ if (line < (char *)file + len && *line == '\x0a') {
+ ++line;
+ }
+ if (line >= (char *)file + len) {
+ return NULL;
+ }
+ return line;
+}
+
+void FoFiType1::parse() {
+ char *line, *line1, *p, *p2;
+ char buf[256];
+ char c;
+ int n, code, i, j;
+
+ for (i = 1, line = (char *)file;
+ i <= 100 && line && (!name || !encoding);
+ ++i) {
+
+ // get font name
+ if (!name && !strncmp(line, "/FontName", 9)) {
+ strncpy(buf, line, 255);
+ buf[255] = '\0';
+ if ((p = strchr(buf+9, '/')) &&
+ (p = strtok(p+1, " \t\n\r"))) {
+ name = copyString(p);
+ }
+ line = getNextLine(line);
+
+ // get encoding
+ } else if (!encoding &&
+ !strncmp(line, "/Encoding StandardEncoding def", 30)) {
+ encoding = fofiType1StandardEncoding;
+ } else if (!encoding &&
+ !strncmp(line, "/Encoding 256 array", 19)) {
+ encoding = (char **)gmalloc(256 * sizeof(char *));
+ for (j = 0; j < 256; ++j) {
+ encoding[j] = NULL;
+ }
+ line = getNextLine(line);
+ for (j = 0; j < 300 && line; ++j) {
+ line1 = getNextLine(line);
+ if ((n = line1 - line) > 255) {
+ n = 255;
+ }
+ strncpy(buf, line, n);
+ buf[n] = '\0';
+ for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
+ if (!strncmp(p, "dup", 3)) {
+ for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
+ for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
+ if (*p2) {
+ c = *p2;
+ *p2 = '\0';
+ if ((code = atoi(p)) < 256) {
+ *p2 = c;
+ for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
+ if (*p == '/') {
+ ++p;
+ for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
+ *p2 = '\0';
+ encoding[code] = copyString(p);
+ }
+ }
+ }
+ } else {
+ if (strtok(buf, " \t") &&
+ (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
+ break;
+ }
+ }
+ line = line1;
+ }
+ //~ check for getinterval/putinterval junk
+
+ } else {
+ line = getNextLine(line);
+ }
+
+ ++i;
+ }
+
+ parsed = gTrue;
+}
diff --git a/pdf2swf/xpdf/FoFiType1.h b/pdf2swf/xpdf/FoFiType1.h
new file mode 100644
index 00000000..843352b2
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiType1.h
@@ -0,0 +1,59 @@
+//========================================================================
+//
+// FoFiType1.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFITYPE1_H
+#define FOFITYPE1_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "FoFiBase.h"
+
+//------------------------------------------------------------------------
+// FoFiType1
+//------------------------------------------------------------------------
+
+class FoFiType1: public FoFiBase {
+public:
+
+ // Create a FoFiType1 object from a memory buffer.
+ static FoFiType1 *make(char *fileA, int lenA);
+
+ // Create a FoFiType1 object from a file on disk.
+ static FoFiType1 *load(char *fileName);
+
+ virtual ~FoFiType1();
+
+ // Return the font name.
+ char *getName();
+
+ // Return the encoding, as an array of 256 names (any of which may
+ // be NULL).
+ char **getEncoding();
+
+ // Write a version of the Type 1 font file with a new encoding.
+ void writeEncoded(char **newEncoding,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+private:
+
+ FoFiType1(char *fileA, int lenA, GBool freeFileDataA);
+
+ char *getNextLine(char *line);
+ void parse();
+
+ char *name;
+ char **encoding;
+ GBool parsed;
+};
+
+#endif
diff --git a/pdf2swf/xpdf/FoFiType1C.cc b/pdf2swf/xpdf/FoFiType1C.cc
new file mode 100644
index 00000000..91a21adc
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiType1C.cc
@@ -0,0 +1,2385 @@
+//========================================================================
+//
+// FoFiType1C.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "gmem.h"
+#include "GString.h"
+#include "FoFiEncodings.h"
+#include "FoFiType1C.h"
+
+//------------------------------------------------------------------------
+
+static char hexChars[17] = "0123456789ABCDEF";
+
+//------------------------------------------------------------------------
+// FoFiType1C
+//------------------------------------------------------------------------
+
+FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
+ FoFiType1C *ff;
+
+ ff = new FoFiType1C(fileA, lenA, gFalse);
+ if (!ff->parse()) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiType1C *FoFiType1C::load(char *fileName) {
+ FoFiType1C *ff;
+ char *fileA;
+ int lenA;
+
+ if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
+ return NULL;
+ }
+ ff = new FoFiType1C(fileA, lenA, gTrue);
+ if (!ff->parse()) {
+ delete ff;
+ return NULL;
+ }
+ return ff;
+}
+
+FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
+ FoFiBase(fileA, lenA, freeFileDataA)
+{
+ name = NULL;
+ encoding = NULL;
+ privateDicts = NULL;
+ fdSelect = NULL;
+ charset = NULL;
+}
+
+FoFiType1C::~FoFiType1C() {
+ int i;
+
+ if (name) {
+ delete name;
+ }
+ if (encoding &&
+ encoding != fofiType1StandardEncoding &&
+ encoding != fofiType1ExpertEncoding) {
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+ if (privateDicts) {
+ gfree(privateDicts);
+ }
+ if (fdSelect) {
+ gfree(fdSelect);
+ }
+ if (charset &&
+ charset != fofiType1CISOAdobeCharset &&
+ charset != fofiType1CExpertCharset &&
+ charset != fofiType1CExpertSubsetCharset) {
+ gfree(charset);
+ }
+}
+
+char *FoFiType1C::getName() {
+ return name ? name->getCString() : (char *)NULL;
+}
+
+char **FoFiType1C::getEncoding() {
+ return encoding;
+}
+
+Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
+ Gushort *map;
+ int n, i;
+
+ // a CID font's top dict has ROS as the first operator
+ if (topDict.firstOp != 0x0c1e) {
+ *nCIDs = 0;
+ return NULL;
+ }
+
+ // in a CID font, the charset data is the GID-to-CID mapping, so all
+ // we have to do is reverse it
+ n = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] > n) {
+ n = charset[i];
+ }
+ }
+ ++n;
+ map = (Gushort *)gmalloc(n * sizeof(Gushort));
+ memset(map, 0, n * sizeof(Gushort));
+ for (i = 0; i < nGlyphs; ++i) {
+ map[charset[i]] = i;
+ }
+ *nCIDs = n;
+ return map;
+}
+
+void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ Type1CEexecBuf eb;
+ Type1CIndex subrIdx;
+ Type1CIndexVal val;
+ char buf[512];
+ char **enc;
+ GBool ok;
+ int i;
+
+ // write header and font dictionary, up to encoding
+ ok = gTrue;
+ (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ if (topDict.versionSID != 0) {
+ getString(topDict.versionSID, buf, &ok);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ // the dictionary needs room for 12 entries: the following 9, plus
+ // Private and CharStrings (in the eexec section) and FID (which is
+ // added by definefont)
+ (*outputFunc)(outputStream, "12 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
+ if (topDict.versionSID != 0) {
+ (*outputFunc)(outputStream, "/version (", 10);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (topDict.noticeSID != 0) {
+ getString(topDict.noticeSID, buf, &ok);
+ (*outputFunc)(outputStream, "/Notice (", 9);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (topDict.copyrightSID != 0) {
+ getString(topDict.copyrightSID, buf, &ok);
+ (*outputFunc)(outputStream, "/Copyright (", 12);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (topDict.fullNameSID != 0) {
+ getString(topDict.fullNameSID, buf, &ok);
+ (*outputFunc)(outputStream, "/FullName (", 11);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (topDict.familyNameSID != 0) {
+ getString(topDict.familyNameSID, buf, &ok);
+ (*outputFunc)(outputStream, "/FamilyName (", 13);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (topDict.weightSID != 0) {
+ getString(topDict.weightSID, buf, &ok);
+ (*outputFunc)(outputStream, "/Weight (", 9);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (topDict.isFixedPitch) {
+ (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
+ } else {
+ (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
+ }
+ sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, " def\n", 5);
+ sprintf(buf, "/PaintType %d def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
+ topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (topDict.uniqueID != 0) {
+ sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+
+ // write the encoding
+ (*outputFunc)(outputStream, "/Encoding ", 10);
+ if (!newEncoding && encoding == fofiType1StandardEncoding) {
+ (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
+ } else {
+ (*outputFunc)(outputStream, "256 array\n", 10);
+ (*outputFunc)(outputStream,
+ "0 1 255 {1 index exch /.notdef put} for\n", 40);
+ enc = newEncoding ? newEncoding : encoding;
+ for (i = 0; i < 256; ++i) {
+ if (enc[i]) {
+ sprintf(buf, "dup %d /%s put\n", i, enc[i]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ }
+ (*outputFunc)(outputStream, "currentdict end\n", 16);
+
+ // start the binary section
+ (*outputFunc)(outputStream, "currentfile eexec\n", 18);
+ eb.outputFunc = outputFunc;
+ eb.outputStream = outputStream;
+ eb.ascii = ascii;
+ eb.r1 = 55665;
+ eb.line = 0;
+
+ // write the private dictionary
+ eexecWrite(&eb, "\x83\xca\x73\xd5");
+ eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
+ eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
+ " executeonly def\n");
+ eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
+ eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
+ eexecWrite(&eb, "/MinFeature {16 16} def\n");
+ eexecWrite(&eb, "/password 5839 def\n");
+ if (privateDicts[0].nBlueValues) {
+ eexecWrite(&eb, "/BlueValues [");
+ for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
+ sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nOtherBlues) {
+ eexecWrite(&eb, "/OtherBlues [");
+ for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
+ sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nFamilyBlues) {
+ eexecWrite(&eb, "/FamilyBlues [");
+ for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
+ sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nFamilyOtherBlues) {
+ eexecWrite(&eb, "/FamilyOtherBlues [");
+ for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
+ sprintf(buf, "%s%d", i > 0 ? " " : "",
+ privateDicts[0].familyOtherBlues[i]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].blueScale != 0.039625) {
+ sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].blueShift != 7) {
+ sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].blueFuzz != 1) {
+ sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].hasStdHW) {
+ sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].hasStdVW) {
+ sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].nStemSnapH) {
+ eexecWrite(&eb, "/StemSnapH [");
+ for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
+ sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].nStemSnapV) {
+ eexecWrite(&eb, "/StemSnapV [");
+ for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
+ sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[0].hasForceBold) {
+ sprintf(buf, "/ForceBold %s def\n",
+ privateDicts[0].forceBold ? "true" : "false");
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].forceBoldThreshold != 0) {
+ sprintf(buf, "/ForceBoldThreshold %g def\n",
+ privateDicts[0].forceBoldThreshold);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].languageGroup != 0) {
+ sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[0].expansionFactor != 0.06) {
+ sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
+ eexecWrite(&eb, buf);
+ }
+
+ // set up subroutines
+ ok = gTrue;
+ getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
+ if (!ok) {
+ subrIdx.pos = -1;
+ }
+
+ // write the CharStrings
+ sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
+ eexecWrite(&eb, buf);
+ for (i = 0; i < nGlyphs; ++i) {
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, i, &val, &ok);
+ if (ok) {
+ getString(charset[i], buf, &ok);
+ if (ok) {
+ eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
+ }
+ }
+ }
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "readonly put\n");
+ eexecWrite(&eb, "noaccess put\n");
+ eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
+ eexecWrite(&eb, "mark currentfile closefile\n");
+
+ // trailer
+ if (ascii && eb.line > 0) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
+ }
+ (*outputFunc)(outputStream, "cleartomark\n", 12);
+}
+
+void FoFiType1C::convertToCIDType0(char *psName,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ int *cidMap;
+ GString *charStrings;
+ int *charStringOffsets;
+ Type1CIndex subrIdx;
+ Type1CIndexVal val;
+ int nCIDs, gdBytes;
+ char buf[512], buf2[512];
+ GBool ok;
+ int gid, offset, n, i, j, k;
+
+ // compute the CID count and build the CID-to-GID mapping
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmalloc(nCIDs * sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+
+ // build the charstrings
+ charStrings = new GString();
+ charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ charStringOffsets[i] = charStrings->getLength();
+ if ((gid = cidMap[i]) >= 0) {
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, gid, &val, &ok);
+ if (ok) {
+ getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
+ if (!ok) {
+ subrIdx.pos = -1;
+ }
+ cvtGlyph(val.pos, val.len, charStrings,
+ &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
+ }
+ }
+ }
+ charStringOffsets[nCIDs] = charStrings->getLength();
+
+ // compute gdBytes = number of bytes needed for charstring offsets
+ // (offset size needs to account for the charstring offset table,
+ // with a worst case of five bytes per entry, plus the charstrings
+ // themselves)
+ i = (nCIDs + 1) * 5 + charStrings->getLength();
+ if (i < 0x100) {
+ gdBytes = 1;
+ } else if (i < 0x10000) {
+ gdBytes = 2;
+ } else if (i < 0x1000000) {
+ gdBytes = 3;
+ } else {
+ gdBytes = 4;
+ }
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
+ (*outputFunc)(outputStream, "20 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/CIDFontName /", 14);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
+ (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
+ if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
+ ok = gTrue;
+ getString(topDict.registrySID, buf, &ok);
+ if (ok) {
+ (*outputFunc)(outputStream, " /Registry (", 13);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") def\n", 6);
+ }
+ ok = gTrue;
+ getString(topDict.orderingSID, buf, &ok);
+ if (ok) {
+ (*outputFunc)(outputStream, " /Ordering (", 13);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") def\n", 6);
+ }
+ } else {
+ (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
+ (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
+ }
+ sprintf(buf, " /Supplement %d def\n", topDict.supplement);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "end def\n", 8);
+ sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
+ topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
+ (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
+ (*outputFunc)(outputStream, "end def\n", 8);
+
+ // CIDFont-specific entries
+ sprintf(buf, "/CIDCount %d def\n", nCIDs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
+ sprintf(buf, "/GDBytes %d def\n", gdBytes);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
+ if (topDict.paintType != 0) {
+ sprintf(buf, "/PaintType %d def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+
+ // FDArray entry
+ sprintf(buf, "/FDArray %d array\n", nFDs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ for (i = 0; i < nFDs; ++i) {
+ sprintf(buf, "dup %d 10 dict begin\n", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/PaintType %d def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
+ if (privateDicts[i].nBlueValues) {
+ (*outputFunc)(outputStream, "/BlueValues [", 13);
+ for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
+ sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nOtherBlues) {
+ (*outputFunc)(outputStream, "/OtherBlues [", 13);
+ for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
+ sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nFamilyBlues) {
+ (*outputFunc)(outputStream, "/FamilyBlues [", 14);
+ for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
+ sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nFamilyOtherBlues) {
+ (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
+ for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
+ sprintf(buf, "%s%d", j > 0 ? " " : "",
+ privateDicts[i].familyOtherBlues[j]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].blueScale != 0.039625) {
+ sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].blueShift != 7) {
+ sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].blueFuzz != 1) {
+ sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].hasStdHW) {
+ sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].hasStdVW) {
+ sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].nStemSnapH) {
+ (*outputFunc)(outputStream, "/StemSnapH [", 12);
+ for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
+ sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].nStemSnapV) {
+ (*outputFunc)(outputStream, "/StemSnapV [", 12);
+ for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
+ sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ }
+ if (privateDicts[i].hasForceBold) {
+ sprintf(buf, "/ForceBold %s def\n",
+ privateDicts[i].forceBold ? "true" : "false");
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].forceBoldThreshold != 0) {
+ sprintf(buf, "/ForceBoldThreshold %g def\n",
+ privateDicts[i].forceBoldThreshold);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].languageGroup != 0) {
+ sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (privateDicts[i].expansionFactor != 0.06) {
+ sprintf(buf, "/ExpansionFactor %g def\n",
+ privateDicts[i].expansionFactor);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "currentdict end def\n", 20);
+ (*outputFunc)(outputStream, "currentdict end put\n", 20);
+ }
+ (*outputFunc)(outputStream, "def\n", 4);
+
+ // start the binary section
+ offset = (nCIDs + 1) * (1 + gdBytes);
+ sprintf(buf, "(Hex) %d StartData\n",
+ offset + charStrings->getLength());
+ (*outputFunc)(outputStream, buf, strlen(buf));
+
+ // write the charstring offset (CIDMap) table
+ for (i = 0; i <= nCIDs; i += 6) {
+ for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
+ if (i+j < nCIDs && cidMap[i+j] >= 0) {
+ buf[0] = (char)fdSelect[cidMap[i+j]];
+ } else {
+ buf[0] = (char)0;
+ }
+ n = offset + charStringOffsets[i+j];
+ for (k = gdBytes; k >= 1; --k) {
+ buf[k] = (char)(n & 0xff);
+ n >>= 8;
+ }
+ for (k = 0; k <= gdBytes; ++k) {
+ sprintf(buf2, "%02x", buf[k] & 0xff);
+ (*outputFunc)(outputStream, buf2, 2);
+ }
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+
+ // write the charstring data
+ n = charStrings->getLength();
+ for (i = 0; i < n; i += 32) {
+ for (j = 0; j < 32 && i+j < n; ++j) {
+ sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (i + 32 >= n) {
+ (*outputFunc)(outputStream, ">", 1);
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+
+ gfree(charStringOffsets);
+ delete charStrings;
+ gfree(cidMap);
+}
+
+void FoFiType1C::convertToType0(char *psName,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ int *cidMap;
+ Type1CIndex subrIdx;
+ Type1CIndexVal val;
+ int nCIDs;
+ char buf[512];
+ Type1CEexecBuf eb;
+ GBool ok;
+ int fd, i, j, k;
+
+ // compute the CID count and build the CID-to-GID mapping
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmalloc(nCIDs * sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+
+ // write the descendant Type 1 fonts
+ for (i = 0; i < nCIDs; i += 256) {
+
+ //~ this assumes that all CIDs in this block have the same FD --
+ //~ to handle multiple FDs correctly, need to somehow divide the
+ //~ font up by FD
+ fd = 0;
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ fd = fdSelect[cidMap[i+j]];
+ break;
+ }
+ }
+
+ // font dictionary (unencrypted section)
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ sprintf(buf, "_%02x def\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/PaintType %d def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (topDict.paintType != 0) {
+ sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ sprintf(buf, "dup %d /c%02x put\n", j, j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (j < 256) {
+ sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ (*outputFunc)(outputStream, "currentdict end\n", 16);
+
+ // start the binary section
+ (*outputFunc)(outputStream, "currentfile eexec\n", 18);
+ eb.outputFunc = outputFunc;
+ eb.outputStream = outputStream;
+ eb.ascii = gTrue;
+ eb.r1 = 55665;
+ eb.line = 0;
+
+ // start the private dictionary
+ eexecWrite(&eb, "\x83\xca\x73\xd5");
+ eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
+ eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
+ " executeonly def\n");
+ eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
+ eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
+ eexecWrite(&eb, "/MinFeature {16 16} def\n");
+ eexecWrite(&eb, "/password 5839 def\n");
+ if (privateDicts[fd].nBlueValues) {
+ eexecWrite(&eb, "/BlueValues [");
+ for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
+ sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nOtherBlues) {
+ eexecWrite(&eb, "/OtherBlues [");
+ for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
+ sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nFamilyBlues) {
+ eexecWrite(&eb, "/FamilyBlues [");
+ for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
+ sprintf(buf, "%s%d", k > 0 ? " " : "",
+ privateDicts[fd].familyBlues[k]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nFamilyOtherBlues) {
+ eexecWrite(&eb, "/FamilyOtherBlues [");
+ for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
+ sprintf(buf, "%s%d", k > 0 ? " " : "",
+ privateDicts[fd].familyOtherBlues[k]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].blueScale != 0.039625) {
+ sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].blueShift != 7) {
+ sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].blueFuzz != 1) {
+ sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].hasStdHW) {
+ sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].hasStdVW) {
+ sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].nStemSnapH) {
+ eexecWrite(&eb, "/StemSnapH [");
+ for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
+ sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].nStemSnapV) {
+ eexecWrite(&eb, "/StemSnapV [");
+ for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
+ sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
+ eexecWrite(&eb, buf);
+ }
+ eexecWrite(&eb, "] def\n");
+ }
+ if (privateDicts[fd].hasForceBold) {
+ sprintf(buf, "/ForceBold %s def\n",
+ privateDicts[fd].forceBold ? "true" : "false");
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].forceBoldThreshold != 0) {
+ sprintf(buf, "/ForceBoldThreshold %g def\n",
+ privateDicts[fd].forceBoldThreshold);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].languageGroup != 0) {
+ sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
+ eexecWrite(&eb, buf);
+ }
+ if (privateDicts[fd].expansionFactor != 0.06) {
+ sprintf(buf, "/ExpansionFactor %g def\n",
+ privateDicts[fd].expansionFactor);
+ eexecWrite(&eb, buf);
+ }
+
+ // set up the subroutines
+ ok = gTrue;
+ getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
+ if (!ok) {
+ subrIdx.pos = -1;
+ }
+
+ // start the CharStrings
+ sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
+ eexecWrite(&eb, buf);
+
+ // write the .notdef CharString
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, 0, &val, &ok);
+ if (ok) {
+ eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
+ &subrIdx, &privateDicts[fd]);
+ }
+
+ // write the CharStrings
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ ok = gTrue;
+ getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
+ if (ok) {
+ sprintf(buf, "c%02x", j);
+ eexecCvtGlyph(&eb, buf, val.pos, val.len,
+ &subrIdx, &privateDicts[fd]);
+ }
+ }
+ }
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "end\n");
+ eexecWrite(&eb, "readonly put\n");
+ eexecWrite(&eb, "noaccess put\n");
+ eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
+ eexecWrite(&eb, "mark currentfile closefile\n");
+
+ // trailer
+ if (eb.line > 0) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ for (j = 0; j < 8; ++j) {
+ (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
+ }
+ (*outputFunc)(outputStream, "cleartomark\n", 12);
+ }
+
+ // write the Type 0 parent font
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
+ (*outputFunc)(outputStream, "/Encoding [\n", 12);
+ for (i = 0; i < nCIDs; i += 256) {
+ sprintf(buf, "%d\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "/FDepVector [\n", 14);
+ for (i = 0; i < nCIDs; i += 256) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ sprintf(buf, "_%02x findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+
+ gfree(cidMap);
+}
+
+void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
+ int offset, int nBytes,
+ Type1CIndex *subrIdx,
+ Type1CPrivateDict *pDict) {
+ char buf[512];
+ GString *charBuf;
+
+ // generate the charstring
+ charBuf = new GString();
+ cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
+
+ sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
+ eexecWrite(eb, buf);
+ eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
+ charBuf->getLength());
+ eexecWrite(eb, " ND\n");
+
+ delete charBuf;
+}
+
+void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
+ Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
+ GBool top) {
+ Type1CIndexVal val;
+ GBool ok, dFP;
+ double d, dx, dy;
+ Gushort r2;
+ Guchar byte;
+ int pos, subrBias, start, i, k;
+
+ start = charBuf->getLength();
+ if (top) {
+ charBuf->append((char)73);
+ charBuf->append((char)58);
+ charBuf->append((char)147);
+ charBuf->append((char)134);
+ nOps = 0;
+ nHints = 0;
+ firstOp = gTrue;
+ }
+
+ pos = offset;
+ while (pos < offset + nBytes) {
+ ok = gTrue;
+ pos = getOp(pos, gTrue, &ok);
+ if (!ok) {
+ break;
+ }
+ if (!ops[nOps - 1].isNum) {
+ --nOps; // drop the operator
+ switch (ops[nOps].op) {
+ case 0x0001: // hstem
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
+ }
+ d = 0;
+ dFP = gFalse;
+ for (k = 0; k < nOps; k += 2) {
+ if (ops[k+1].num < 0) {
+ d += ops[k].num + ops[k+1].num;
+ dFP |= ops[k].isFP | ops[k+1].isFP;
+ cvtNum(d, dFP, charBuf);
+ cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
+ } else {
+ d += ops[k].num;
+ dFP |= ops[k].isFP;
+ cvtNum(d, dFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ d += ops[k+1].num;
+ dFP |= ops[k+1].isFP;
+ }
+ charBuf->append((char)1);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0003: // vstem
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
+ }
+ d = 0;
+ dFP = gFalse;
+ for (k = 0; k < nOps; k += 2) {
+ if (ops[k+1].num < 0) {
+ d += ops[k].num + ops[k+1].num;
+ dFP |= ops[k].isFP | ops[k+1].isFP;
+ cvtNum(d, dFP, charBuf);
+ cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
+ } else {
+ d += ops[k].num;
+ dFP |= ops[k].isFP;
+ cvtNum(d, dFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ d += ops[k+1].num;
+ dFP |= ops[k+1].isFP;
+ }
+ charBuf->append((char)3);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0004: // vmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 2, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps != 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ charBuf->append((char)4);
+ nOps = 0;
+ break;
+ case 0x0005: // rlineto
+ if (nOps < 2 || nOps % 2 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
+ }
+ for (k = 0; k < nOps; k += 2) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ charBuf->append((char)5);
+ }
+ nOps = 0;
+ break;
+ case 0x0006: // hlineto
+ if (nOps < 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
+ }
+ for (k = 0; k < nOps; ++k) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ charBuf->append((char)((k & 1) ? 7 : 6));
+ }
+ nOps = 0;
+ break;
+ case 0x0007: // vlineto
+ if (nOps < 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
+ }
+ for (k = 0; k < nOps; ++k) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ charBuf->append((char)((k & 1) ? 6 : 7));
+ }
+ nOps = 0;
+ break;
+ case 0x0008: // rrcurveto
+ if (nOps < 6 || nOps % 6 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
+ }
+ for (k = 0; k < nOps; k += 6) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ break;
+ case 0x000a: // callsubr
+ if (nOps >= 1) {
+ subrBias = (subrIdx->len < 1240)
+ ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
+ k = subrBias + (int)ops[nOps - 1].num;
+ --nOps;
+ ok = gTrue;
+ getIndexVal(subrIdx, k, &val, &ok);
+ if (ok) {
+ cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
+ }
+ } else {
+ //~ error(-1, "Too few args to Type 2 callsubr");
+ }
+ // don't clear the stack
+ break;
+ case 0x000b: // return
+ // don't clear the stack
+ break;
+ case 0x000e: // endchar / seac
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps == 4) {
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ charBuf->append((char)12)->append((char)6);
+ } else if (nOps == 0) {
+ charBuf->append((char)14);
+ } else {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
+ }
+ nOps = 0;
+ break;
+ case 0x000f: // (obsolete)
+ // this op is ignored, but we need the glyph width
+ if (firstOp) {
+ cvtGlyphWidth(nOps > 0, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ nOps = 0;
+ break;
+ case 0x0010: // blend
+ //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
+ nOps = 0;
+ break;
+ case 0x0012: // hstemhm
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0013: // hintmask
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps > 0) {
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
+ //~ nOps);
+ }
+ nHints += nOps / 2;
+ }
+ pos += (nHints + 7) >> 3;
+ nOps = 0;
+ break;
+ case 0x0014: // cntrmask
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps > 0) {
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
+ //~ nOps);
+ }
+ nHints += nOps / 2;
+ }
+ pos += (nHints + 7) >> 3;
+ nOps = 0;
+ break;
+ case 0x0015: // rmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 3, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps != 2) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ charBuf->append((char)21);
+ nOps = 0;
+ break;
+ case 0x0016: // hmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 2, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps != 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ charBuf->append((char)22);
+ nOps = 0;
+ break;
+ case 0x0017: // vstemhm
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1, charBuf, pDict);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
+ }
+ nHints += nOps / 2;
+ nOps = 0;
+ break;
+ case 0x0018: // rcurveline
+ if (nOps < 8 || (nOps - 2) % 6 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
+ }
+ for (k = 0; k < nOps - 2; k += 6) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
+ charBuf->append((char)8);
+ }
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
+ charBuf->append((char)5);
+ nOps = 0;
+ break;
+ case 0x0019: // rlinecurve
+ if (nOps < 8 || (nOps - 6) % 2 != 0) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
+ }
+ for (k = 0; k < nOps - 6; k += 2) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
+ charBuf->append((char)5);
+ }
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
+ charBuf->append((char)8);
+ nOps = 0;
+ break;
+ case 0x001a: // vvcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
+ }
+ if (nOps % 2 == 1) {
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[4].num, ops[4].isFP, charBuf);
+ charBuf->append((char)8);
+ k = 5;
+ } else {
+ k = 0;
+ }
+ for (; k < nOps; k += 4) {
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ break;
+ case 0x001b: // hhcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
+ }
+ if (nOps % 2 == 1) {
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ cvtNum(ops[4].num, ops[4].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ charBuf->append((char)8);
+ k = 5;
+ } else {
+ k = 0;
+ }
+ for (; k < nOps; k += 4) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ break;
+ case 0x001d: // callgsubr
+ if (nOps >= 1) {
+ k = gsubrBias + (int)ops[nOps - 1].num;
+ --nOps;
+ ok = gTrue;
+ getIndexVal(&gsubrIdx, k, &val, &ok);
+ if (ok) {
+ cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
+ }
+ } else {
+ //~ error(-1, "Too few args to Type 2 callgsubr");
+ }
+ // don't clear the stack
+ break;
+ case 0x001e: // vhcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
+ }
+ for (k = 0; k < nOps && k != nOps-5; k += 4) {
+ if (k % 8 == 0) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ charBuf->append((char)30);
+ } else {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ charBuf->append((char)31);
+ }
+ }
+ if (k == nOps-5) {
+ if (k % 8 == 0) {
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ } else {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ }
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ break;
+ case 0x001f: // hvcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
+ }
+ for (k = 0; k < nOps && k != nOps-5; k += 4) {
+ if (k % 8 == 0) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ charBuf->append((char)31);
+ } else {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ charBuf->append((char)30);
+ }
+ }
+ if (k == nOps-5) {
+ if (k % 8 == 0) {
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ } else {
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[k].num, ops[k].isFP, charBuf);
+ cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
+ cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
+ cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
+ cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
+ }
+ charBuf->append((char)8);
+ }
+ nOps = 0;
+ break;
+ case 0x0c00: // dotsection (should be Type 1 only?)
+ // ignored
+ nOps = 0;
+ break;
+ case 0x0c03: // and
+ case 0x0c04: // or
+ case 0x0c05: // not
+ case 0x0c08: // store
+ case 0x0c09: // abs
+ case 0x0c0a: // add
+ case 0x0c0b: // sub
+ case 0x0c0c: // div
+ case 0x0c0d: // load
+ case 0x0c0e: // neg
+ case 0x0c0f: // eq
+ case 0x0c12: // drop
+ case 0x0c14: // put
+ case 0x0c15: // get
+ case 0x0c16: // ifelse
+ case 0x0c17: // random
+ case 0x0c18: // mul
+ case 0x0c1a: // sqrt
+ case 0x0c1b: // dup
+ case 0x0c1c: // exch
+ case 0x0c1d: // index
+ case 0x0c1e: // roll
+ //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
+ nOps = 0;
+ break;
+ case 0x0c22: // hflex
+ if (nOps != 7) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[4].num, ops[4].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[5].num, ops[5].isFP, charBuf);
+ cvtNum(-ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[6].num, ops[6].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ charBuf->append((char)8);
+ nOps = 0;
+ break;
+ case 0x0c23: // flex
+ if (nOps != 13) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ cvtNum(ops[4].num, ops[4].isFP, charBuf);
+ cvtNum(ops[5].num, ops[5].isFP, charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[6].num, ops[6].isFP, charBuf);
+ cvtNum(ops[7].num, ops[7].isFP, charBuf);
+ cvtNum(ops[8].num, ops[8].isFP, charBuf);
+ cvtNum(ops[9].num, ops[9].isFP, charBuf);
+ cvtNum(ops[10].num, ops[10].isFP, charBuf);
+ cvtNum(ops[11].num, ops[11].isFP, charBuf);
+ charBuf->append((char)8);
+ nOps = 0;
+ break;
+ case 0x0c24: // hflex1
+ if (nOps != 9) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ cvtNum(ops[4].num, ops[4].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[5].num, ops[5].isFP, charBuf);
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(ops[6].num, ops[6].isFP, charBuf);
+ cvtNum(ops[7].num, ops[7].isFP, charBuf);
+ cvtNum(ops[8].num, ops[8].isFP, charBuf);
+ cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
+ ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
+ charBuf->append((char)8);
+ nOps = 0;
+ break;
+ case 0x0c25: // flex1
+ if (nOps != 11) {
+ //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
+ }
+ cvtNum(ops[0].num, ops[0].isFP, charBuf);
+ cvtNum(ops[1].num, ops[1].isFP, charBuf);
+ cvtNum(ops[2].num, ops[2].isFP, charBuf);
+ cvtNum(ops[3].num, ops[3].isFP, charBuf);
+ cvtNum(ops[4].num, ops[4].isFP, charBuf);
+ cvtNum(ops[5].num, ops[5].isFP, charBuf);
+ charBuf->append((char)8);
+ cvtNum(ops[6].num, ops[6].isFP, charBuf);
+ cvtNum(ops[7].num, ops[7].isFP, charBuf);
+ cvtNum(ops[8].num, ops[8].isFP, charBuf);
+ cvtNum(ops[9].num, ops[9].isFP, charBuf);
+ dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
+ dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
+ if (fabs(dx) > fabs(dy)) {
+ cvtNum(ops[10].num, ops[10].isFP, charBuf);
+ cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
+ ops[7].isFP | ops[9].isFP, charBuf);
+ } else {
+ cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
+ ops[6].isFP | ops[8].isFP, charBuf);
+ cvtNum(ops[10].num, ops[10].isFP, charBuf);
+ }
+ charBuf->append((char)8);
+ nOps = 0;
+ break;
+ default:
+ //~ error(-1, "Illegal Type 2 charstring op: %04x",
+ //~ ops[nOps].op);
+ nOps = 0;
+ break;
+ }
+ }
+ }
+
+ // charstring encryption
+ if (top) {
+ r2 = 4330;
+ for (i = start; i < charBuf->getLength(); ++i) {
+ byte = charBuf->getChar(i) ^ (r2 >> 8);
+ charBuf->setChar(i, byte);
+ r2 = (byte + r2) * 52845 + 22719;
+ }
+ }
+}
+
+void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
+ Type1CPrivateDict *pDict) {
+ double w;
+ GBool wFP;
+ int i;
+
+ if (useOp) {
+ w = pDict->nominalWidthX + ops[0].num;
+ wFP = pDict->nominalWidthXFP | ops[0].isFP;
+ for (i = 1; i < nOps; ++i) {
+ ops[i-1] = ops[i];
+ }
+ --nOps;
+ } else {
+ w = pDict->defaultWidthX;
+ wFP = pDict->defaultWidthXFP;
+ }
+ cvtNum(0, gFalse, charBuf);
+ cvtNum(w, wFP, charBuf);
+ charBuf->append((char)13);
+}
+
+void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
+ Guchar buf[12];
+ int y, n;
+
+ n = 0;
+ if (isFP) {
+ if (x >= -32768 && x < 32768) {
+ y = (int)(x * 256.0);
+ buf[0] = 255;
+ buf[1] = (Guchar)(y >> 24);
+ buf[2] = (Guchar)(y >> 16);
+ buf[3] = (Guchar)(y >> 8);
+ buf[4] = (Guchar)y;
+ buf[5] = 255;
+ buf[6] = 0;
+ buf[7] = 0;
+ buf[8] = 1;
+ buf[9] = 0;
+ buf[10] = 12;
+ buf[11] = 12;
+ n = 12;
+ } else {
+ //~ error(-1, "Type 2 fixed point constant out of range");
+ }
+ } else {
+ y = (int)x;
+ if (y >= -107 && y <= 107) {
+ buf[0] = (Guchar)(y + 139);
+ n = 1;
+ } else if (y > 107 && y <= 1131) {
+ y -= 108;
+ buf[0] = (Guchar)((y >> 8) + 247);
+ buf[1] = (Guchar)(y & 0xff);
+ n = 2;
+ } else if (y < -107 && y >= -1131) {
+ y = -y - 108;
+ buf[0] = (Guchar)((y >> 8) + 251);
+ buf[1] = (Guchar)(y & 0xff);
+ n = 2;
+ } else {
+ buf[0] = 255;
+ buf[1] = (Guchar)(y >> 24);
+ buf[2] = (Guchar)(y >> 16);
+ buf[3] = (Guchar)(y >> 8);
+ buf[4] = (Guchar)y;
+ n = 5;
+ }
+ }
+ charBuf->append((char *)buf, n);
+}
+
+void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
+ Guchar *p;
+ Guchar x;
+
+ for (p = (Guchar *)s; *p; ++p) {
+ x = *p ^ (eb->r1 >> 8);
+ eb->r1 = (x + eb->r1) * 52845 + 22719;
+ if (eb->ascii) {
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
+ eb->line += 2;
+ if (eb->line == 64) {
+ (*eb->outputFunc)(eb->outputStream, "\n", 1);
+ eb->line = 0;
+ }
+ } else {
+ (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
+ }
+ }
+}
+
+void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
+ Guchar *s, int n) {
+ Guchar x;
+ int i;
+
+ // eexec encryption
+ for (i = 0; i < n; ++i) {
+ x = s[i] ^ (eb->r1 >> 8);
+ eb->r1 = (x + eb->r1) * 52845 + 22719;
+ if (eb->ascii) {
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
+ (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
+ eb->line += 2;
+ if (eb->line == 64) {
+ (*eb->outputFunc)(eb->outputStream, "\n", 1);
+ eb->line = 0;
+ }
+ } else {
+ (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
+ }
+ }
+}
+
+GBool FoFiType1C::parse() {
+ Type1CIndex fdIdx;
+ Type1CIndexVal val;
+ int i;
+
+ parsedOk = gTrue;
+
+ // some tools embed Type 1C fonts with an extra whitespace char at
+ // the beginning
+ if (len > 0 && file[0] != '\x01') {
+ ++file;
+ --len;
+ }
+
+ // find the indexes
+ getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
+ getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
+ getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
+ getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ gsubrBias = (gsubrIdx.len < 1240) ? 107
+ : (gsubrIdx.len < 33900) ? 1131 : 32768;
+
+ // read the first font name
+ getIndexVal(&nameIdx, 0, &val, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ name = new GString((char *)&file[val.pos], val.len);
+
+ // read the top dict for the first font
+ readTopDict();
+
+ // for CID fonts: read the FDArray dicts and private dicts
+ if (topDict.firstOp == 0x0c1e) {
+ if (topDict.fdArrayOffset == 0) {
+ nFDs = 1;
+ privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
+ readPrivateDict(0, 0, &privateDicts[0]);
+ } else {
+ getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ nFDs = fdIdx.len;
+ privateDicts = (Type1CPrivateDict *)
+ gmalloc(nFDs * sizeof(Type1CPrivateDict));
+ for (i = 0; i < nFDs; ++i) {
+ getIndexVal(&fdIdx, i, &val, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ readFD(val.pos, val.len, &privateDicts[i]);
+ }
+ }
+
+ // for 8-bit fonts: read the private dict
+ } else {
+ privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
+ readPrivateDict(topDict.privateOffset, topDict.privateSize,
+ &privateDicts[0]);
+ }
+
+ // check for parse errors in the private dict(s)
+ if (!parsedOk) {
+ return gFalse;
+ }
+
+ // get the charstrings index
+ if (topDict.charStringsOffset <= 0) {
+ parsedOk = gFalse;
+ return gFalse;
+ }
+ getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
+ if (!parsedOk) {
+ return gFalse;
+ }
+ nGlyphs = charStringsIdx.len;
+
+ // for CID fonts: read the FDSelect table
+ if (topDict.firstOp == 0x0c1e) {
+ readFDSelect();
+ if (!parsedOk) {
+ return gFalse;
+ }
+ }
+
+ // read the charset
+ if (!readCharset()) {
+ parsedOk = gFalse;
+ return gFalse;
+ }
+
+ // for 8-bit fonts: build the encoding
+ if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
+ buildEncoding();
+ if (!parsedOk) {
+ return gFalse;
+ }
+ }
+
+ return parsedOk;
+}
+
+void FoFiType1C::readTopDict() {
+ Type1CIndexVal topDictPtr;
+ int pos;
+
+ topDict.firstOp = -1;
+ topDict.versionSID = 0;
+ topDict.noticeSID = 0;
+ topDict.copyrightSID = 0;
+ topDict.fullNameSID = 0;
+ topDict.familyNameSID = 0;
+ topDict.weightSID = 0;
+ topDict.isFixedPitch = 0;
+ topDict.italicAngle = 0;
+ topDict.underlinePosition = -100;
+ topDict.underlineThickness = 50;
+ topDict.paintType = 0;
+ topDict.charstringType = 2;
+ topDict.fontMatrix[0] = 0.001;
+ topDict.fontMatrix[1] = 0;
+ topDict.fontMatrix[2] = 0;
+ topDict.fontMatrix[3] = 0.001;
+ topDict.fontMatrix[4] = 0;
+ topDict.fontMatrix[5] = 0;
+ topDict.uniqueID = 0;
+ topDict.fontBBox[0] = 0;
+ topDict.fontBBox[1] = 0;
+ topDict.fontBBox[2] = 0;
+ topDict.fontBBox[3] = 0;
+ topDict.strokeWidth = 0;
+ topDict.charsetOffset = 0;
+ topDict.encodingOffset = 0;
+ topDict.charStringsOffset = 0;
+ topDict.privateSize = 0;
+ topDict.privateOffset = 0;
+ topDict.registrySID = 0;
+ topDict.orderingSID = 0;
+ topDict.supplement = 0;
+ topDict.fdArrayOffset = 0;
+ topDict.fdSelectOffset = 0;
+
+ getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
+ pos = topDictPtr.pos;
+ nOps = 0;
+ while (pos < topDictPtr.pos + topDictPtr.len) {
+ pos = getOp(pos, gFalse, &parsedOk);
+ if (!parsedOk) {
+ break;
+ }
+ if (!ops[nOps - 1].isNum) {
+ --nOps; // drop the operator
+ if (topDict.firstOp < 0) {
+ topDict.firstOp = ops[nOps].op;
+ }
+ switch (ops[nOps].op) {
+ case 0x0000: topDict.versionSID = (int)ops[0].num; break;
+ case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
+ case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
+ case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
+ case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
+ case 0x0004: topDict.weightSID = (int)ops[0].num; break;
+ case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
+ case 0x0c02: topDict.italicAngle = ops[0].num; break;
+ case 0x0c03: topDict.underlinePosition = ops[0].num; break;
+ case 0x0c04: topDict.underlineThickness = ops[0].num; break;
+ case 0x0c05: topDict.paintType = (int)ops[0].num; break;
+ case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
+ case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
+ topDict.fontMatrix[1] = ops[1].num;
+ topDict.fontMatrix[2] = ops[2].num;
+ topDict.fontMatrix[3] = ops[3].num;
+ topDict.fontMatrix[4] = ops[4].num;
+ topDict.fontMatrix[5] = ops[5].num; break;
+ case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
+ case 0x0005: topDict.fontBBox[0] = ops[0].num;
+ topDict.fontBBox[1] = ops[1].num;
+ topDict.fontBBox[2] = ops[2].num;
+ topDict.fontBBox[3] = ops[3].num; break;
+ case 0x0c08: topDict.strokeWidth = ops[0].num; break;
+ case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
+ case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
+ case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
+ case 0x0012: topDict.privateSize = (int)ops[0].num;
+ topDict.privateOffset = (int)ops[1].num; break;
+ case 0x0c1e: topDict.registrySID = (int)ops[0].num;
+ topDict.orderingSID = (int)ops[1].num;
+ topDict.supplement = (int)ops[2].num; break;
+ case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
+ case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
+ }
+ nOps = 0;
+ }
+ }
+}
+
+// Read a CID font dict (FD) - this pulls out the private dict
+// pointer, and reads the private dict.
+void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
+ int pos, pSize, pOffset;
+
+ pSize = pOffset = 0;
+ pos = offset;
+ nOps = 0;
+ while (pos < offset + length) {
+ pos = getOp(pos, gFalse, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (!ops[nOps - 1].isNum) {
+ if (ops[nOps - 1].op == 0x0012) {
+ if (nOps < 3) {
+ parsedOk = gFalse;
+ return;
+ }
+ pSize = (int)ops[0].num;
+ pOffset = (int)ops[1].num;
+ break;
+ }
+ nOps = 0;
+ }
+ }
+ readPrivateDict(pOffset, pSize, pDict);
+}
+
+void FoFiType1C::readPrivateDict(int offset, int length,
+ Type1CPrivateDict *pDict) {
+ int pos;
+
+ pDict->nBlueValues = 0;
+ pDict->nOtherBlues = 0;
+ pDict->nFamilyBlues = 0;
+ pDict->nFamilyOtherBlues = 0;
+ pDict->blueScale = 0.039625;
+ pDict->blueShift = 7;
+ pDict->blueFuzz = 1;
+ pDict->hasStdHW = gFalse;
+ pDict->hasStdVW = gFalse;
+ pDict->nStemSnapH = 0;
+ pDict->nStemSnapV = 0;
+ pDict->hasForceBold = gFalse;
+ pDict->forceBoldThreshold = 0;
+ pDict->languageGroup = 0;
+ pDict->expansionFactor = 0.06;
+ pDict->initialRandomSeed = 0;
+ pDict->subrsOffset = 0;
+ pDict->defaultWidthX = 0;
+ pDict->defaultWidthXFP = 0;
+ pDict->nominalWidthX = 0;
+ pDict->nominalWidthXFP = 0;
+
+ // no dictionary
+ if (offset == 0 || length == 0) {
+ return;
+ }
+
+ pos = offset;
+ nOps = 0;
+ while (pos < offset + length) {
+ pos = getOp(pos, gFalse, &parsedOk);
+ if (!parsedOk) {
+ break;
+ }
+ if (!ops[nOps - 1].isNum) {
+ --nOps; // drop the operator
+ switch (ops[nOps].op) {
+ case 0x0006:
+ pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
+ type1CMaxBlueValues);
+ break;
+ case 0x0007:
+ pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
+ type1CMaxOtherBlues);
+ break;
+ case 0x0008:
+ pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
+ type1CMaxBlueValues);
+ break;
+ case 0x0009:
+ pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
+ type1CMaxOtherBlues);
+ break;
+ case 0x0c09:
+ pDict->blueScale = ops[0].num;
+ break;
+ case 0x0c0a:
+ pDict->blueShift = (int)ops[0].num;
+ break;
+ case 0x0c0b:
+ pDict->blueFuzz = (int)ops[0].num;
+ break;
+ case 0x000a:
+ pDict->stdHW = ops[0].num;
+ pDict->hasStdHW = gTrue;
+ break;
+ case 0x000b:
+ pDict->stdVW = ops[0].num;
+ pDict->hasStdVW = gTrue;
+ break;
+ case 0x0c0c:
+ pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
+ type1CMaxStemSnap);
+ break;
+ case 0x0c0d:
+ pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
+ type1CMaxStemSnap);
+ break;
+ case 0x0c0e:
+ pDict->forceBold = ops[0].num != 0;
+ pDict->hasForceBold = gTrue;
+ break;
+ case 0x0c0f:
+ pDict->forceBoldThreshold = ops[0].num;
+ break;
+ case 0x0c11:
+ pDict->languageGroup = (int)ops[0].num;
+ break;
+ case 0x0c12:
+ pDict->expansionFactor = ops[0].num;
+ break;
+ case 0x0c13:
+ pDict->initialRandomSeed = (int)ops[0].num;
+ break;
+ case 0x0013:
+ pDict->subrsOffset = offset + (int)ops[0].num;
+ break;
+ case 0x0014:
+ pDict->defaultWidthX = ops[0].num;
+ break;
+ case 0x0015:
+ pDict->nominalWidthX = ops[0].num;
+ break;
+ }
+ nOps = 0;
+ }
+ }
+}
+
+void FoFiType1C::readFDSelect() {
+ int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
+
+ fdSelect = (Guchar *)gmalloc(nGlyphs);
+ if (topDict.fdSelectOffset == 0) {
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ } else {
+ pos = topDict.fdSelectOffset;
+ fdSelectFmt = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (fdSelectFmt == 0) {
+ if (!checkRegion(pos, nGlyphs)) {
+ parsedOk = gFalse;
+ return;
+ }
+ memcpy(fdSelect, file + pos, nGlyphs);
+ } else if (fdSelectFmt == 3) {
+ nRanges = getU16BE(pos, &parsedOk);
+ pos += 2;
+ gid0 = getU16BE(pos, &parsedOk);
+ pos += 2;
+ for (i = 1; i <= nRanges; ++i) {
+ fd = getU8(pos++, &parsedOk);
+ gid1 = getU16BE(pos, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ pos += 2;
+ if (gid0 > gid1 || gid1 > nGlyphs) {
+ //~ error(-1, "Bad FDSelect table in CID font");
+ parsedOk = gFalse;
+ return;
+ }
+ for (j = gid0; j < gid1; ++j) {
+ fdSelect[j] = fd;
+ }
+ gid0 = gid1;
+ }
+ } else {
+ //~ error(-1, "Unknown FDSelect table format in CID font");
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ }
+ }
+}
+
+void FoFiType1C::buildEncoding() {
+ char buf[256];
+ int nCodes, nRanges, encFormat;
+ int pos, c, sid, nLeft, nSups, i, j;
+
+ if (topDict.encodingOffset == 0) {
+ encoding = fofiType1StandardEncoding;
+
+ } else if (topDict.encodingOffset == 1) {
+ encoding = fofiType1ExpertEncoding;
+
+ } else {
+ encoding = (char **)gmalloc(256 * sizeof(char *));
+ for (i = 0; i < 256; ++i) {
+ encoding[i] = NULL;
+ }
+ pos = topDict.encodingOffset;
+ encFormat = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if ((encFormat & 0x7f) == 0) {
+ nCodes = 1 + getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (nCodes > nGlyphs) {
+ nCodes = nGlyphs;
+ }
+ for (i = 1; i < nCodes; ++i) {
+ c = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
+ }
+ } else if ((encFormat & 0x7f) == 1) {
+ nRanges = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ nCodes = 1;
+ for (i = 0; i < nRanges; ++i) {
+ c = getU8(pos++, &parsedOk);
+ nLeft = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
+ if (c < 256) {
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(charset[nCodes], buf,
+ &parsedOk));
+ }
+ ++nCodes;
+ ++c;
+ }
+ }
+ }
+ if (encFormat & 0x80) {
+ nSups = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ for (i = 0; i < nSups; ++i) {
+ c = getU8(pos++, &parsedOk);;
+ if (!parsedOk) {
+ return;;
+ }
+ sid = getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ return;
+ }
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(sid, buf, &parsedOk));
+ }
+ }
+ }
+}
+
+GBool FoFiType1C::readCharset() {
+ int charsetFormat, c, pos;
+ int nLeft, i, j;
+
+ if (topDict.charsetOffset == 0) {
+ charset = fofiType1CISOAdobeCharset;
+ } else if (topDict.charsetOffset == 1) {
+ charset = fofiType1CExpertCharset;
+ } else if (topDict.charsetOffset == 2) {
+ charset = fofiType1CExpertSubsetCharset;
+ } else {
+ charset = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
+ for (i = 0; i < nGlyphs; ++i) {
+ charset[i] = 0;
+ }
+ pos = topDict.charsetOffset;
+ charsetFormat = getU8(pos++, &parsedOk);
+ if (charsetFormat == 0) {
+ for (i = 1; i < nGlyphs; ++i) {
+ charset[i] = (Gushort)getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ break;
+ }
+ }
+ } else if (charsetFormat == 1) {
+ i = 1;
+ while (i < nGlyphs) {
+ c = getU16BE(pos, &parsedOk);
+ pos += 2;
+ nLeft = getU8(pos++, &parsedOk);
+ if (!parsedOk) {
+ break;
+ }
+ for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
+ charset[i++] = (Gushort)c++;
+ }
+ }
+ } else if (charsetFormat == 2) {
+ i = 1;
+ while (i < nGlyphs) {
+ c = getU16BE(pos, &parsedOk);
+ pos += 2;
+ nLeft = getU16BE(pos, &parsedOk);
+ pos += 2;
+ if (!parsedOk) {
+ break;
+ }
+ for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
+ charset[i++] = (Gushort)c++;
+ }
+ }
+ }
+ if (!parsedOk) {
+ gfree(charset);
+ charset = NULL;
+ return gFalse;
+ }
+ }
+ return gTrue;
+}
+
+int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
+ static char nybChars[16] = "0123456789.ee -";
+ Type1COp op;
+ char buf[65];
+ int b0, b1, nyb0, nyb1, x, i;
+
+ b0 = getU8(pos++, ok);
+ op.isNum = gTrue;
+ op.isFP = gFalse;
+
+ if (b0 == 28) {
+ x = getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ if (x & 0x8000) {
+ x |= ~0xffff;
+ }
+ op.num = x;
+
+ } else if (!charstring && b0 == 29) {
+ x = getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ if (x & 0x80000000) {
+ x |= ~0xffffffff;
+ }
+ op.num = x;
+
+ } else if (!charstring && b0 == 30) {
+ i = 0;
+ do {
+ b1 = getU8(pos++, ok);
+ nyb0 = b1 >> 4;
+ nyb1 = b1 & 0x0f;
+ if (nyb0 == 0xf) {
+ break;
+ }
+ buf[i++] = nybChars[nyb0];
+ if (i == 64) {
+ break;
+ }
+ if (nyb0 == 0xc) {
+ buf[i++] = '-';
+ }
+ if (i == 64) {
+ break;
+ }
+ if (nyb1 == 0xf) {
+ break;
+ }
+ buf[i++] = nybChars[nyb1];
+ if (i == 64) {
+ break;
+ }
+ if (nyb1 == 0xc) {
+ buf[i++] = '-';
+ }
+ } while (i < 64);
+ buf[i] = '\0';
+ op.num = atof(buf);
+ op.isFP = gTrue;
+
+ } else if (b0 >= 32 && b0 <= 246) {
+ op.num = b0 - 139;
+
+ } else if (b0 >= 247 && b0 <= 250) {
+ op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
+
+ } else if (b0 >= 251 && b0 <= 254) {
+ op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
+
+ } else if (charstring && b0 == 255) {
+ x = getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ x = (x << 8) | getU8(pos++, ok);
+ if (x & 0x80000000) {
+ x |= ~0xffffffff;
+ }
+ op.num = (double)x / 65536.0;
+ op.isFP = gTrue;
+
+ } else if (b0 == 12) {
+ op.isNum = gFalse;
+ op.op = 0x0c00 + getU8(pos++, ok);
+
+ } else {
+ op.isNum = gFalse;
+ op.op = b0;
+ }
+
+ if (nOps < 49) {
+ ops[nOps++] = op;
+ }
+
+ return pos;
+}
+
+// Convert the delta-encoded ops array to an array of ints.
+int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
+ int x;
+ int n, i;
+
+ if ((n = nOps) > maxLen) {
+ n = maxLen;
+ }
+ x = 0;
+ for (i = 0; i < n; ++i) {
+ x += (int)ops[i].num;
+ arr[i] = x;
+ }
+ return n;
+}
+
+// Convert the delta-encoded ops array to an array of doubles.
+int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
+ double x;
+ int n, i;
+
+ if ((n = nOps) > maxLen) {
+ n = maxLen;
+ }
+ x = 0;
+ for (i = 0; i < n; ++i) {
+ x += ops[i].num;
+ arr[i] = x;
+ }
+ return n;
+}
+
+void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
+ idx->pos = pos;
+ idx->len = getU16BE(pos, ok);
+ if (idx->len == 0) {
+ // empty indexes are legal
+ idx->offSize = 0;
+ idx->startPos = idx->endPos = 0;
+ } else {
+ idx->offSize = getU8(pos + 2, ok);
+ if (idx->offSize < 1 || idx->offSize > 4) {
+ *ok = gFalse;
+ }
+ idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
+ if (idx->startPos < 0 || idx->startPos >= len) {
+ *ok = gFalse;
+ }
+ idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
+ idx->offSize, ok);
+ if (idx->endPos < idx->startPos || idx->endPos > len) {
+ *ok = gFalse;
+ }
+ }
+}
+
+void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
+ Type1CIndexVal *val, GBool *ok) {
+ int pos0, pos1;
+
+ if (i < 0 || i >= idx->len) {
+ *ok = gFalse;
+ return;
+ }
+ pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
+ idx->offSize, ok);
+ pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
+ idx->offSize, ok);
+ if (pos0 < idx->startPos || pos0 >= idx->endPos ||
+ pos1 <= idx->startPos || pos1 > idx->endPos ||
+ pos1 < pos0) {
+ *ok = gFalse;
+ }
+ val->pos = pos0;
+ val->len = pos1 - pos0;
+}
+
+char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
+ Type1CIndexVal val;
+ int n;
+
+ if (sid < 391) {
+ strcpy(buf, fofiType1CStdStrings[sid]);
+ } else {
+ sid -= 391;
+ getIndexVal(&stringIdx, sid, &val, ok);
+ if (ok) {
+ if ((n = val.len) > 255) {
+ n = 255;
+ }
+ strncpy(buf, (char *)&file[val.pos], n);
+ buf[n] = '\0';
+ } else {
+ buf[0] = '\0';
+ }
+ }
+ return buf;
+}
diff --git a/pdf2swf/xpdf/FoFiType1C.h b/pdf2swf/xpdf/FoFiType1C.h
new file mode 100644
index 00000000..e6f2b64d
--- /dev/null
+++ b/pdf2swf/xpdf/FoFiType1C.h
@@ -0,0 +1,226 @@
+//========================================================================
+//
+// FoFiType1C.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FOFITYPE1C_H
+#define FOFITYPE1C_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "FoFiBase.h"
+
+class GString;
+
+//------------------------------------------------------------------------
+
+struct Type1CIndex {
+ int pos; // absolute position in file
+ int len; // length (number of entries)
+ int offSize; // offset size
+ int startPos; // position of start of index data - 1
+ int endPos; // position one byte past end of the index
+};
+
+struct Type1CIndexVal {
+ int pos; // absolute position in file
+ int len; // length, in bytes
+};
+
+struct Type1CTopDict {
+ int firstOp;
+
+ int versionSID;
+ int noticeSID;
+ int copyrightSID;
+ int fullNameSID;
+ int familyNameSID;
+ int weightSID;
+ int isFixedPitch;
+ double italicAngle;
+ double underlinePosition;
+ double underlineThickness;
+ int paintType;
+ int charstringType;
+ double fontMatrix[6];
+ int uniqueID;
+ double fontBBox[4];
+ double strokeWidth;
+ int charsetOffset;
+ int encodingOffset;
+ int charStringsOffset;
+ int privateSize;
+ int privateOffset;
+
+ // CIDFont entries
+ int registrySID;
+ int orderingSID;
+ int supplement;
+ int fdArrayOffset;
+ int fdSelectOffset;
+};
+
+#define type1CMaxBlueValues 14
+#define type1CMaxOtherBlues 10
+#define type1CMaxStemSnap 12
+
+struct Type1CPrivateDict {
+ int blueValues[type1CMaxBlueValues];
+ int nBlueValues;
+ int otherBlues[type1CMaxOtherBlues];
+ int nOtherBlues;
+ int familyBlues[type1CMaxBlueValues];
+ int nFamilyBlues;
+ int familyOtherBlues[type1CMaxOtherBlues];
+ int nFamilyOtherBlues;
+ double blueScale;
+ int blueShift;
+ int blueFuzz;
+ double stdHW;
+ GBool hasStdHW;
+ double stdVW;
+ GBool hasStdVW;
+ double stemSnapH[type1CMaxStemSnap];
+ int nStemSnapH;
+ double stemSnapV[type1CMaxStemSnap];
+ int nStemSnapV;
+ GBool forceBold;
+ GBool hasForceBold;
+ double forceBoldThreshold;
+ int languageGroup;
+ double expansionFactor;
+ int initialRandomSeed;
+ int subrsOffset;
+ double defaultWidthX;
+ GBool defaultWidthXFP;
+ double nominalWidthX;
+ GBool nominalWidthXFP;
+};
+
+struct Type1COp {
+ GBool isNum; // true -> number, false -> operator
+ GBool isFP; // true -> floating point number, false -> int
+ union {
+ double num; // if num is true
+ int op; // if num is false
+ };
+};
+
+struct Type1CEexecBuf {
+ FoFiOutputFunc outputFunc;
+ void *outputStream;
+ GBool ascii; // ASCII encoding?
+ Gushort r1; // eexec encryption key
+ int line; // number of eexec chars left on current line
+};
+
+//------------------------------------------------------------------------
+// FoFiType1C
+//------------------------------------------------------------------------
+
+class FoFiType1C: public FoFiBase {
+public:
+
+ // Create a FoFiType1C object from a memory buffer.
+ static FoFiType1C *make(char *fileA, int lenA);
+
+ // Create a FoFiType1C object from a file on disk.
+ static FoFiType1C *load(char *fileName);
+
+ virtual ~FoFiType1C();
+
+ // Return the font name.
+ char *getName();
+
+ // Return the encoding, as an array of 256 names (any of which may
+ // be NULL). This is only useful with 8-bit fonts.
+ char **getEncoding();
+
+ // Return the mapping from CIDs to GIDs, and return the number of
+ // CIDs in *<nCIDs>. This is only useful for CID fonts.
+ Gushort *getCIDToGIDMap(int *nCIDs);
+
+ // Convert to a Type 1 font, suitable for embedding in a PostScript
+ // file. This is only useful with 8-bit fonts. If <newEncoding> is
+ // not NULL, it will be used in place of the encoding in the Type 1C
+ // font. If <ascii> is true the eexec section will be hex-encoded,
+ // otherwise it will be left as binary data.
+ void convertToType1(char **newEncoding, GBool ascii,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name.
+ void convertToCIDType0(char *psName,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name.
+ void convertToType0(char *psName,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
+private:
+
+ FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
+ void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
+ int offset, int nBytes,
+ Type1CIndex *subrIdx,
+ Type1CPrivateDict *pDict);
+ void cvtGlyph(int offset, int nBytes, GString *charBuf,
+ Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
+ GBool top);
+ void cvtGlyphWidth(GBool useOp, GString *charBuf,
+ Type1CPrivateDict *pDict);
+ void cvtNum(double x, GBool isFP, GString *charBuf);
+ void eexecWrite(Type1CEexecBuf *eb, char *s);
+ void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n);
+ GBool parse();
+ void readTopDict();
+ void readFD(int offset, int length, Type1CPrivateDict *pDict);
+ void readPrivateDict(int offset, int length, Type1CPrivateDict *pDict);
+ void readFDSelect();
+ void buildEncoding();
+ GBool readCharset();
+ int getOp(int pos, GBool charstring, GBool *ok);
+ int getDeltaIntArray(int *arr, int maxLen);
+ int getDeltaFPArray(double *arr, int maxLen);
+ void getIndex(int pos, Type1CIndex *idx, GBool *ok);
+ void getIndexVal(Type1CIndex *idx, int i, Type1CIndexVal *val, GBool *ok);
+ char *getString(int sid, char *buf, GBool *ok);
+
+ GString *name;
+ char **encoding;
+
+ Type1CIndex nameIdx;
+ Type1CIndex topDictIdx;
+ Type1CIndex stringIdx;
+ Type1CIndex gsubrIdx;
+ Type1CIndex charStringsIdx;
+
+ Type1CTopDict topDict;
+ Type1CPrivateDict *privateDicts;
+
+ int nGlyphs;
+ int nFDs;
+ Guchar *fdSelect;
+ Gushort *charset;
+ int gsubrBias;
+
+ GBool parsedOk;
+
+ Type1COp ops[49]; // operands and operator
+ 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
+};
+
+#endif
diff --git a/pdf2swf/xpdf/FontEncodingTables.cc b/pdf2swf/xpdf/FontEncodingTables.cc
index bd5f9cff..f3b9280a 100644
--- a/pdf2swf/xpdf/FontEncodingTables.cc
+++ b/pdf2swf/xpdf/FontEncodingTables.cc
@@ -2,7 +2,7 @@
//
// FontEncodingTables.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
@@ -184,32 +184,32 @@ char *macRomanEncoding[256] = {
"trademark",
"acute",
"dieresis",
- NULL,
+ "notequal",
"AE",
"Oslash",
- NULL,
+ "infinity",
"plusminus",
- NULL,
- NULL,
+ "lessequal",
+ "greaterequal",
"yen",
"mu",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ "partialdiff",
+ "summation",
+ "product",
+ "pi",
+ "integral",
"ordfeminine",
"ordmasculine",
- NULL,
+ "Omega",
"ae",
"oslash",
"questiondown",
"exclamdown",
"logicalnot",
- NULL,
+ "radical",
"florin",
- NULL,
- NULL,
+ "approxequal",
+ "Delta",
"guillemotleft",
"guillemotright",
"ellipsis",
@@ -226,7 +226,7 @@ char *macRomanEncoding[256] = {
"quoteleft",
"quoteright",
"divide",
- NULL,
+ "lozenge",
"ydieresis",
"Ydieresis",
"fraction",
@@ -251,7 +251,7 @@ char *macRomanEncoding[256] = {
"Igrave",
"Oacute",
"Ocircumflex",
- NULL,
+ "apple",
"Ograve",
"Uacute",
"Ucircumflex",
diff --git a/pdf2swf/xpdf/FontEncodingTables.h b/pdf2swf/xpdf/FontEncodingTables.h
index deee0a87..8b0a1e7e 100644
--- a/pdf2swf/xpdf/FontEncodingTables.h
+++ b/pdf2swf/xpdf/FontEncodingTables.h
@@ -2,7 +2,7 @@
//
// FontEncodingTables.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
diff --git a/pdf2swf/xpdf/Function.cc b/pdf2swf/xpdf/Function.cc
index 64ea60c1..46b1912d 100644
--- a/pdf2swf/xpdf/Function.cc
+++ b/pdf2swf/xpdf/Function.cc
@@ -2,15 +2,16 @@
//
// Function.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -379,8 +380,8 @@ void SampledFunction::transform(double *in, double *out) {
// pull 2^m values out of the sample array
for (j = 0; j < (1<<m); ++j) {
- idx = e[j & 1][m - 1];
- for (k = m - 2; k >= 0; --k) {
+ idx = 0;
+ for (k = m - 1; k >= 0; --k) {
idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
}
idx = idx * n + i;
@@ -411,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;
@@ -424,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()) {
@@ -450,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;
}
@@ -471,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();
@@ -482,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;
@@ -622,9 +616,13 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
}
StitchingFunction::StitchingFunction(StitchingFunction *func) {
+ int i;
+
k = func->k;
funcs = (Function **)gmalloc(k * sizeof(Function *));
- memcpy(funcs, func->funcs, k * sizeof(Function *));
+ for (i = 0; i < k; ++i) {
+ funcs[i] = func->funcs[i]->copy();
+ }
bounds = (double *)gmalloc((k + 1) * sizeof(double));
memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
encode = (double *)gmalloc(2 * k * sizeof(double));
@@ -635,9 +633,11 @@ StitchingFunction::StitchingFunction(StitchingFunction *func) {
StitchingFunction::~StitchingFunction() {
int i;
- for (i = 0; i < k; ++i) {
- if (funcs[i]) {
- delete funcs[i];
+ if (funcs) {
+ for (i = 0; i < k; ++i) {
+ if (funcs[i]) {
+ delete funcs[i];
+ }
}
}
gfree(funcs);
@@ -1095,14 +1095,14 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
if (!parseCode(str, codePtr)) {
return gFalse;
}
+ delete tok;
+ if (!(tok = getToken(str))) {
+ error(-1, "Unexpected end of PostScript function stream");
+ return gFalse;
+ }
} else {
elsePtr = -1;
}
- delete tok;
- if (!(tok = getToken(str))) {
- error(-1, "Unexpected end of PostScript function stream");
- return gFalse;
- }
if (!tok->cmp("if")) {
if (elsePtr >= 0) {
error(-1, "Got 'if' operator with two blocks in PostScript function");
@@ -1247,7 +1247,7 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
} else {
b2 = stack->popBool();
b1 = stack->popBool();
- stack->pushReal(b1 && b2);
+ stack->pushBool(b1 && b2);
}
break;
case psOpAtan:
@@ -1314,8 +1314,8 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
stack->roll(2, 1);
break;
case psOpExp:
- r2 = stack->popInt();
- r1 = stack->popInt();
+ r2 = stack->popNum();
+ r1 = stack->popNum();
stack->pushReal(pow(r1, r2));
break;
case psOpFalse:
@@ -1427,7 +1427,7 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
if (stack->topIsInt()) {
stack->pushInt(~stack->popInt());
} else {
- stack->pushReal(!stack->popBool());
+ stack->pushBool(!stack->popBool());
}
break;
case psOpOr:
@@ -1438,7 +1438,7 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
} else {
b2 = stack->popBool();
b1 = stack->popBool();
- stack->pushReal(b1 || b2);
+ stack->pushBool(b1 || b2);
}
break;
case psOpPop:
@@ -1456,7 +1456,7 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
}
break;
case psOpSin:
- stack->pushReal(cos(stack->popNum()));
+ stack->pushReal(sin(stack->popNum()));
break;
case psOpSqrt:
stack->pushReal(sqrt(stack->popNum()));
@@ -1489,7 +1489,7 @@ void PostScriptFunction::exec(PSStack *stack, int codePtr) {
} else {
b2 = stack->popBool();
b1 = stack->popBool();
- stack->pushReal(b1 ^ b2);
+ stack->pushBool(b1 ^ b2);
}
break;
case psOpIf:
diff --git a/pdf2swf/xpdf/Function.h b/pdf2swf/xpdf/Function.h
index 9b0879f3..0ceb0351 100644
--- a/pdf2swf/xpdf/Function.h
+++ b/pdf2swf/xpdf/Function.h
@@ -2,14 +2,16 @@
//
// Function.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef FUNCTION_H
#define FUNCTION_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -25,8 +27,8 @@ class PSStack;
// Function
//------------------------------------------------------------------------
-#define funcMaxInputs 8
-#define funcMaxOutputs 8
+#define funcMaxInputs 8
+#define funcMaxOutputs 32
class Function {
public:
diff --git a/pdf2swf/xpdf/GHash.cc b/pdf2swf/xpdf/GHash.cc
index dc09f717..1dd0e26c 100644
--- a/pdf2swf/xpdf/GHash.cc
+++ b/pdf2swf/xpdf/GHash.cc
@@ -2,15 +2,16 @@
//
// GHash.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include "gmem.h"
#include "GString.h"
#include "GHash.h"
@@ -19,7 +20,10 @@
struct GHashBucket {
GString *key;
- void *val;
+ union {
+ void *p;
+ int i;
+ } val;
GHashBucket *next;
};
@@ -60,35 +64,37 @@ GHash::~GHash() {
}
void GHash::add(GString *key, void *val) {
- GHashBucket **oldTab;
GHashBucket *p;
- int oldSize, i, h;
+ int h;
// expand the table if necessary
if (len >= size) {
- oldSize = size;
- oldTab = tab;
- size = 2*size + 1;
- tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
- for (h = 0; h < size; ++h) {
- tab[h] = NULL;
- }
- for (i = 0; i < oldSize; ++i) {
- while (oldTab[i]) {
- p = oldTab[i];
- oldTab[i] = oldTab[i]->next;
- h = hash(p->key);
- p->next = tab[h];
- tab[h] = p;
- }
- }
- gfree(oldTab);
+ expand();
}
// add the new symbol
p = new GHashBucket;
p->key = key;
- p->val = val;
+ p->val.p = val;
+ h = hash(key);
+ p->next = tab[h];
+ tab[h] = p;
+ ++len;
+}
+
+void GHash::add(GString *key, int val) {
+ GHashBucket *p;
+ int h;
+
+ // expand the table if necessary
+ if (len >= size) {
+ expand();
+ }
+
+ // add the new symbol
+ p = new GHashBucket;
+ p->key = key;
+ p->val.i = val;
h = hash(key);
p->next = tab[h];
tab[h] = p;
@@ -102,7 +108,17 @@ void *GHash::lookup(GString *key) {
if (!(p = find(key, &h))) {
return NULL;
}
- return p->val;
+ return p->val.p;
+}
+
+int GHash::lookupInt(GString *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ return p->val.i;
}
void *GHash::lookup(char *key) {
@@ -112,7 +128,17 @@ void *GHash::lookup(char *key) {
if (!(p = find(key, &h))) {
return NULL;
}
- return p->val;
+ return p->val.p;
+}
+
+int GHash::lookupInt(char *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ return p->val.i;
}
void *GHash::remove(GString *key) {
@@ -132,7 +158,30 @@ void *GHash::remove(GString *key) {
if (deleteKeys) {
delete p->key;
}
- val = p->val;
+ val = p->val.p;
+ delete p;
+ --len;
+ return val;
+}
+
+int GHash::removeInt(GString *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ int val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val.i;
delete p;
--len;
return val;
@@ -155,7 +204,30 @@ void *GHash::remove(char *key) {
if (deleteKeys) {
delete p->key;
}
- val = p->val;
+ val = p->val.p;
+ delete p;
+ --len;
+ return val;
+}
+
+int GHash::removeInt(char *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ int val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return 0;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val.i;
delete p;
--len;
return val;
@@ -183,7 +255,27 @@ GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
(*iter)->p = tab[(*iter)->h];
}
*key = (*iter)->p->key;
- *val = (*iter)->p->val;
+ *val = (*iter)->p->val.p;
+ return gTrue;
+}
+
+GBool GHash::getNext(GHashIter **iter, GString **key, int *val) {
+ if (!*iter) {
+ return gFalse;
+ }
+ if ((*iter)->p) {
+ (*iter)->p = (*iter)->p->next;
+ }
+ while (!(*iter)->p) {
+ if (++(*iter)->h == size) {
+ delete *iter;
+ *iter = NULL;
+ return gFalse;
+ }
+ (*iter)->p = tab[(*iter)->h];
+ }
+ *key = (*iter)->p->key;
+ *val = (*iter)->p->val.i;
return gTrue;
}
@@ -192,6 +284,30 @@ void GHash::killIter(GHashIter **iter) {
*iter = NULL;
}
+void GHash::expand() {
+ GHashBucket **oldTab;
+ GHashBucket *p;
+ int oldSize, h, i;
+
+ oldSize = size;
+ oldTab = tab;
+ size = 2*size + 1;
+ tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
+ for (h = 0; h < size; ++h) {
+ tab[h] = NULL;
+ }
+ for (i = 0; i < oldSize; ++i) {
+ while (oldTab[i]) {
+ p = oldTab[i];
+ oldTab[i] = oldTab[i]->next;
+ h = hash(p->key);
+ p->next = tab[h];
+ tab[h] = p;
+ }
+ }
+ gfree(oldTab);
+}
+
GHashBucket *GHash::find(GString *key, int *h) {
GHashBucket *p;
diff --git a/pdf2swf/xpdf/GHash.h b/pdf2swf/xpdf/GHash.h
index 91d97006..4a6e08d6 100644
--- a/pdf2swf/xpdf/GHash.h
+++ b/pdf2swf/xpdf/GHash.h
@@ -2,14 +2,16 @@
//
// GHash.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GHASH_H
#define GHASH_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -27,17 +29,24 @@ public:
GHash(GBool deleteKeysA = gFalse);
~GHash();
void add(GString *key, void *val);
+ void add(GString *key, int val);
void *lookup(GString *key);
+ int lookupInt(GString *key);
void *lookup(char *key);
+ int lookupInt(char *key);
void *remove(GString *key);
+ int removeInt(GString *key);
void *remove(char *key);
+ int removeInt(char *key);
int getLength() { return len; }
void startIter(GHashIter **iter);
GBool getNext(GHashIter **iter, GString **key, void **val);
+ GBool getNext(GHashIter **iter, GString **key, int *val);
void killIter(GHashIter **iter);
private:
+ void expand();
GHashBucket *find(GString *key, int *h);
GHashBucket *find(char *key, int *h);
int hash(GString *key);
diff --git a/pdf2swf/xpdf/GList.cc b/pdf2swf/xpdf/GList.cc
index f52bc262..9534232e 100644
--- a/pdf2swf/xpdf/GList.cc
+++ b/pdf2swf/xpdf/GList.cc
@@ -2,15 +2,16 @@
//
// GList.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <string.h>
#include "gmem.h"
#include "GList.h"
diff --git a/pdf2swf/xpdf/GList.h b/pdf2swf/xpdf/GList.h
index 0ef4fd78..4c52489f 100644
--- a/pdf2swf/xpdf/GList.h
+++ b/pdf2swf/xpdf/GList.h
@@ -2,14 +2,16 @@
//
// GList.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GLIST_H
#define GLIST_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/GMutex.h b/pdf2swf/xpdf/GMutex.h
new file mode 100644
index 00000000..7fa93d85
--- /dev/null
+++ b/pdf2swf/xpdf/GMutex.h
@@ -0,0 +1,49 @@
+//========================================================================
+//
+// GMutex.h
+//
+// Portable mutex macros.
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GMUTEX_H
+#define GMUTEX_H
+
+// Usage:
+//
+// GMutex m;
+// gInitMutex(&m);
+// ...
+// gLockMutex(&m);
+// ... critical section ...
+// gUnlockMutex(&m);
+// ...
+// gDestroyMutex(&m);
+
+#ifdef WIN32
+
+#include <windows.h>
+
+typedef CRITICAL_SECTION GMutex;
+
+#define gInitMutex(m) InitializeCriticalSection(m)
+#define gDestroyMutex(m) DeleteCriticalSection(m)
+#define gLockMutex(m) EnterCriticalSection(m)
+#define gUnlockMutex(m) LeaveCriticalSection(m)
+
+#else // assume pthreads
+
+#include <pthread.h>
+
+typedef pthread_mutex_t GMutex;
+
+#define gInitMutex(m) pthread_mutex_init(m, NULL)
+#define gDestroyMutex(m) pthread_mutex_destroy(m)
+#define gLockMutex(m) pthread_mutex_lock(m)
+#define gUnlockMutex(m) pthread_mutex_unlock(m)
+
+#endif
+
+#endif
diff --git a/pdf2swf/xpdf/GString.cc b/pdf2swf/xpdf/GString.cc
index 3bf626aa..7653fd06 100644
--- a/pdf2swf/xpdf/GString.cc
+++ b/pdf2swf/xpdf/GString.cc
@@ -4,15 +4,16 @@
//
// Simple variable-length string type.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -203,8 +204,12 @@ GString *GString::del(int i, int n) {
int j;
if (n > 0) {
- for (j = i; j <= length - n; ++j)
+ if (i + n > length) {
+ n = length - i;
+ }
+ for (j = i; j <= length - n; ++j) {
s[j] = s[j + n];
+ }
resize(length -= n);
}
return this;
diff --git a/pdf2swf/xpdf/GString.h b/pdf2swf/xpdf/GString.h
index 93796cb7..2083802b 100644
--- a/pdf2swf/xpdf/GString.h
+++ b/pdf2swf/xpdf/GString.h
@@ -4,14 +4,16 @@
//
// Simple variable-length string type.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GSTRING_H
#define GSTRING_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Gfx.cc b/pdf2swf/xpdf/Gfx.cc
index 81d164ee..a52aa02a 100644
--- a/pdf2swf/xpdf/Gfx.cc
+++ b/pdf2swf/xpdf/Gfx.cc
@@ -2,20 +2,22 @@
//
// Gfx.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include "gmem.h"
+#include "GlobalParams.h"
#include "CharTypes.h"
#include "Object.h"
#include "Array.h"
@@ -39,6 +41,12 @@
// constants
//------------------------------------------------------------------------
+// Max recursive depth for a function shading fill.
+#define functionMaxDepth 6
+
+// Max delta allowed in any color component for a function shading fill.
+#define functionColorDelta (1 / 256.0)
+
// Max number of splits along the t axis for an axial shading fill.
#define axialMaxSplits 256
@@ -55,6 +63,10 @@
// Operator table
//------------------------------------------------------------------------
+#ifdef WIN32 // this works around a bug in the VC7 compiler
+# pragma optimize("",off)
+#endif
+
Operator Gfx::opTab[] = {
{"\"", 3, {tchkNum, tchkNum, tchkString},
&Gfx::opMoveSetShowText},
@@ -210,6 +222,10 @@ Operator Gfx::opTab[] = {
&Gfx::opCurveTo2},
};
+#ifdef WIN32 // this works around a bug in the VC7 compiler
+# pragma optimize("",on)
+#endif
+
#define numOps (sizeof(opTab) / sizeof(Operator))
//------------------------------------------------------------------------
@@ -217,15 +233,23 @@ Operator Gfx::opTab[] = {
//------------------------------------------------------------------------
GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
- Object obj1;
+ Object obj1, obj2;
+ Ref r;
if (resDict) {
// build font dictionary
fonts = NULL;
- resDict->lookup("Font", &obj1);
- if (obj1.isDict()) {
- fonts = new GfxFontDict(xref, obj1.getDict());
+ resDict->lookupNF("Font", &obj1);
+ if (obj1.isRef()) {
+ obj1.fetch(xref, &obj2);
+ if (obj2.isDict()) {
+ r = obj1.getRef();
+ fonts = new GfxFontDict(xref, &r, obj2.getDict());
+ }
+ obj2.free();
+ } else if (obj1.isDict()) {
+ fonts = new GfxFontDict(xref, NULL, obj1.getDict());
}
obj1.free();
@@ -249,6 +273,7 @@ GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
xObjDict.initNull();
colorSpaceDict.initNull();
patternDict.initNull();
+ shadingDict.initNull();
gStateDict.initNull();
}
@@ -379,33 +404,38 @@ GBool GfxResources::lookupGState(char *name, Object *obj) {
// Gfx
//------------------------------------------------------------------------
-Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
- PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
- GBool printCommandsA) {
+Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
+ double hDPI, double vDPI, PDFRectangle *box, GBool crop,
+ PDFRectangle *cropBox, int rotate,
+ GBool (*abortCheckCbkA)(void *data),
+ void *abortCheckCbkDataA) {
int i;
xref = xrefA;
subPage = gFalse;
- printCommands = printCommandsA;
+ printCommands = globalParams->getPrintCommands();
// start the resource stack
res = new GfxResources(xref, resDict, NULL);
// initialize
out = outA;
- state = new GfxState(dpi, box, rotate, out->upsideDown());
+ state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown());
fontChanged = gFalse;
clip = clipNone;
ignoreUndef = 0;
- out->startPage(pageNum, state, cropBox->x1,cropBox->y1,cropBox->x2,cropBox->y2);
+ out->startPage(pageNum, state);
out->setDefaultCTM(state->getCTM());
out->updateAll(state);
for (i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
}
+ formDepth = 0;
+ abortCheckCbk = abortCheckCbkA;
+ abortCheckCbkData = abortCheckCbkDataA;
// set crop box
- /*if (crop) {
+ if (crop) {
state->moveTo(cropBox->x1, cropBox->y1);
state->lineTo(cropBox->x2, cropBox->y1);
state->lineTo(cropBox->x2, cropBox->y2);
@@ -414,29 +444,34 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
state->clip();
out->clip(state);
state->clearPath();
- }*/
+ }
}
Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
- PDFRectangle *box, GBool crop, PDFRectangle *cropBox) {
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox,
+ GBool (*abortCheckCbkA)(void *data),
+ void *abortCheckCbkDataA) {
int i;
xref = xrefA;
subPage = gTrue;
- printCommands = gFalse;
+ printCommands = globalParams->getPrintCommands();
// start the resource stack
res = new GfxResources(xref, resDict, NULL);
// initialize
out = outA;
- state = new GfxState(72, box, 0, gFalse);
+ state = new GfxState(72, 72, box, 0, gFalse);
fontChanged = gFalse;
clip = clipNone;
ignoreUndef = 0;
for (i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
}
+ formDepth = 0;
+ abortCheckCbk = abortCheckCbkA;
+ abortCheckCbkData = abortCheckCbkDataA;
// set crop box
if (crop) {
@@ -453,8 +488,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
Gfx::~Gfx() {
while (state->hasSaves()) {
- state = state->restore();
- out->restoreState(state);
+ restoreState();
}
if (!subPage) {
out->endPage();
@@ -494,11 +528,11 @@ void Gfx::display(Object *obj, GBool topLevel) {
void Gfx::go(GBool topLevel) {
Object obj;
Object args[maxArgs];
- int numArgs;
- int i;
+ int numArgs, i;
+ int lastAbortCheck;
// scan a sequence of objects
- updateLevel = 0;
+ updateLevel = lastAbortCheck = 0;
numArgs = 0;
parser->getObj(&obj);
while (!obj.isEOF()) {
@@ -526,6 +560,16 @@ void Gfx::go(GBool topLevel) {
updateLevel = 0;
}
+ // check for an abort
+ if (abortCheckCbk) {
+ if (updateLevel - lastAbortCheck > 10) {
+ if ((*abortCheckCbk)(abortCheckCbkData)) {
+ break;
+ }
+ lastAbortCheck = updateLevel;
+ }
+ }
+
// got an argument - save it
} else if (numArgs < maxArgs) {
args[numArgs++] = obj;
@@ -572,10 +616,11 @@ void Gfx::go(GBool topLevel) {
void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
Operator *op;
char *name;
+ Object *argPtr;
int i;
// find operator
- name = cmd->getName();
+ name = cmd->getCmd();
if (!(op = findOp(name))) {
if (ignoreUndef == 0)
error(getPos(), "Unknown operator '%s'", name);
@@ -583,12 +628,19 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
}
// type check args
+ argPtr = args;
if (op->numArgs >= 0) {
- if (numArgs != op->numArgs) {
- error(getPos(), "Wrong number (%d) of args to '%s' operator",
- numArgs, name);
+ if (numArgs < op->numArgs) {
+ error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name);
return;
}
+ if (numArgs > op->numArgs) {
+#if 0
+ error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name);
+#endif
+ argPtr += numArgs - op->numArgs;
+ numArgs = op->numArgs;
+ }
} else {
if (numArgs > -op->numArgs) {
error(getPos(), "Too many (%d) args to '%s' operator",
@@ -597,15 +649,15 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
}
}
for (i = 0; i < numArgs; ++i) {
- if (!checkArg(&args[i], op->tchk[i])) {
+ if (!checkArg(&argPtr[i], op->tchk[i])) {
error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
- i, name, args[i].getTypeName());
+ i, name, argPtr[i].getTypeName());
return;
}
}
// do it
- (this->*op->func)(args, numArgs);
+ (this->*op->func)(argPtr, numArgs);
}
Operator *Gfx::findOp(char *name) {
@@ -653,13 +705,11 @@ int Gfx::getPos() {
//------------------------------------------------------------------------
void Gfx::opSave(Object args[], int numArgs) {
- out->saveState(state);
- state = state->save();
+ saveState();
}
void Gfx::opRestore(Object args[], int numArgs) {
- state = state->restore();
- out->restoreState(state);
+ restoreState();
}
void Gfx::opConcat(Object args[], int numArgs) {
@@ -1175,18 +1225,7 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
}
void Gfx::doPatternFill(GBool eoFill) {
- GfxPatternColorSpace *patCS;
GfxPattern *pattern;
- GfxTilingPattern *tPat;
- GfxColorSpace *cs;
- double xMin, yMin, xMax, yMax, x, y, x1, y1;
- double cxMin, cyMin, cxMax, cyMax;
- int xi0, yi0, xi1, yi1, xi, yi;
- double *ctm, *btm, *ptm;
- double m[6], ictm[6], m1[6], imb[6];
- double det;
- double xstep, ystep;
- int i;
// this is a bit of a kludge -- patterns can be really slow, so we
// skip them if we're only doing text extraction, since they almost
@@ -1195,17 +1234,38 @@ void Gfx::doPatternFill(GBool eoFill) {
return;
}
- // get color space
- patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
-
- // get pattern
if (!(pattern = state->getFillPattern())) {
return;
}
- if (pattern->getType() != 1) {
- return;
+ switch (pattern->getType()) {
+ case 1:
+ doTilingPatternFill((GfxTilingPattern *)pattern, eoFill);
+ break;
+ case 2:
+ doShadingPatternFill((GfxShadingPattern *)pattern, eoFill);
+ break;
+ default:
+ error(getPos(), "Unimplemented pattern type (%d) in fill",
+ pattern->getType());
+ break;
}
- tPat = (GfxTilingPattern *)pattern;
+}
+
+void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
+ GfxPatternColorSpace *patCS;
+ GfxColorSpace *cs;
+ GfxPath *savedPath;
+ double xMin, yMin, xMax, yMax, x, y, x1, y1;
+ double cxMin, cyMin, cxMax, cyMax;
+ int xi0, yi0, xi1, yi1, xi, yi;
+ double *ctm, *btm, *ptm;
+ double m[6], ictm[6], m1[6], imb[6];
+ double det;
+ double xstep, ystep;
+ int i;
+
+ // get color space
+ patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
// construct a (pattern space) -> (current space) transform matrix
ctm = state->getCTM();
@@ -1244,17 +1304,26 @@ void Gfx::doPatternFill(GBool eoFill) {
imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
// save current graphics state
- out->saveState(state);
- state = state->save();
+ savedPath = state->getPath()->copy();
+ saveState();
- // set underlying color space (for uncolored tiling patterns)
+ // set underlying color space (for uncolored tiling patterns); set
+ // various other parameters (stroke color, line width) to match
+ // Adobe's behavior
if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
state->setFillColorSpace(cs->copy());
+ state->setStrokeColorSpace(cs->copy());
+ state->setStrokeColor(state->getFillColor());
} else {
state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
}
state->setFillPattern(NULL);
out->updateFillColor(state);
+ state->setStrokePattern(NULL);
+ out->updateStrokeColor(state);
+ state->setLineWidth(0);
+ out->updateLineWidth(state);
// clip to current path
state->clip();
@@ -1311,10 +1380,10 @@ void Gfx::doPatternFill(GBool eoFill) {
//~ edge instead of left/bottom (?)
xstep = fabs(tPat->getXStep());
ystep = fabs(tPat->getYStep());
- xi0 = (int)floor(xMin / xstep);
- xi1 = (int)ceil(xMax / xstep);
- yi0 = (int)floor(yMin / ystep);
- yi1 = (int)ceil(yMax / ystep);
+ xi0 = (int)floor((xMin - tPat->getBBox()[0]) / xstep);
+ xi1 = (int)ceil((xMax - tPat->getBBox()[0]) / xstep);
+ yi0 = (int)floor((yMin - tPat->getBBox()[1]) / ystep);
+ yi1 = (int)ceil((yMax - tPat->getBBox()[1]) / ystep);
for (i = 0; i < 4; ++i) {
m1[i] = m[i];
}
@@ -1330,12 +1399,101 @@ void Gfx::doPatternFill(GBool eoFill) {
}
// restore graphics state
- state = state->restore();
- out->restoreState(state);
+ restoreState();
+ state->setPath(savedPath);
+}
+
+void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
+ GfxShading *shading;
+ GfxPath *savedPath;
+ double *ctm, *btm, *ptm;
+ double m[6], ictm[6], m1[6];
+ double xMin, yMin, xMax, yMax;
+ double det;
+
+ shading = sPat->getShading();
+
+ // save current graphics state
+ savedPath = state->getPath()->copy();
+ saveState();
+
+ // clip to bbox
+ if (shading->getHasBBox()) {
+ shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+
+ // clip to current path
+ state->clip();
+ if (eoFill) {
+ out->eoClip(state);
+ } else {
+ out->clip(state);
+ }
+ state->clearPath();
+
+ // construct a (pattern space) -> (current space) transform matrix
+ ctm = state->getCTM();
+ btm = baseMatrix;
+ ptm = sPat->getMatrix();
+ // iCTM = invert CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+ // m1 = PTM * BTM = PTM * base transform matrix
+ m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
+ m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
+ m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
+ m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
+ m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
+ m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
+ // m = m1 * iCTM = (PTM * BTM) * (iCTM)
+ m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
+ m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
+ m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
+ m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
+ m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
+ m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
+
+ // set the new matrix
+ state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]);
+ out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);
+
+ // set the color space
+ state->setFillColorSpace(shading->getColorSpace()->copy());
+
+ // do shading type-specific operations
+ switch (shading->getType()) {
+ case 1:
+ doFunctionShFill((GfxFunctionShading *)shading);
+ break;
+ case 2:
+ doAxialShFill((GfxAxialShading *)shading);
+ break;
+ case 3:
+ doRadialShFill((GfxRadialShading *)shading);
+ break;
+ }
+
+ // restore graphics state
+ restoreState();
+ state->setPath(savedPath);
}
void Gfx::opShFill(Object args[], int numArgs) {
GfxShading *shading;
+ GfxPath *savedPath;
double xMin, yMin, xMax, yMax;
if (!(shading = res->lookupShading(args[0].getName()))) {
@@ -1343,8 +1501,8 @@ void Gfx::opShFill(Object args[], int numArgs) {
}
// save current graphics state
- out->saveState(state);
- state = state->save();
+ savedPath = state->getPath()->copy();
+ saveState();
// clip to bbox
if (shading->getHasBBox()) {
@@ -1364,6 +1522,9 @@ void Gfx::opShFill(Object args[], int numArgs) {
// do shading type-specific operations
switch (shading->getType()) {
+ case 1:
+ doFunctionShFill((GfxFunctionShading *)shading);
+ break;
case 2:
doAxialShFill((GfxAxialShading *)shading);
break;
@@ -1373,12 +1534,132 @@ void Gfx::opShFill(Object args[], int numArgs) {
}
// restore graphics state
- state = state->restore();
- out->restoreState(state);
+ restoreState();
+ state->setPath(savedPath);
delete shading;
}
+void Gfx::doFunctionShFill(GfxFunctionShading *shading) {
+ double x0, y0, x1, y1;
+ GfxColor colors[4];
+
+ shading->getDomain(&x0, &y0, &x1, &y1);
+ shading->getColor(x0, y0, &colors[0]);
+ shading->getColor(x0, y1, &colors[1]);
+ shading->getColor(x1, y0, &colors[2]);
+ shading->getColor(x1, y1, &colors[3]);
+ doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0);
+}
+
+void Gfx::doFunctionShFill1(GfxFunctionShading *shading,
+ double x0, double y0,
+ double x1, double y1,
+ GfxColor *colors, int depth) {
+ GfxColor fillColor;
+ GfxColor color0M, color1M, colorM0, colorM1, colorMM;
+ GfxColor colors2[4];
+ double *matrix;
+ double xM, yM;
+ int nComps, i, j;
+
+ nComps = shading->getColorSpace()->getNComps();
+ matrix = shading->getMatrix();
+
+ // compare the four corner colors
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < nComps; ++j) {
+ if (fabs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) {
+ break;
+ }
+ }
+ if (j < nComps) {
+ break;
+ }
+ }
+
+ // center of the rectangle
+ xM = 0.5 * (x0 + x1);
+ yM = 0.5 * (y0 + y1);
+
+ // the four corner colors are close (or we hit the recursive limit)
+ // -- fill the rectangle; but require at least one subdivision
+ // (depth==0) to avoid problems when the four outer corners of the
+ // shaded region are the same color
+ if ((i == 4 && depth > 0) || depth == functionMaxDepth) {
+
+ // use the center color
+ shading->getColor(xM, yM, &fillColor);
+ state->setFillColor(&fillColor);
+ out->updateFillColor(state);
+
+ // fill the rectangle
+ state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4],
+ x0 * matrix[1] + y0 * matrix[3] + matrix[5]);
+ state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4],
+ x1 * matrix[1] + y0 * matrix[3] + matrix[5]);
+ state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4],
+ x1 * matrix[1] + y1 * matrix[3] + matrix[5]);
+ state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4],
+ x0 * matrix[1] + y1 * matrix[3] + matrix[5]);
+ state->closePath();
+ out->fill(state);
+ state->clearPath();
+
+ // the four corner colors are not close enough -- subdivide the
+ // rectangle
+ } else {
+
+ // colors[0] colorM0 colors[2]
+ // (x0,y0) (xM,y0) (x1,y0)
+ // +----------+----------+
+ // | | |
+ // | UL | UR |
+ // color0M | colorMM | color1M
+ // (x0,yM) +----------+----------+ (x1,yM)
+ // | (xM,yM) |
+ // | LL | LR |
+ // | | |
+ // +----------+----------+
+ // colors[1] colorM1 colors[3]
+ // (x0,y1) (xM,y1) (x1,y1)
+
+ shading->getColor(x0, yM, &color0M);
+ shading->getColor(x1, yM, &color1M);
+ shading->getColor(xM, y0, &colorM0);
+ shading->getColor(xM, y1, &colorM1);
+ shading->getColor(xM, yM, &colorMM);
+
+ // upper-left sub-rectangle
+ colors2[0] = colors[0];
+ colors2[1] = color0M;
+ colors2[2] = colorM0;
+ colors2[3] = colorMM;
+ doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1);
+
+ // lower-left sub-rectangle
+ colors2[0] = color0M;
+ colors2[1] = colors[1];
+ colors2[2] = colorMM;
+ colors2[3] = colorM1;
+ doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1);
+
+ // upper-right sub-rectangle
+ colors2[0] = colorM0;
+ colors2[1] = colorMM;
+ colors2[2] = colors[2];
+ colors2[3] = color1M;
+ doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1);
+
+ // lower-right sub-rectangle
+ colors2[0] = colorMM;
+ colors2[1] = colorM1;
+ colors2[2] = color1M;
+ colors2[3] = colors[3];
+ doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1);
+ }
+}
+
void Gfx::doAxialShFill(GfxAxialShading *shading) {
double xMin, yMin, xMax, yMax;
double x0, y0, x1, y1;
@@ -1461,11 +1742,14 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
// difference across a region is small enough, and then the region
// is painted with a single color.
- // set up
+ // set up: require at least one split to avoid problems when the two
+ // ends of the t axis have the same color
nComps = shading->getColorSpace()->getNComps();
ta[0] = tMin;
+ next[0] = axialMaxSplits / 2;
+ ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax);
+ next[axialMaxSplits / 2] = axialMaxSplits;
ta[axialMaxSplits] = tMax;
- next[0] = axialMaxSplits;
// compute the color at t = tMin
if (tMin < 0) {
@@ -1730,7 +2014,9 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
// go as far along the t axis (toward t1) as we can, such that the
// color difference is within the tolerance (radialColorDelta) --
// this uses bisection (between the current value, t, and t1),
- // limited to radialMaxSplits points along the t axis
+ // limited to radialMaxSplits points along the t axis; require at
+ // least one split to avoid problems when the innermost and
+ // outermost colors are the same
ib = radialMaxSplits;
sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin);
tb = t0 + sb * (t1 - t0);
@@ -1747,7 +2033,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
break;
}
}
- if (k == nComps) {
+ if (k == nComps && ib < radialMaxSplits) {
break;
}
ib = (ia + ib) / 2;
@@ -1806,7 +2092,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
}
void Gfx::doEndPath() {
- if (state->isPath() && clip != clipNone) {
+ if (state->isCurPt() && clip != clipNone) {
state->clip();
if (clip == clipNormal) {
out->clip(state);
@@ -1843,6 +2129,7 @@ void Gfx::opBeginText(Object args[], int numArgs) {
}
void Gfx::opEndText(Object args[], int numArgs) {
+ out->endTextObject(state);
}
//------------------------------------------------------------------------
@@ -2019,7 +2306,7 @@ void Gfx::doShowText(GString *s) {
double riseX, riseY;
CharCode code;
Unicode u[8];
- double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy;
+ double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY;
double originX, originY, tOriginX, tOriginY;
double oldCTM[6], newCTM[6];
double *mat;
@@ -2057,12 +2344,16 @@ void Gfx::doShowText(GString *s) {
newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
newCTM[0] *= state->getFontSize();
+ newCTM[1] *= state->getFontSize();
+ newCTM[2] *= state->getFontSize();
newCTM[3] *= state->getFontSize();
newCTM[0] *= state->getHorizScaling();
newCTM[2] *= state->getHorizScaling();
state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
curX = state->getCurX();
curY = state->getCurY();
+ lineX = state->getLineX();
+ lineY = state->getLineY();
oldParser = parser;
p = s->getCString();
len = s->getLength();
@@ -2078,11 +2369,11 @@ void Gfx::doShowText(GString *s) {
dy *= state->getFontSize();
state->textTransformDelta(dx, dy, &tdx, &tdy);
state->transform(curX + riseX, curY + riseY, &x, &y);
- out->saveState(state);
- state = state->save();
+ saveState();
state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
//~ out->updateCTM(???)
- if (!out->beginType3Char(state, code, u, uLen)) {
+ if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy,
+ code, u, uLen)) {
((Gfx8BitFont *)font)->getCharProc(code, &charProc);
if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
pushResources(resDict);
@@ -2098,13 +2389,13 @@ void Gfx::doShowText(GString *s) {
}
charProc.free();
}
- state = state->restore();
- out->restoreState(state);
+ restoreState();
// GfxState::restore() does *not* restore the current position,
- // so we track it here with (curX, curY)
+ // so we deal with it here using (curX, curY) and (lineX, lineY)
curX += tdx;
curY += tdy;
state->moveTo(curX, curY);
+ state->textSetPos(lineX, lineY);
p += n;
len -= n;
}
@@ -2291,9 +2582,13 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
obj1.free();
dict->lookup("BPC", &obj1);
}
- if (!obj1.isInt())
+ if (obj1.isInt()) {
+ bits = obj1.getInt();
+ } else if (mask) {
+ bits = 1;
+ } else {
goto err2;
- bits = obj1.getInt();
+ }
obj1.free();
// display a mask
@@ -2397,6 +2692,11 @@ void Gfx::doForm(Object *str) {
Object obj1;
int i;
+ // check for excessive recursion
+ if (formDepth > 20) {
+ return;
+ }
+
// get stream dict
dict = str->streamGetDict();
@@ -2442,7 +2742,9 @@ void Gfx::doForm(Object *str) {
resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
// draw it
+ ++formDepth;
doForm1(str, resDict, m, bbox);
+ --formDepth;
resObj.free();
}
@@ -2570,8 +2872,10 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
pushResources(resDict);
// save current graphics state
- out->saveState(state);
- state = state->save();
+ saveState();
+
+ // kill any pre-existing path
+ state->clearPath();
// save current parser
oldParser = parser;
@@ -2610,8 +2914,7 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
parser = oldParser;
// restore graphics state
- state = state->restore();
- out->restoreState(state);
+ restoreState();
// pop resource stack
popResources();
@@ -2619,18 +2922,6 @@ void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
return;
}
-void Gfx::pushResources(Dict *resDict) {
- res = new GfxResources(xref, resDict, res);
-}
-
-void Gfx::popResources() {
- GfxResources *resPtr;
-
- resPtr = res->getNext();
- delete res;
- res = resPtr;
-}
-
//------------------------------------------------------------------------
// in-line image operators
//------------------------------------------------------------------------
@@ -2691,7 +2982,7 @@ Stream *Gfx::buildImageStream() {
obj.free();
// make stream
- str = new EmbedStream(parser->getStream(), &dict);
+ str = new EmbedStream(parser->getStream(), &dict, gFalse, 0);
str = str->addFilters(&dict);
return str;
@@ -2758,3 +3049,29 @@ void Gfx::opMarkPoint(Object args[], int numArgs) {
fflush(stdout);
}
}
+
+//------------------------------------------------------------------------
+// misc
+//------------------------------------------------------------------------
+
+void Gfx::saveState() {
+ out->saveState(state);
+ state = state->save();
+}
+
+void Gfx::restoreState() {
+ state = state->restore();
+ out->restoreState(state);
+}
+
+void Gfx::pushResources(Dict *resDict) {
+ res = new GfxResources(xref, resDict, res);
+}
+
+void Gfx::popResources() {
+ GfxResources *resPtr;
+
+ resPtr = res->getNext();
+ delete res;
+ res = resPtr;
+}
diff --git a/pdf2swf/xpdf/Gfx.h b/pdf2swf/xpdf/Gfx.h
index b4da531c..2e40a573 100644
--- a/pdf2swf/xpdf/Gfx.h
+++ b/pdf2swf/xpdf/Gfx.h
@@ -2,14 +2,16 @@
//
// Gfx.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GFX_H
#define GFX_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -25,12 +27,16 @@ class OutputDev;
class GfxFontDict;
class GfxFont;
class GfxPattern;
+class GfxTilingPattern;
+class GfxShadingPattern;
class GfxShading;
+class GfxFunctionShading;
class GfxAxialShading;
class GfxRadialShading;
class GfxState;
+struct GfxColor;
class Gfx;
-struct PDFRectangle;
+class PDFRectangle;
//------------------------------------------------------------------------
// Gfx
@@ -94,13 +100,17 @@ class Gfx {
public:
// Constructor for regular output.
- Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
- PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
- GBool printCommandsA);
+ Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
+ double hDPI, double vDPI, PDFRectangle *box, GBool crop,
+ PDFRectangle *cropBox, int rotate,
+ GBool (*abortCheckCbkA)(void *data) = NULL,
+ void *abortCheckCbkDataA = NULL);
// Constructor for a sub-page object.
Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
- PDFRectangle *box, GBool crop, PDFRectangle *cropBox);
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox,
+ GBool (*abortCheckCbkA)(void *data) = NULL,
+ void *abortCheckCbkDataA = NULL);
~Gfx();
@@ -112,8 +122,11 @@ public:
void doAnnot(Object *str, double xMin, double yMin,
double xMax, double yMax);
- void pushResources(Dict *resDict);
- void popResources();
+ // Save graphics state.
+ void saveState();
+
+ // Restore graphics state.
+ void restoreState();
private:
@@ -130,9 +143,14 @@ private:
int ignoreUndef; // current BX/EX nesting level
double baseMatrix[6]; // default matrix for most recent
// page/form/pattern
+ int formDepth;
Parser *parser; // parser for page content stream(s)
+ GBool // callback to check for an abort
+ (*abortCheckCbk)(void *data);
+ void *abortCheckCbkData;
+
static Operator opTab[]; // table of operators
void go(GBool topLevel);
@@ -188,7 +206,14 @@ private:
void opEOFillStroke(Object args[], int numArgs);
void opCloseEOFillStroke(Object args[], int numArgs);
void doPatternFill(GBool eoFill);
+ void doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill);
+ void doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill);
void opShFill(Object args[], int numArgs);
+ void doFunctionShFill(GfxFunctionShading *shading);
+ void doFunctionShFill1(GfxFunctionShading *shading,
+ double x0, double y0,
+ double x1, double y1,
+ GfxColor *colors, int depth);
void doAxialShFill(GfxAxialShading *shading);
void doRadialShFill(GfxRadialShading *shading);
void doEndPath();
@@ -247,6 +272,9 @@ private:
void opBeginMarkedContent(Object args[], int numArgs);
void opEndMarkedContent(Object args[], int numArgs);
void opMarkPoint(Object args[], int numArgs);
+
+ void pushResources(Dict *resDict);
+ void popResources();
};
#endif
diff --git a/pdf2swf/xpdf/GfxFont.cc b/pdf2swf/xpdf/GfxFont.cc
index 8dcd8e78..ed9f076d 100644
--- a/pdf2swf/xpdf/GfxFont.cc
+++ b/pdf2swf/xpdf/GfxFont.cc
@@ -2,15 +2,16 @@
//
// GfxFont.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -24,7 +25,9 @@
#include "CharCodeToUnicode.h"
#include "FontEncodingTables.h"
#include "BuiltinFontTables.h"
-#include "FontFile.h"
+#include "FoFiType1.h"
+#include "FoFiType1C.h"
+#include "FoFiTrueType.h"
#include "GfxFont.h"
//------------------------------------------------------------------------
@@ -34,6 +37,11 @@ struct StdFontMapEntry {
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" },
@@ -65,6 +73,9 @@ static StdFontMapEntry stdFontMap[] = {
{ "Helvetica,Italic", "Helvetica-Oblique" },
{ "Helvetica-BoldItalic", "Helvetica-BoldOblique" },
{ "Helvetica-Italic", "Helvetica-Oblique" },
+ { "Symbol,Bold", "Symbol" },
+ { "Symbol,BoldItalic", "Symbol" },
+ { "Symbol,Italic", "Symbol" },
{ "TimesNewRoman", "Times-Roman" },
{ "TimesNewRoman,Bold", "Times-Bold" },
{ "TimesNewRoman,BoldItalic", "Times-BoldItalic" },
@@ -79,7 +90,10 @@ static StdFontMapEntry stdFontMap[] = {
{ "TimesNewRomanPS-BoldMT", "Times-Bold" },
{ "TimesNewRomanPS-Italic", "Times-Italic" },
{ "TimesNewRomanPS-ItalicMT", "Times-Italic" },
- { "TimesNewRomanPSMT", "Times-Roman" }
+ { "TimesNewRomanPSMT", "Times-Roman" },
+ { "TimesNewRomanPSMT,Bold", "Times-Bold" },
+ { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
+ { "TimesNewRomanPSMT,Italic", "Times-Italic" }
};
//------------------------------------------------------------------------
@@ -127,12 +141,16 @@ GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) {
tag = new GString(tagA);
id = idA;
name = nameA;
+ origName = nameA;
embFontName = NULL;
extFontFile = NULL;
}
GfxFont::~GfxFont() {
delete tag;
+ if (origName && origName != name) {
+ delete origName;
+ }
if (name) {
delete name;
}
@@ -255,6 +273,10 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
if (t != 0) {
descent = t;
}
+ // some broken font descriptors specify a positive descent
+ if (descent > 0) {
+ descent = -descent;
+ }
}
obj2.free();
@@ -273,8 +295,8 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
obj1.free();
}
-CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits) {
- CharCodeToUnicode *ctu;
+CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
+ CharCodeToUnicode *ctu) {
GString *buf;
Object obj1;
int c;
@@ -290,17 +312,24 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits) {
}
obj1.streamClose();
obj1.free();
- ctu = CharCodeToUnicode::parseCMap(buf, nBits);
+ if (ctu) {
+ ctu->mergeCMap(buf, nBits);
+ } else {
+ ctu = CharCodeToUnicode::parseCMap(buf, nBits);
+ }
delete buf;
return ctu;
}
void GfxFont::findExtFontFile() {
+ static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
+ static 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);
}
}
}
@@ -318,7 +347,8 @@ char *GfxFont::readExtFontFile(int *len) {
fseek(f, 0, SEEK_SET);
buf = (char *)gmalloc(*len);
if ((int)fread(buf, 1, *len, f) != *len) {
- error(-1, "Error reading external font file '%s'", extFontFile);
+ error(-1, "Error reading external font file '%s'",
+ extFontFile->getCString());
}
fclose(f);
return buf;
@@ -374,11 +404,14 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
GBool baseEncFromFontFile;
char *buf;
int len;
- FontFile *fontFile;
+ FoFiType1 *ffT1;
+ FoFiType1C *ffT1C;
int code, code2;
char *charName;
GBool missing, hex;
Unicode toUnicode[256];
+ CharCodeToUnicode *utu, *ctu2;
+ Unicode uBuf[8];
double mul;
int firstChar, lastChar;
Gushort w;
@@ -388,10 +421,8 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, 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);
@@ -405,7 +436,6 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
}
if (!name->cmp(stdFontMap[a].altName)) {
- delete name;
name = new GString(stdFontMap[a].properName);
}
}
@@ -490,6 +520,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// check FontDict for base encoding
hasEncoding = gFalse;
+ usesMacRomanEnc = gFalse;
baseEnc = NULL;
baseEncFromFontFile = gFalse;
fontDict->lookup("Encoding", &obj1);
@@ -497,6 +528,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
obj1.dictLookup("BaseEncoding", &obj2);
if (obj2.isName("MacRomanEncoding")) {
hasEncoding = gTrue;
+ usesMacRomanEnc = gTrue;
baseEnc = macRomanEncoding;
} else if (obj2.isName("MacExpertEncoding")) {
hasEncoding = gTrue;
@@ -511,6 +543,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
obj2.free();
} else if (obj1.isName("MacRomanEncoding")) {
hasEncoding = gTrue;
+ usesMacRomanEnc = gTrue;
baseEnc = macRomanEncoding;
} else if (obj1.isName("MacExpertEncoding")) {
hasEncoding = gTrue;
@@ -526,46 +559,59 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// check embedded or external font file for base encoding
// (only for Type 1 fonts - trying to get an encoding out of a
// TrueType font is a losing proposition)
- fontFile = NULL;
+ ffT1 = NULL;
+ ffT1C = NULL;
buf = NULL;
- if ((type == fontType1 || type == fontType1C) &&
- (extFontFile || embFontID.num >= 0)) {
+ if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
if (extFontFile) {
- buf = readExtFontFile(&len);
+ ffT1 = FoFiType1::load(extFontFile->getCString());
} else {
buf = readEmbFontFile(xref, &len);
+ ffT1 = FoFiType1::make(buf, len);
}
- if (buf) {
- if (type == fontType1C && !strncmp(buf, "%!", 2)) {
- // various tools (including Adobe's) occasionally embed Type 1
- // fonts but label them Type 1C
- type = fontType1;
+ if (ffT1) {
+ if (ffT1->getName()) {
+ if (embFontName) {
+ delete embFontName;
+ }
+ embFontName = new GString(ffT1->getName());
}
- if (type == fontType1) {
- fontFile = new Type1FontFile(buf, len);
- } else {
- fontFile = new Type1CFontFile(buf, len);
+ if (!baseEnc) {
+ baseEnc = ffT1->getEncoding();
+ baseEncFromFontFile = gTrue;
}
- if (fontFile->getName()) {
+ }
+ } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
+ if (extFontFile) {
+ ffT1C = FoFiType1C::load(extFontFile->getCString());
+ } else {
+ buf = readEmbFontFile(xref, &len);
+ ffT1C = FoFiType1C::make(buf, len);
+ }
+ if (ffT1C) {
+ if (ffT1C->getName()) {
if (embFontName) {
delete embFontName;
}
- embFontName = new GString(fontFile->getName());
+ embFontName = new GString(ffT1C->getName());
}
if (!baseEnc) {
- baseEnc = fontFile->getEncoding();
+ baseEnc = ffT1C->getEncoding();
baseEncFromFontFile = gTrue;
}
- gfree(buf);
}
}
+ if (buf) {
+ gfree(buf);
+ }
// get default base encoding
if (!baseEnc) {
if (builtinFont) {
baseEnc = builtinFont->defaultBaseEnc;
+ hasEncoding = gTrue;
} else if (type == fontTrueType) {
- baseEnc = macRomanEncoding;
+ baseEnc = winAnsiEncoding;
} else {
baseEnc = standardEncoding;
}
@@ -579,6 +625,20 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
}
+ // some Type 1C font files have empty encodings, which can break the
+ // T1C->T1 conversion (since the 'seac' operator depends on having
+ // the accents in the encoding), so we fill in any gaps from
+ // StandardEncoding
+ if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
+ baseEncFromFontFile) {
+ for (i = 0; i < 256; ++i) {
+ if (!enc[i] && standardEncoding[i]) {
+ enc[i] = standardEncoding[i];
+ encFree[i] = gFalse;
+ }
+ }
+ }
+
// merge differences into encoding
if (obj1.isDict()) {
obj1.dictLookup("Differences", &obj2);
@@ -590,7 +650,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
if (obj3.isInt()) {
code = obj3.getInt();
} else if (obj3.isName()) {
- if (code < 256) {
+ if (code >= 0 && code < 256) {
if (encFree[code]) {
gfree(enc[code]);
}
@@ -608,82 +668,106 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
obj2.free();
}
obj1.free();
- if (fontFile) {
- delete fontFile;
+ if (ffT1) {
+ delete ffT1;
+ }
+ if (ffT1C) {
+ delete ffT1C;
}
//----- build the mapping to Unicode -----
- // look for a ToUnicode CMap
- if (!(ctu = readToUnicodeCMap(fontDict, 8))) {
-
- // no ToUnicode CMap, so use the char names
+ // pass 1: use the name-to-Unicode mapping table
+ missing = hex = gFalse;
+ for (code = 0; code < 256; ++code) {
+ if ((charName = enc[code])) {
+ if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
+ strcmp(charName, ".notdef")) {
+ // if it wasn't in the name-to-Unicode table, check for a
+ // name that looks like 'Axx' or 'xx', where 'A' is any letter
+ // and 'xx' is two hex digits
+ if ((strlen(charName) == 3 &&
+ isalpha(charName[0]) &&
+ isxdigit(charName[1]) && isxdigit(charName[2]) &&
+ ((charName[1] >= 'a' && charName[1] <= 'f') ||
+ (charName[1] >= 'A' && charName[1] <= 'F') ||
+ (charName[2] >= 'a' && charName[2] <= 'f') ||
+ (charName[2] >= 'A' && charName[2] <= 'F'))) ||
+ (strlen(charName) == 2 &&
+ isxdigit(charName[0]) && isxdigit(charName[1]) &&
+ ((charName[0] >= 'a' && charName[0] <= 'f') ||
+ (charName[0] >= 'A' && charName[0] <= 'F') ||
+ (charName[1] >= 'a' && charName[1] <= 'f') ||
+ (charName[1] >= 'A' && charName[1] <= 'F')))) {
+ hex = gTrue;
+ }
+ missing = gTrue;
+ }
+ } else {
+ toUnicode[code] = 0;
+ }
+ }
- // pass 1: use the name-to-Unicode mapping table
- missing = hex = gFalse;
+ // pass 2: try to fill in the missing chars, looking for names of
+ // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
+ // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
+ // decimal digits
+ if (missing && globalParams->getMapNumericCharNames()) {
for (code = 0; code < 256; ++code) {
- if ((charName = enc[code])) {
- if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
- strcmp(charName, ".notdef")) {
- // if it wasn't in the name-to-Unicode table, check for a
- // name that looks like 'Axx' or 'xx', where 'A' is any letter
- // and 'xx' is two hex digits
- if ((strlen(charName) == 3 &&
- isalpha(charName[0]) &&
- isxdigit(charName[1]) && isxdigit(charName[2]) &&
- ((charName[1] >= 'a' && charName[1] <= 'f') ||
- (charName[1] >= 'A' && charName[1] <= 'F') ||
- (charName[2] >= 'a' && charName[2] <= 'f') ||
- (charName[2] >= 'A' && charName[2] <= 'F'))) ||
- (strlen(charName) == 2 &&
- isxdigit(charName[0]) && isxdigit(charName[1]) &&
- ((charName[0] >= 'a' && charName[0] <= 'f') ||
- (charName[0] >= 'A' && charName[0] <= 'F') ||
- (charName[1] >= 'a' && charName[1] <= 'f') ||
- (charName[1] >= 'A' && charName[1] <= 'F')))) {
- hex = gTrue;
- }
- missing = gTrue;
+ if ((charName = enc[code]) && !toUnicode[code] &&
+ strcmp(charName, ".notdef")) {
+ n = strlen(charName);
+ code2 = -1;
+ if (hex && n == 3 && isalpha(charName[0]) &&
+ isxdigit(charName[1]) && isxdigit(charName[2])) {
+ sscanf(charName+1, "%x", &code2);
+ } else if (hex && n == 2 &&
+ isxdigit(charName[0]) && isxdigit(charName[1])) {
+ sscanf(charName, "%x", &code2);
+ } else if (!hex && n >= 2 && n <= 4 &&
+ isdigit(charName[0]) && isdigit(charName[1])) {
+ code2 = atoi(charName);
+ } else if (n >= 3 && n <= 5 &&
+ isdigit(charName[1]) && isdigit(charName[2])) {
+ code2 = atoi(charName+1);
+ } else if (n >= 4 && n <= 6 &&
+ isdigit(charName[2]) && isdigit(charName[3])) {
+ code2 = atoi(charName+2);
+ }
+ if (code2 >= 0 && code2 <= 0xff) {
+ toUnicode[code] = (Unicode)code2;
}
- } else {
- toUnicode[code] = 0;
}
}
+ }
- // pass 2: try to fill in the missing chars, looking for names of
- // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
- // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
- // decimal digits
- if (missing && globalParams->getMapNumericCharNames()) {
- for (code = 0; code < 256; ++code) {
- if ((charName = enc[code]) && !toUnicode[code] &&
- strcmp(charName, ".notdef")) {
- n = strlen(charName);
- code2 = -1;
- if (hex && n == 3 && isalpha(charName[0]) &&
- isxdigit(charName[1]) && isxdigit(charName[2])) {
- sscanf(charName+1, "%x", &code2);
- } else if (hex && n == 2 &&
- isxdigit(charName[0]) && isxdigit(charName[1])) {
- sscanf(charName, "%x", &code2);
- } else if (!hex && n >= 2 && n <= 4 &&
- isdigit(charName[0]) && isdigit(charName[1])) {
- code2 = atoi(charName);
- } else if (n >= 3 && n <= 5 &&
- isdigit(charName[1]) && isdigit(charName[2])) {
- code2 = atoi(charName+1);
- } else if (n >= 4 && n <= 6 &&
- isdigit(charName[2]) && isdigit(charName[3])) {
- code2 = atoi(charName+2);
- }
- if (code2 >= 0 && code2 <= 0xff) {
- toUnicode[code] = (Unicode)code2;
- }
+ // construct the char code -> Unicode mapping object
+ ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
+
+ // merge in a ToUnicode CMap, if there is one -- this overwrites
+ // existing entries in ctu, i.e., the ToUnicode CMap takes
+ // precedence, but the other encoding info is allowed to fill in any
+ // holes
+ readToUnicodeCMap(fontDict, 8, ctu);
+
+ // look for a Unicode-to-Unicode mapping
+ if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
+ for (i = 0; i < 256; ++i) {
+ toUnicode[i] = 0;
+ }
+ ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
+ for (i = 0; i < 256; ++i) {
+ n = ctu->mapToUnicode((CharCode)i, uBuf, 8);
+ if (n >= 1) {
+ n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
+ if (n >= 1) {
+ ctu2->setMapping((CharCode)i, uBuf, n);
}
}
}
-
- ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
+ utu->decRefCnt();
+ delete ctu;
+ ctu = ctu2;
}
//----- get the character widths -----
@@ -697,13 +781,22 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
fontDict->lookup("FirstChar", &obj1);
firstChar = obj1.isInt() ? obj1.getInt() : 0;
obj1.free();
+ if (firstChar < 0 || firstChar > 255) {
+ firstChar = 0;
+ }
fontDict->lookup("LastChar", &obj1);
lastChar = obj1.isInt() ? obj1.getInt() : 255;
obj1.free();
+ if (lastChar < 0 || lastChar > 255) {
+ lastChar = 255;
+ }
mul = (type == fontType3) ? fontMat[0] : 0.001;
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()) {
@@ -797,12 +890,126 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
return ctu;
}
+Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
+ Gushort *map;
+ int cmapPlatform, cmapEncoding;
+ int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
+ GBool useMacRoman, useUnicode;
+ char *charName;
+ Unicode u;
+ int code, i, n;
+
+ map = (Gushort *)gmalloc(256 * sizeof(Gushort));
+ for (i = 0; i < 256; ++i) {
+ map[i] = 0;
+ }
+
+ // To match up with the Adobe-defined behaviour, we choose a cmap
+ // like this:
+ // 1. If the PDF font has an encoding:
+ // 1a. If the PDF font specified MacRomanEncoding and the
+ // TrueType font has a Macintosh Roman cmap, use it, and
+ // reverse map the char names through MacRomanEncoding to
+ // get char codes.
+ // 1b. If the TrueType font has a Microsoft Unicode cmap or a
+ // non-Microsoft Unicode cmap, use it, and use the Unicode
+ // indexes, not the char codes.
+ // 1c. If the PDF font is symbolic and the TrueType font has a
+ // Microsoft Symbol cmap, use it, and use char codes
+ // directly (possibly with an offset of 0xf000).
+ // 1d. If the TrueType font has a Macintosh Roman cmap, use it,
+ // as in case 1a.
+ // 2. If the PDF font does not have an encoding:
+ // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
+ // and use char codes directly (possibly with an offset of
+ // 0xf000).
+ // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
+ // and use char codes directly (possible with an offset of
+ // 0xf000).
+ // 3. If none of these rules apply, use the first cmap and hope for
+ // the best (this shouldn't happen).
+ unicodeCmap = macRomanCmap = msSymbolCmap = -1;
+ for (i = 0; i < ff->getNumCmaps(); ++i) {
+ cmapPlatform = ff->getCmapPlatform(i);
+ cmapEncoding = ff->getCmapEncoding(i);
+ if ((cmapPlatform == 3 && cmapEncoding == 1) ||
+ cmapPlatform == 0) {
+ unicodeCmap = i;
+ } else if (cmapPlatform == 1 && cmapEncoding == 0) {
+ macRomanCmap = i;
+ } else if (cmapPlatform == 3 && cmapEncoding == 0) {
+ msSymbolCmap = i;
+ }
+ }
+ cmap = 0;
+ useMacRoman = gFalse;
+ useUnicode = gFalse;
+ if (hasEncoding) {
+ if (usesMacRomanEnc && macRomanCmap >= 0) {
+ cmap = macRomanCmap;
+ useMacRoman = gTrue;
+ } else if (unicodeCmap >= 0) {
+ cmap = unicodeCmap;
+ useUnicode = gTrue;
+ } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
+ cmap = msSymbolCmap;
+ } else if (macRomanCmap >= 0) {
+ cmap = macRomanCmap;
+ useMacRoman = gTrue;
+ }
+ } else {
+ if (macRomanCmap >= 0) {
+ cmap = macRomanCmap;
+ } else if (msSymbolCmap >= 0) {
+ cmap = msSymbolCmap;
+ }
+ }
+
+ // reverse map the char names through MacRomanEncoding, then map the
+ // char codes through the cmap
+ if (useMacRoman) {
+ for (i = 0; i < 256; ++i) {
+ if ((charName = enc[i])) {
+ if ((code = globalParams->getMacRomanCharCode(charName))) {
+ map[i] = ff->mapCodeToGID(cmap, code);
+ }
+ }
+ }
+
+ // map Unicode through the cmap
+ } else if (useUnicode) {
+ for (i = 0; i < 256; ++i) {
+ if ((n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
+ map[i] = ff->mapCodeToGID(cmap, u);
+ }
+ }
+
+ // map the char codes through the cmap, possibly with an offset of
+ // 0xf000
+ } else {
+ for (i = 0; i < 256; ++i) {
+ if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
+ map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
+ }
+ }
+ }
+
+ // try the TrueType 'post' table to handle any unmapped characters
+ for (i = 0; i < 256; ++i) {
+ if (!map[i] && (charName = enc[i])) {
+ map[i] = (Gushort)(int)ff->mapNameToGID(charName);
+ }
+ }
+
+ return map;
+}
+
Dict *Gfx8BitFont::getCharProcs() {
return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
}
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
- if (charProcs.isDict()) {
+ if (enc[code] && charProcs.isDict()) {
charProcs.dictLookup(enc[code], proc);
} else {
proc->initNull();
@@ -818,12 +1025,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;
}
@@ -908,7 +1115,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
obj1.free();
// look for a ToUnicode CMap
- if (!(ctu = readToUnicodeCMap(fontDict, 16))) {
+ if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
// the "Adobe-Identity" and "Adobe-UCS" collections don't have
// cidToUnicode files
@@ -947,7 +1154,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// CIDToGIDMap (for embedded TrueType fonts)
if (type == fontCIDType2) {
- fontDict->lookup("CIDToGIDMap", &obj1);
+ desFontDict->lookup("CIDToGIDMap", &obj1);
if (obj1.isStream()) {
cidToGIDLen = 0;
i = 64;
@@ -1036,11 +1243,11 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
if (desFontDict->lookup("DW2", &obj1)->isArray() &&
obj1.arrayGetLength() == 2) {
if (obj1.arrayGet(0, &obj2)->isNum()) {
- widths.defVY = obj1.getNum() * 0.001;
+ widths.defVY = obj2.getNum() * 0.001;
}
obj2.free();
if (obj1.arrayGet(1, &obj2)->isNum()) {
- widths.defHeight = obj1.getNum() * 0.001;
+ widths.defHeight = obj2.getNum() * 0.001;
}
obj2.free();
}
@@ -1051,8 +1258,8 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
excepsSize = 0;
i = 0;
while (i + 1 < obj1.arrayGetLength()) {
- obj1.arrayGet(0, &obj2);
- obj2.arrayGet(0, &obj3);
+ obj1.arrayGet(i, &obj2);
+ obj1.arrayGet(i+ 1, &obj3);
if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
obj1.arrayGet(i + 3, &obj5)->isNum() &&
@@ -1085,10 +1292,10 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
excepsSize * sizeof(GfxFontCIDWidthExcepV));
}
j = obj2.getInt();
- for (k = 0; k < obj3.arrayGetLength(); ++k) {
+ for (k = 0; k < obj3.arrayGetLength(); k += 3) {
if (obj3.arrayGet(k, &obj4)->isNum() &&
- obj3.arrayGet(k, &obj5)->isNum() &&
- obj3.arrayGet(k, &obj6)->isNum()) {
+ obj3.arrayGet(k+1, &obj5)->isNum() &&
+ obj3.arrayGet(k+2, &obj6)->isNum()) {
widths.excepsV[widths.nExceps].first = j;
widths.excepsV[widths.nExceps].last = j;
widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001;
@@ -1225,7 +1432,9 @@ int GfxCIDFont::getWMode() {
}
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
- ctu->incRefCnt();
+ if (ctu) {
+ ctu->incRefCnt();
+ }
return ctu;
}
@@ -1237,24 +1446,38 @@ GString *GfxCIDFont::getCollection() {
// GfxFontDict
//------------------------------------------------------------------------
-GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) {
+GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
int i;
Object obj1, obj2;
+ Ref r;
numFonts = fontDict->getLength();
fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
for (i = 0; i < numFonts; ++i) {
fontDict->getValNF(i, &obj1);
obj1.fetch(xref, &obj2);
- if (obj1.isRef() && obj2.isDict()) {
+ if (obj2.isDict()) {
+ if (obj1.isRef()) {
+ r = obj1.getRef();
+ } else {
+ // no indirect reference for this font, so invent a unique one
+ // (legal generation numbers are five digits, so any 6-digit
+ // number would be safe)
+ r.num = i;
+ if (fontDictRef) {
+ r.gen = 100000 + fontDictRef->num;
+ } else {
+ r.gen = 999999;
+ }
+ }
fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
- obj1.getRef(), obj2.getDict());
+ r, obj2.getDict());
if (fonts[i] && !fonts[i]->isOk()) {
delete fonts[i];
fonts[i] = NULL;
}
} else {
- error(-1, "font resource is not a dictionary reference");
+ error(-1, "font resource is not a dictionary");
fonts[i] = NULL;
}
obj1.free();
diff --git a/pdf2swf/xpdf/GfxFont.h b/pdf2swf/xpdf/GfxFont.h
index edd26e5f..62dfd088 100644
--- a/pdf2swf/xpdf/GfxFont.h
+++ b/pdf2swf/xpdf/GfxFont.h
@@ -2,14 +2,16 @@
//
// GfxFont.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GFXFONT_H
#define GFXFONT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -21,6 +23,7 @@
class Dict;
class CMap;
class CharCodeToUnicode;
+class FoFiTrueType;
struct GfxFontCIDWidths;
//------------------------------------------------------------------------
@@ -102,6 +105,10 @@ public:
// Get base font name.
GString *getName() { return name; }
+ // Get the original font name (ignornig any munging that might have
+ // been done to map to a canonical Base-14 font name).
+ GString *getOrigName() { return origName; }
+
// Get font type.
GfxFontType getType() { return type; }
virtual GBool isCIDFont() { return gFalse; }
@@ -156,12 +163,14 @@ public:
protected:
void readFontDescriptor(XRef *xref, Dict *fontDict);
- CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits);
+ CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits,
+ CharCodeToUnicode *ctu);
void findExtFontFile();
GString *tag; // PDF font tag
Ref id; // reference (used as unique ID)
GString *name; // font name
+ GString *origName; // original font name
GfxFontType type; // type of font
int flags; // font descriptor flags
GString *embFontName; // name of embedded font
@@ -198,14 +207,21 @@ public:
CharCodeToUnicode *getToUnicode();
// Return the character name associated with <code>.
- char *getCharName(int code) { return code>=256?0:enc[code]; }
+ char *getCharName(int code) { return enc[code]; }
// Returns true if the PDF font specified an encoding.
GBool getHasEncoding() { return hasEncoding; }
- // Get width of a character or string.
+ // Returns true if the PDF font specified MacRomanEncoding.
+ GBool getUsesMacRomanEnc() { return usesMacRomanEnc; }
+
+ // Get width of a character.
double getWidth(Guchar c) { return widths[c]; }
+ // Return a char code-to-GID mapping for the provided font file.
+ // (This is only useful for TrueType fonts.)
+ Gushort *getCodeToGIDMap(FoFiTrueType *ff);
+
// Return the Type 3 CharProc dictionary, or NULL if none.
Dict *getCharProcs();
@@ -222,6 +238,7 @@ private:
// the string is malloc'ed
CharCodeToUnicode *ctu; // char code --> Unicode
GBool hasEncoding;
+ GBool usesMacRomanEnc;
double widths[256]; // character widths
Object charProcs; // Type 3 CharProcs dictionary
Object resources; // Type 3 Resources dictionary
@@ -277,7 +294,7 @@ class GfxFontDict {
public:
// Build the font dictionary, given the PDF font dictionary.
- GfxFontDict(XRef *xref, Dict *fontDict);
+ GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict);
// Destructor.
~GfxFontDict();
diff --git a/pdf2swf/xpdf/GfxState.cc b/pdf2swf/xpdf/GfxState.cc
index d65bbbab..65a1da8e 100644
--- a/pdf2swf/xpdf/GfxState.cc
+++ b/pdf2swf/xpdf/GfxState.cc
@@ -2,15 +2,16 @@
//
// GfxState.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <math.h>
#include <string.h> // for memcpy()
@@ -28,6 +29,24 @@ static inline double clip01(double x) {
}
//------------------------------------------------------------------------
+
+static char *gfxColorSpaceModeNames[] = {
+ "DeviceGray",
+ "CalGray",
+ "DeviceRGB",
+ "CalRGB",
+ "DeviceCMYK",
+ "Lab",
+ "ICCBased",
+ "Indexed",
+ "Separation",
+ "DeviceN",
+ "Pattern"
+};
+
+#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
+
+//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
@@ -79,7 +98,7 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
} else if (obj1.isName("Pattern")) {
cs = GfxPatternColorSpace::parse(csObj->getArray());
} else {
- error(-1, "Bad color space '%s'", csObj->getName());
+ error(-1, "Bad color space");
}
obj1.free();
} else {
@@ -98,6 +117,14 @@ void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
}
}
+int GfxColorSpace::getNumColorSpaceModes() {
+ return nGfxColorSpaceModes;
+}
+
+char *GfxColorSpace::getColorSpaceModeName(int idx) {
+ return gfxColorSpaceModeNames[idx];
+}
+
//------------------------------------------------------------------------
// GfxDeviceGrayColorSpace
//------------------------------------------------------------------------
@@ -733,12 +760,18 @@ void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
double *decodeRange,
int maxImgPixel) {
+ alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel);
+
+#if 0
+ // this is nominally correct, but some PDF files don't set the
+ // correct ranges in the ICCBased dict
int i;
for (i = 0; i < nComps; ++i) {
decodeLow[i] = rangeMin[i];
decodeRange[i] = rangeMax[i] - rangeMin[i];
}
+#endif
}
//------------------------------------------------------------------------
@@ -788,9 +821,19 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
obj1.free();
if (!arr->get(2, &obj1)->isInt()) {
error(-1, "Bad Indexed color space (hival)");
+ delete baseA;
goto err2;
}
indexHighA = obj1.getInt();
+ if (indexHighA < 0 || indexHighA > 255) {
+ // the PDF spec requires indexHigh to be in [0,255] -- allowing
+ // values larger than 255 creates a security hole: if nComps *
+ // indexHigh is greater than 2^31, the loop below may overwrite
+ // past the end of the array
+ error(-1, "Bad Indexed color space (invalid indexHigh value)");
+ delete baseA;
+ goto err2;
+ }
obj1.free();
cs = new GfxIndexedColorSpace(baseA, indexHighA);
arr->get(3, &obj1);
@@ -833,43 +876,37 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
return NULL;
}
-void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
+GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color,
+ GfxColor *baseColor) {
Guchar *p;
- GfxColor color2;
+ double low[gfxColorMaxComps], range[gfxColorMaxComps];
int n, i;
n = base->getNComps();
+ base->getDefaultRanges(low, range, indexHigh);
p = &lookup[(int)(color->c[0] + 0.5) * n];
for (i = 0; i < n; ++i) {
- color2.c[i] = p[i] / 255.0;
+ baseColor->c[i] = low[i] + (p[i] / 255.0) * range[i];
}
- base->getGray(&color2, gray);
+ return baseColor;
+}
+
+void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ base->getGray(mapColorToBase(color, &color2), gray);
}
void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- Guchar *p;
GfxColor color2;
- int n, i;
- n = base->getNComps();
- p = &lookup[(int)(color->c[0] + 0.5) * n];
- for (i = 0; i < n; ++i) {
- color2.c[i] = p[i] / 255.0;
- }
- base->getRGB(&color2, rgb);
+ base->getRGB(mapColorToBase(color, &color2), rgb);
}
void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
- Guchar *p;
GfxColor color2;
- int n, i;
- n = base->getNComps();
- p = &lookup[(int)(color->c[0] + 0.5) * n];
- for (i = 0; i < n; ++i) {
- color2.c[i] = p[i] / 255.0;
- }
- base->getCMYK(&color2, cmyk);
+ base->getCMYK(mapColorToBase(color, &color2), cmyk);
}
void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
@@ -1016,6 +1053,11 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
goto err2;
}
nCompsA = obj1.arrayGetLength();
+ if (nCompsA > gfxColorMaxComps) {
+ error(-1, "DeviceN color space with more than %d > %d components",
+ nCompsA, gfxColorMaxComps);
+ nCompsA = gfxColorMaxComps;
+ }
for (i = 0; i < nCompsA; ++i) {
if (!obj1.arrayGet(i, &obj2)->isName()) {
error(-1, "Bad DeviceN color space (names)");
@@ -1144,18 +1186,22 @@ GfxPattern::~GfxPattern() {
GfxPattern *GfxPattern::parse(Object *obj) {
GfxPattern *pattern;
- Dict *dict;
Object obj1;
+ if (obj->isDict()) {
+ obj->dictLookup("PatternType", &obj1);
+ } else if (obj->isStream()) {
+ obj->streamGetDict()->lookup("PatternType", &obj1);
+ } else {
+ return NULL;
+ }
pattern = NULL;
- if (obj->isStream()) {
- dict = obj->streamGetDict();
- dict->lookup("PatternType", &obj1);
- if (obj1.isInt() && obj1.getInt() == 1) {
- pattern = new GfxTilingPattern(dict, obj);
- }
- obj1.free();
+ if (obj1.isInt() && obj1.getInt() == 1) {
+ pattern = GfxTilingPattern::parse(obj);
+ } else if (obj1.isInt() && obj1.getInt() == 2) {
+ pattern = GfxShadingPattern::parse(obj);
}
+ obj1.free();
return pattern;
}
@@ -1163,33 +1209,42 @@ GfxPattern *GfxPattern::parse(Object *obj) {
// GfxTilingPattern
//------------------------------------------------------------------------
-GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
- GfxPattern(1)
-{
+GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) {
+ GfxTilingPattern *pat;
+ Dict *dict;
+ int paintTypeA, tilingTypeA;
+ double bboxA[4], matrixA[6];
+ double xStepA, yStepA;
+ Object resDictA;
Object obj1, obj2;
int i;
- if (streamDict->lookup("PaintType", &obj1)->isInt()) {
- paintType = obj1.getInt();
+ if (!patObj->isStream()) {
+ return NULL;
+ }
+ dict = patObj->streamGetDict();
+
+ if (dict->lookup("PaintType", &obj1)->isInt()) {
+ paintTypeA = obj1.getInt();
} else {
- paintType = 1;
+ paintTypeA = 1;
error(-1, "Invalid or missing PaintType in pattern");
}
obj1.free();
- if (streamDict->lookup("TilingType", &obj1)->isInt()) {
- tilingType = obj1.getInt();
+ if (dict->lookup("TilingType", &obj1)->isInt()) {
+ tilingTypeA = obj1.getInt();
} else {
- tilingType = 1;
+ tilingTypeA = 1;
error(-1, "Invalid or missing TilingType in pattern");
}
obj1.free();
- bbox[0] = bbox[1] = 0;
- bbox[2] = bbox[3] = 1;
- if (streamDict->lookup("BBox", &obj1)->isArray() &&
+ bboxA[0] = bboxA[1] = 0;
+ bboxA[2] = bboxA[3] = 1;
+ if (dict->lookup("BBox", &obj1)->isArray() &&
obj1.arrayGetLength() == 4) {
for (i = 0; i < 4; ++i) {
if (obj1.arrayGet(i, &obj2)->isNum()) {
- bbox[i] = obj2.getNum();
+ bboxA[i] = obj2.getNum();
}
obj2.free();
}
@@ -1197,39 +1252,65 @@ GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
error(-1, "Invalid or missing BBox in pattern");
}
obj1.free();
- if (streamDict->lookup("XStep", &obj1)->isNum()) {
- xStep = obj1.getNum();
+ if (dict->lookup("XStep", &obj1)->isNum()) {
+ xStepA = obj1.getNum();
} else {
- xStep = 1;
+ xStepA = 1;
error(-1, "Invalid or missing XStep in pattern");
}
obj1.free();
- if (streamDict->lookup("YStep", &obj1)->isNum()) {
- yStep = obj1.getNum();
+ if (dict->lookup("YStep", &obj1)->isNum()) {
+ yStepA = obj1.getNum();
} else {
- yStep = 1;
+ yStepA = 1;
error(-1, "Invalid or missing YStep in pattern");
}
obj1.free();
- if (!streamDict->lookup("Resources", &resDict)->isDict()) {
- resDict.free();
- resDict.initNull();
+ if (!dict->lookup("Resources", &resDictA)->isDict()) {
+ resDictA.free();
+ resDictA.initNull();
error(-1, "Invalid or missing Resources in pattern");
}
- matrix[0] = 1; matrix[1] = 0;
- matrix[2] = 0; matrix[3] = 1;
- matrix[4] = 0; matrix[5] = 0;
- if (streamDict->lookup("Matrix", &obj1)->isArray() &&
+ matrixA[0] = 1; matrixA[1] = 0;
+ matrixA[2] = 0; matrixA[3] = 1;
+ matrixA[4] = 0; matrixA[5] = 0;
+ if (dict->lookup("Matrix", &obj1)->isArray() &&
obj1.arrayGetLength() == 6) {
for (i = 0; i < 6; ++i) {
if (obj1.arrayGet(i, &obj2)->isNum()) {
- matrix[i] = obj2.getNum();
+ matrixA[i] = obj2.getNum();
}
obj2.free();
}
}
obj1.free();
- stream->copy(&contentStream);
+
+ pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA,
+ &resDictA, matrixA, patObj);
+ resDictA.free();
+ return pat;
+}
+
+GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA,
+ double *bboxA, double xStepA, double yStepA,
+ Object *resDictA, double *matrixA,
+ Object *contentStreamA):
+ GfxPattern(1)
+{
+ int i;
+
+ paintType = paintTypeA;
+ tilingType = tilingTypeA;
+ for (i = 0; i < 4; ++i) {
+ bbox[i] = bboxA[i];
+ }
+ xStep = xStepA;
+ yStep = yStepA;
+ resDictA->copy(&resDict);
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = matrixA[i];
+ }
+ contentStreamA->copy(&contentStream);
}
GfxTilingPattern::~GfxTilingPattern() {
@@ -1238,127 +1319,341 @@ GfxTilingPattern::~GfxTilingPattern() {
}
GfxPattern *GfxTilingPattern::copy() {
- return new GfxTilingPattern(this);
+ return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep,
+ &resDict, matrix, &contentStream);
}
-GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
- GfxPattern(1)
+//------------------------------------------------------------------------
+// GfxShadingPattern
+//------------------------------------------------------------------------
+
+GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) {
+ Dict *dict;
+ GfxShading *shadingA;
+ double matrixA[6];
+ Object obj1, obj2;
+ int i;
+
+ if (!patObj->isDict()) {
+ return NULL;
+ }
+ dict = patObj->getDict();
+
+ dict->lookup("Shading", &obj1);
+ shadingA = GfxShading::parse(&obj1);
+ obj1.free();
+ if (!shadingA) {
+ return NULL;
+ }
+
+ matrixA[0] = 1; matrixA[1] = 0;
+ matrixA[2] = 0; matrixA[3] = 1;
+ matrixA[4] = 0; matrixA[5] = 0;
+ if (dict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ for (i = 0; i < 6; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ matrixA[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+
+ return new GfxShadingPattern(shadingA, matrixA);
+}
+
+GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA):
+ GfxPattern(2)
{
- memcpy(this, pat, sizeof(GfxTilingPattern));
- pat->resDict.copy(&resDict);
- pat->contentStream.copy(&contentStream);
+ int i;
+
+ shading = shadingA;
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = matrixA[i];
+ }
+}
+
+GfxShadingPattern::~GfxShadingPattern() {
+ delete shading;
+}
+
+GfxPattern *GfxShadingPattern::copy() {
+ return new GfxShadingPattern(shading->copy(), matrix);
}
//------------------------------------------------------------------------
// GfxShading
//------------------------------------------------------------------------
-GfxShading::GfxShading() {
+GfxShading::GfxShading(int typeA) {
+ type = typeA;
+ colorSpace = NULL;
+}
+
+GfxShading::GfxShading(GfxShading *shading) {
+ int i;
+
+ type = shading->type;
+ colorSpace = shading->colorSpace->copy();
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ background.c[i] = shading->background.c[i];
+ }
+ hasBackground = shading->hasBackground;
+ xMin = shading->xMin;
+ yMin = shading->yMin;
+ xMax = shading->xMax;
+ yMax = shading->yMax;
+ hasBBox = shading->hasBBox;
}
GfxShading::~GfxShading() {
- delete colorSpace;
+ if (colorSpace) {
+ delete colorSpace;
+ }
}
GfxShading *GfxShading::parse(Object *obj) {
GfxShading *shading;
+ Dict *dict;
int typeA;
- GfxColorSpace *colorSpaceA;
- GfxColor backgroundA;
- GBool hasBackgroundA;
- double xMinA, yMinA, xMaxA, yMaxA;
- GBool hasBBoxA;
- Object obj1, obj2;
- int i;
+ Object obj1;
- shading = NULL;
if (obj->isDict()) {
+ dict = obj->getDict();
+ } else if (obj->isStream()) {
+ dict = obj->streamGetDict();
+ } else {
+ return NULL;
+ }
- if (!obj->dictLookup("ShadingType", &obj1)->isInt()) {
- error(-1, "Invalid ShadingType in shading dictionary");
- obj1.free();
- goto err1;
- }
- typeA = obj1.getInt();
+ if (!dict->lookup("ShadingType", &obj1)->isInt()) {
+ error(-1, "Invalid ShadingType in shading dictionary");
obj1.free();
+ return NULL;
+ }
+ typeA = obj1.getInt();
+ obj1.free();
- obj->dictLookup("ColorSpace", &obj1);
- if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
- error(-1, "Bad color space in shading dictionary");
- obj1.free();
- goto err1;
- }
- obj1.free();
+ switch (typeA) {
+ case 1:
+ shading = GfxFunctionShading::parse(dict);
+ break;
+ case 2:
+ shading = GfxAxialShading::parse(dict);
+ break;
+ case 3:
+ shading = GfxRadialShading::parse(dict);
+ break;
+ default:
+ error(-1, "Unimplemented shading type %d", typeA);
+ goto err1;
+ }
- for (i = 0; i < gfxColorMaxComps; ++i) {
- backgroundA.c[i] = 0;
- }
- hasBackgroundA = gFalse;
- if (obj->dictLookup("Background", &obj1)->isArray()) {
- if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
- hasBackgroundA = gTrue;
- for (i = 0; i < colorSpaceA->getNComps(); ++i) {
- backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
- obj2.free();
- }
- } else {
- error(-1, "Bad Background in shading dictionary");
- }
- }
+ return shading;
+
+ err1:
+ return NULL;
+}
+
+GBool GfxShading::init(Dict *dict) {
+ Object obj1, obj2;
+ int i;
+
+ dict->lookup("ColorSpace", &obj1);
+ if (!(colorSpace = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad color space in shading dictionary");
obj1.free();
+ return gFalse;
+ }
+ obj1.free();
- xMinA = yMinA = xMaxA = yMaxA = 0;
- hasBBoxA = gFalse;
- if (obj->dictLookup("BBox", &obj1)->isArray()) {
- if (obj1.arrayGetLength() == 4) {
- hasBBoxA = gTrue;
- xMinA = obj1.arrayGet(0, &obj2)->getNum();
- obj2.free();
- yMinA = obj1.arrayGet(1, &obj2)->getNum();
- obj2.free();
- xMaxA = obj1.arrayGet(2, &obj2)->getNum();
- obj2.free();
- yMaxA = obj1.arrayGet(3, &obj2)->getNum();
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ background.c[i] = 0;
+ }
+ hasBackground = gFalse;
+ if (dict->lookup("Background", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == colorSpace->getNComps()) {
+ hasBackground = gTrue;
+ for (i = 0; i < colorSpace->getNComps(); ++i) {
+ background.c[i] = obj1.arrayGet(i, &obj2)->getNum();
obj2.free();
- } else {
- error(-1, "Bad BBox in shading dictionary");
}
+ } else {
+ error(-1, "Bad Background in shading dictionary");
}
- obj1.free();
+ }
+ obj1.free();
- switch (typeA) {
- case 2:
- shading = GfxAxialShading::parse(obj->getDict());
- break;
- case 3:
- shading = GfxRadialShading::parse(obj->getDict());
- break;
- default:
- error(-1, "Unimplemented shading type %d", typeA);
- goto err1;
+ xMin = yMin = xMax = yMax = 0;
+ hasBBox = gFalse;
+ if (dict->lookup("BBox", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == 4) {
+ hasBBox = gTrue;
+ xMin = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ yMin = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ xMax = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ yMax = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Bad BBox in shading dictionary");
}
+ }
+ obj1.free();
- if (shading) {
- shading->type = typeA;
- shading->colorSpace = colorSpaceA;
- shading->background = backgroundA;
- shading->hasBackground = hasBackgroundA;
- shading->xMin = xMinA;
- shading->yMin = yMinA;
- shading->xMax = xMaxA;
- shading->yMax = yMaxA;
- shading->hasBBox = hasBBoxA;
- } else {
- delete colorSpaceA;
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+// GfxFunctionShading
+//------------------------------------------------------------------------
+
+GfxFunctionShading::GfxFunctionShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double *matrixA,
+ Function **funcsA, int nFuncsA):
+ GfxShading(1)
+{
+ int i;
+
+ x0 = x0A;
+ y0 = y0A;
+ x1 = x1A;
+ y1 = y1A;
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = matrixA[i];
+ }
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+}
+
+GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ x0 = shading->x0;
+ y0 = shading->y0;
+ x1 = shading->x1;
+ y1 = shading->y1;
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = shading->matrix[i];
+ }
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+}
+
+GfxFunctionShading::~GfxFunctionShading() {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) {
+ GfxFunctionShading *shading;
+ double x0A, y0A, x1A, y1A;
+ double matrixA[6];
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ Object obj1, obj2;
+ int i;
+
+ x0A = y0A = 0;
+ x1A = y1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ y1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ matrixA[0] = 1; matrixA[1] = 0;
+ matrixA[2] = 0; matrixA[3] = 1;
+ matrixA[4] = 0; matrixA[5] = 0;
+ if (dict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ matrixA[0] = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ matrixA[1] = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ matrixA[2] = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ matrixA[3] = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ matrixA[4] = obj1.arrayGet(4, &obj2)->getNum();
+ obj2.free();
+ matrixA[5] = obj1.arrayGet(5, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ goto err2;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ goto err1;
}
}
+ obj1.free();
+ shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA,
+ funcsA, nFuncsA);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
return shading;
+ err2:
+ obj2.free();
err1:
+ obj1.free();
return NULL;
}
+GfxShading *GfxFunctionShading::copy() {
+ return new GfxFunctionShading(this);
+}
+
+void GfxFunctionShading::getColor(double x, double y, GfxColor *color) {
+ double in[2];
+ int i;
+
+ in[0] = x;
+ in[1] = y;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(in, &color->c[i]);
+ }
+}
+
//------------------------------------------------------------------------
// GfxAxialShading
//------------------------------------------------------------------------
@@ -1367,7 +1662,9 @@ GfxAxialShading::GfxAxialShading(double x0A, double y0A,
double x1A, double y1A,
double t0A, double t1A,
Function **funcsA, int nFuncsA,
- GBool extend0A, GBool extend1A) {
+ GBool extend0A, GBool extend1A):
+ GfxShading(2)
+{
int i;
x0 = x0A;
@@ -1384,6 +1681,25 @@ GfxAxialShading::GfxAxialShading(double x0A, double y0A,
extend1 = extend1A;
}
+GfxAxialShading::GfxAxialShading(GfxAxialShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ x0 = shading->x0;
+ y0 = shading->y0;
+ x1 = shading->x1;
+ y1 = shading->y1;
+ t0 = shading->t0;
+ y1 = shading->t1;
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+ extend0 = shading->extend0;
+ extend1 = shading->extend1;
+}
+
GfxAxialShading::~GfxAxialShading() {
int i;
@@ -1393,6 +1709,7 @@ GfxAxialShading::~GfxAxialShading() {
}
GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
+ GfxAxialShading *shading;
double x0A, y0A, x1A, y1A;
double t0A, t1A;
Function *funcsA[gfxColorMaxComps];
@@ -1432,6 +1749,10 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
dict->lookup("Function", &obj1);
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
if (!(funcsA[i] = Function::parse(&obj2))) {
@@ -1460,16 +1781,27 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
}
obj1.free();
- return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
- funcsA, nFuncsA, extend0A, extend1A);
+ shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
err1:
return NULL;
}
+GfxShading *GfxAxialShading::copy() {
+ return new GfxAxialShading(this);
+}
+
void GfxAxialShading::getColor(double t, GfxColor *color) {
int i;
+ // NB: there can be one function with n outputs or n functions with
+ // one output each (where n = number of color components)
for (i = 0; i < nFuncs; ++i) {
funcs[i]->transform(&t, &color->c[i]);
}
@@ -1483,7 +1815,9 @@ GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
double x1A, double y1A, double r1A,
double t0A, double t1A,
Function **funcsA, int nFuncsA,
- GBool extend0A, GBool extend1A) {
+ GBool extend0A, GBool extend1A):
+ GfxShading(3)
+{
int i;
x0 = x0A;
@@ -1502,6 +1836,27 @@ GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
extend1 = extend1A;
}
+GfxRadialShading::GfxRadialShading(GfxRadialShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ x0 = shading->x0;
+ y0 = shading->y0;
+ r0 = shading->r0;
+ x1 = shading->x1;
+ y1 = shading->y1;
+ r1 = shading->r1;
+ t0 = shading->t0;
+ y1 = shading->t1;
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+ extend0 = shading->extend0;
+ extend1 = shading->extend1;
+}
+
GfxRadialShading::~GfxRadialShading() {
int i;
@@ -1511,6 +1866,7 @@ GfxRadialShading::~GfxRadialShading() {
}
GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
+ GfxRadialShading *shading;
double x0A, y0A, r0A, x1A, y1A, r1A;
double t0A, t1A;
Function *funcsA[gfxColorMaxComps];
@@ -1554,6 +1910,10 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
dict->lookup("Function", &obj1);
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
if (!(funcsA[i] = Function::parse(&obj2))) {
@@ -1582,16 +1942,27 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
}
obj1.free();
- return new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
- funcsA, nFuncsA, extend0A, extend1A);
+ shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
err1:
return NULL;
}
+GfxShading *GfxRadialShading::copy() {
+ return new GfxRadialShading(this);
+}
+
void GfxRadialShading::getColor(double t, GfxColor *color) {
int i;
+ // NB: there can be one function with n outputs or n functions with
+ // one output each (where n = number of color components)
for (i = 0; i < nFuncs; ++i) {
funcs[i]->transform(&t, &color->c[i]);
}
@@ -1612,14 +1983,12 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
double x[gfxColorMaxComps];
double y[gfxColorMaxComps];
int i, j, k;
- int maxPixelForAlloc;
ok = gTrue;
// bits per component and color space
bits = bitsA;
maxPixel = (1 << bits) - 1;
- maxPixelForAlloc = (1 << (bits>8?bits:8));
colorSpace = colorSpaceA;
// get decode map
@@ -1666,19 +2035,25 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
colorSpace2 = indexedCS->getBase();
indexHigh = indexedCS->getIndexHigh();
nComps2 = colorSpace2->getNComps();
- lookup = (double *)gmalloc((maxPixelForAlloc + 1) * nComps2 * sizeof(double));
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
lookup2 = indexedCS->getLookup();
- for (i = 0; i <= indexHigh; ++i) {
- j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
+ colorSpace2->getDefaultRanges(x, y, indexHigh);
+ for (i = 0; i <= maxPixel; ++i) {
+ j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
+ if (j < 0) {
+ j = 0;
+ } else if (j > indexHigh) {
+ j = indexHigh;
+ }
for (k = 0; k < nComps2; ++k) {
- lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
+ lookup[i*nComps2 + k] = x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k];
}
}
} else if (colorSpace->getMode() == csSeparation) {
sepCS = (GfxSeparationColorSpace *)colorSpace;
colorSpace2 = sepCS->getAlt();
nComps2 = colorSpace2->getNComps();
- lookup = (double *)gmalloc((maxPixelForAlloc + 1) * nComps2 * sizeof(double));
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
sepFunc = sepCS->getFunc();
for (i = 0; i <= maxPixel; ++i) {
x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
@@ -1688,7 +2063,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
}
}
} else {
- lookup = (double *)gmalloc((maxPixelForAlloc + 1) * nComps * sizeof(double));
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps * sizeof(double));
for (i = 0; i <= maxPixel; ++i) {
for (k = 0; k < nComps; ++k) {
lookup[i*nComps + k] = decodeLow[k] +
@@ -1705,6 +2080,34 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
ok = gFalse;
}
+GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
+ int n, i;
+
+ colorSpace = colorMap->colorSpace->copy();
+ bits = colorMap->bits;
+ nComps = colorMap->nComps;
+ nComps2 = colorMap->nComps2;
+ colorSpace2 = NULL;
+ lookup = NULL;
+ n = 1 << bits;
+ if (colorSpace->getMode() == csIndexed) {
+ colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
+ n = n * nComps2 * sizeof(double);
+ } else if (colorSpace->getMode() == csSeparation) {
+ colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
+ n = n * nComps2 * sizeof(double);
+ } else {
+ n = n * nComps * sizeof(double);
+ }
+ lookup = (double *)gmalloc(n);
+ memcpy(lookup, colorMap->lookup, n);
+ for (i = 0; i < nComps; ++i) {
+ decodeLow[i] = colorMap->decodeLow[i];
+ decodeRange[i] = colorMap->decodeRange[i];
+ }
+ ok = gTrue;
+}
+
GfxImageColorMap::~GfxImageColorMap() {
delete colorSpace;
gfree(lookup);
@@ -1730,20 +2133,17 @@ void GfxImageColorMap::getGray(Guchar *x, double *gray) {
}
void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
-
GfxColor color;
double *p;
int i;
if (colorSpace2) {
- //printf("lookup[%d] bits=%d\n",x[0],bits);fflush(stdout);
p = &lookup[x[0] * nComps2];
for (i = 0; i < nComps2; ++i) {
color.c[i] = *p++;
}
colorSpace2->getRGB(&color, rgb);
} else {
- //printf("for i=0,i<%d, bits=%d\n",nComps,bits);fflush(stdout);
for (i = 0; i < nComps; ++i) {
color.c[i] = lookup[x[i] * nComps + i];
}
@@ -1770,6 +2170,15 @@ void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
}
}
+void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) {
+ int maxPixel, i;
+
+ maxPixel = (1 << bits) - 1;
+ for (i = 0; i < nComps; ++i) {
+ color->c[i] = decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel;
+ }
+}
+
//------------------------------------------------------------------------
// GfxSubpath and GfxPath
//------------------------------------------------------------------------
@@ -1844,6 +2253,15 @@ void GfxSubpath::close() {
closed = gTrue;
}
+void GfxSubpath::offset(double dx, double dy) {
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ x[i] += dx;
+ y[i] += dy;
+ }
+}
+
GfxPath::GfxPath() {
justMoved = gFalse;
size = 16;
@@ -1926,55 +2344,78 @@ void GfxPath::close() {
subpaths[n-1]->close();
}
+void GfxPath::append(GfxPath *path) {
+ int i;
+
+ if (n + path->n > size) {
+ size = n + path->n;
+ subpaths = (GfxSubpath **)
+ grealloc(subpaths, size * sizeof(GfxSubpath *));
+ }
+ for (i = 0; i < path->n; ++i) {
+ subpaths[n++] = path->subpaths[i]->copy();
+ }
+ justMoved = gFalse;
+}
+
+void GfxPath::offset(double dx, double dy) {
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ subpaths[i]->offset(dx, dy);
+ }
+}
+
//------------------------------------------------------------------------
// GfxState
//------------------------------------------------------------------------
-GfxState::GfxState(double dpi, PDFRectangle *pageBox, int rotate,
- GBool upsideDown) {
- double k;
+GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+ int rotate, GBool upsideDown) {
+ double kx, ky;
px1 = pageBox->x1;
py1 = pageBox->y1;
px2 = pageBox->x2;
py2 = pageBox->y2;
- k = dpi / 72.0;
+ kx = hDPI / 72.0;
+ ky = vDPI / 72.0;
if (rotate == 90) {
ctm[0] = 0;
- ctm[1] = upsideDown ? k : -k;
- ctm[2] = k;
+ ctm[1] = upsideDown ? ky : -ky;
+ ctm[2] = kx;
ctm[3] = 0;
- ctm[4] = -k * py1;
- ctm[5] = k * (upsideDown ? -px1 : px2);
- pageWidth = k * (py2 - py1);
- pageHeight = k * (px2 - px1);
+ ctm[4] = -kx * py1;
+ ctm[5] = ky * (upsideDown ? -px1 : px2);
+ pageWidth = kx * (py2 - py1);
+ pageHeight = ky * (px2 - px1);
} else if (rotate == 180) {
- ctm[0] = -k;
+ ctm[0] = -kx;
ctm[1] = 0;
ctm[2] = 0;
- ctm[3] = upsideDown ? k : -k;
- ctm[4] = k * px2;
- ctm[5] = k * (upsideDown ? -py1 : py2);
- pageWidth = k * (px2 - px1);
- pageHeight = k * (py2 - py1);
+ ctm[3] = upsideDown ? ky : -ky;
+ ctm[4] = kx * px2;
+ ctm[5] = ky * (upsideDown ? -py1 : py2);
+ pageWidth = kx * (px2 - px1);
+ pageHeight = ky * (py2 - py1);
} else if (rotate == 270) {
ctm[0] = 0;
- ctm[1] = upsideDown ? -k : k;
- ctm[2] = -k;
+ ctm[1] = upsideDown ? -ky : ky;
+ ctm[2] = -kx;
ctm[3] = 0;
- ctm[4] = k * py2;
- ctm[5] = k * (upsideDown ? px2 : -px1);
- pageWidth = k * (py2 - py1);
- pageHeight = k * (px2 - px1);
+ ctm[4] = kx * py2;
+ ctm[5] = ky * (upsideDown ? px2 : -px1);
+ pageWidth = kx * (py2 - py1);
+ pageHeight = ky * (px2 - px1);
} else {
- ctm[0] = k;
+ ctm[0] = kx;
ctm[1] = 0;
ctm[2] = 0;
- ctm[3] = upsideDown ? -k : k;
- ctm[4] = -k * px1;
- ctm[5] = k * (upsideDown ? py2 : -py1);
- pageWidth = k * (px2 - px1);
- pageHeight = k * (py2 - py1);
+ ctm[3] = upsideDown ? -ky : ky;
+ ctm[4] = -kx * px1;
+ ctm[5] = ky * (upsideDown ? py2 : -py1);
+ pageWidth = kx * (px2 - px1);
+ pageHeight = ky * (py2 - py1);
}
fillColorSpace = new GfxDeviceGrayColorSpace();
@@ -1990,7 +2431,7 @@ GfxState::GfxState(double dpi, PDFRectangle *pageBox, int rotate,
lineDash = NULL;
lineDashLength = 0;
lineDashStart = 0;
- flatness = 0;
+ flatness = 1;
lineJoin = 0;
lineCap = 0;
miterLimit = 10;
@@ -2064,6 +2505,11 @@ GfxState::GfxState(GfxState *state) {
saved = NULL;
}
+void GfxState::setPath(GfxPath *pathA) {
+ delete path;
+ path = pathA;
+}
+
void GfxState::getUserClipBBox(double *xMin, double *yMin,
double *xMax, double *yMax) {
double ictm[6];
diff --git a/pdf2swf/xpdf/GfxState.h b/pdf2swf/xpdf/GfxState.h
index b1f6f28e..f747a831 100644
--- a/pdf2swf/xpdf/GfxState.h
+++ b/pdf2swf/xpdf/GfxState.h
@@ -2,14 +2,16 @@
//
// GfxState.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GFXSTATE_H
#define GFXSTATE_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -19,7 +21,8 @@
class Array;
class GfxFont;
-struct PDFRectangle;
+class PDFRectangle;
+class GfxShading;
//------------------------------------------------------------------------
// GfxColor
@@ -51,6 +54,8 @@ struct GfxCMYK {
// GfxColorSpace
//------------------------------------------------------------------------
+// NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames
+// array defined in GfxState.cc must match this enum.
enum GfxColorSpaceMode {
csDeviceGray,
csCalGray,
@@ -89,6 +94,12 @@ public:
virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
int maxImgPixel);
+ // Return the number of color space modes
+ static int getNumColorSpaceModes();
+
+ // Return the name of the <idx>th color space mode.
+ static char *getColorSpaceModeName(int idx);
+
private:
};
@@ -342,6 +353,7 @@ public:
GfxColorSpace *getBase() { return base; }
int getIndexHigh() { return indexHigh; }
Guchar *getLookup() { return lookup; }
+ GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor);
private:
@@ -391,7 +403,7 @@ private:
class GfxDeviceNColorSpace: public GfxColorSpace {
public:
- GfxDeviceNColorSpace(int nComps, GfxColorSpace *alt, Function *func);
+ GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func);
virtual ~GfxDeviceNColorSpace();
virtual GfxColorSpace *copy();
virtual GfxColorSpaceMode getMode() { return csDeviceN; }
@@ -406,7 +418,9 @@ public:
virtual int getNComps() { return nComps; }
// DeviceN-specific access.
+ GString *getColorantName(int i) { return names[i]; }
GfxColorSpace *getAlt() { return alt; }
+ Function *getTintTransformFunc() { return func; }
private:
@@ -415,7 +429,6 @@ private:
*names[gfxColorMaxComps];
GfxColorSpace *alt; // alternate color space
Function *func; // tint transform (into alternate color space)
-
};
//------------------------------------------------------------------------
@@ -476,7 +489,7 @@ private:
class GfxTilingPattern: public GfxPattern {
public:
- GfxTilingPattern(Dict *streamDict, Object *stream);
+ static GfxTilingPattern *parse(Object *patObj);
virtual ~GfxTilingPattern();
virtual GfxPattern *copy();
@@ -493,7 +506,10 @@ public:
private:
- GfxTilingPattern(GfxTilingPattern *pat);
+ GfxTilingPattern(int paintTypeA, int tilingTypeA,
+ double *bboxA, double xStepA, double yStepA,
+ Object *resDictA, double *matrixA,
+ Object *contentStreamA);
int paintType;
int tilingType;
@@ -505,17 +521,43 @@ private:
};
//------------------------------------------------------------------------
+// GfxShadingPattern
+//------------------------------------------------------------------------
+
+class GfxShadingPattern: public GfxPattern {
+public:
+
+ static GfxShadingPattern *parse(Object *patObj);
+ virtual ~GfxShadingPattern();
+
+ virtual GfxPattern *copy();
+
+ GfxShading *getShading() { return shading; }
+ double *getMatrix() { return matrix; }
+
+private:
+
+ GfxShadingPattern(GfxShading *shadingA, double *matrixA);
+
+ GfxShading *shading;
+ double matrix[6];
+};
+
+//------------------------------------------------------------------------
// GfxShading
//------------------------------------------------------------------------
class GfxShading {
public:
- GfxShading();
+ GfxShading(int typeA);
+ GfxShading(GfxShading *shading);
virtual ~GfxShading();
static GfxShading *parse(Object *obj);
+ virtual GfxShading *copy() = 0;
+
int getType() { return type; }
GfxColorSpace *getColorSpace() { return colorSpace; }
GfxColor *getBackground() { return &background; }
@@ -524,7 +566,9 @@ public:
{ *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
GBool getHasBBox() { return hasBBox; }
-private:
+protected:
+
+ GBool init(Dict *dict);
int type;
GfxColorSpace *colorSpace;
@@ -535,6 +579,37 @@ private:
};
//------------------------------------------------------------------------
+// GfxFunctionShading
+//------------------------------------------------------------------------
+
+class GfxFunctionShading: public GfxShading {
+public:
+
+ GfxFunctionShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double *matrixA,
+ Function **funcsA, int nFuncsA);
+ GfxFunctionShading(GfxFunctionShading *shading);
+ virtual ~GfxFunctionShading();
+
+ static GfxFunctionShading *parse(Dict *dict);
+
+ virtual GfxShading *copy();
+
+ void getDomain(double *x0A, double *y0A, double *x1A, double *y1A)
+ { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
+ double *getMatrix() { return matrix; }
+ void getColor(double x, double y, GfxColor *color);
+
+private:
+
+ double x0, y0, x1, y1;
+ double matrix[6];
+ Function *funcs[gfxColorMaxComps];
+ int nFuncs;
+};
+
+//------------------------------------------------------------------------
// GfxAxialShading
//------------------------------------------------------------------------
@@ -546,10 +621,13 @@ public:
double t0A, double t1A,
Function **funcsA, int nFuncsA,
GBool extend0A, GBool extend1A);
+ GfxAxialShading(GfxAxialShading *shading);
virtual ~GfxAxialShading();
static GfxAxialShading *parse(Dict *dict);
+ virtual GfxShading *copy();
+
void getCoords(double *x0A, double *y0A, double *x1A, double *y1A)
{ *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
double getDomain0() { return t0; }
@@ -579,10 +657,13 @@ public:
double t0A, double t1A,
Function **funcsA, int nFuncsA,
GBool extend0A, GBool extend1A);
+ GfxRadialShading(GfxRadialShading *shading);
virtual ~GfxRadialShading();
static GfxRadialShading *parse(Dict *dict);
+ virtual GfxShading *copy();
+
void getCoords(double *x0A, double *y0A, double *r0A,
double *x1A, double *y1A, double *r1A)
{ *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; }
@@ -614,6 +695,9 @@ public:
// Destructor.
~GfxImageColorMap();
+ // Return a copy of this color map.
+ GfxImageColorMap *copy() { return new GfxImageColorMap(this); }
+
// Is color map valid?
GBool isOk() { return ok; }
@@ -632,9 +716,12 @@ public:
void getGray(Guchar *x, double *gray);
void getRGB(Guchar *x, GfxRGB *rgb);
void getCMYK(Guchar *x, GfxCMYK *cmyk);
+ void getColor(Guchar *x, GfxColor *color);
private:
+ GfxImageColorMap(GfxImageColorMap *colorMap);
+
GfxColorSpace *colorSpace; // the image color space
int bits; // bits per component
int nComps; // number of components in a pixel
@@ -685,6 +772,9 @@ public:
void close();
GBool isClosed() { return closed; }
+ // Add (<dx>, <dy>) to each point in the subpath.
+ void offset(double dx, double dy);
+
private:
double *x, *y; // points
@@ -737,6 +827,12 @@ public:
// Close the last subpath.
void close();
+ // Append <path> to <this>.
+ void append(GfxPath *path);
+
+ // Add (<dx>, <dy>) to each point in the path.
+ void offset(double dx, double dy);
+
private:
GBool justMoved; // set if a new subpath was just started
@@ -756,11 +852,11 @@ private:
class GfxState {
public:
- // Construct a default GfxState, for a device with resolution <dpi>,
- // page box <pageBox>, page rotation <rotate>, and coordinate system
- // specified by <upsideDown>.
- GfxState(double dpi, PDFRectangle *pageBox, int rotate,
- GBool upsideDown);
+ // Construct a default GfxState, for a device with resolution <hDPI>
+ // x <vDPI>, page box <pageBox>, page rotation <rotate>, and
+ // coordinate system specified by <upsideDown>.
+ GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+ int rotate, GBool upsideDown);
// Destructor.
~GfxState();
@@ -781,7 +877,7 @@ public:
void getFillGray(double *gray)
{ fillColorSpace->getGray(&fillColor, gray); }
void getStrokeGray(double *gray)
- { strokeColorSpace->getGray(&fillColor, gray); }
+ { strokeColorSpace->getGray(&strokeColor, gray); }
void getFillRGB(GfxRGB *rgb)
{ fillColorSpace->getRGB(&fillColor, rgb); }
void getStrokeRGB(GfxRGB *rgb)
@@ -813,6 +909,7 @@ public:
double getRise() { return rise; }
int getRender() { return render; }
GfxPath *getPath() { return path; }
+ void setPath(GfxPath *pathA);
double getCurX() { return curX; }
double getCurY() { return curY; }
void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax)
@@ -898,6 +995,7 @@ public:
void clip();
// Text position.
+ void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
void textMoveTo(double tx, double ty)
{ lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); }
void textShift(double tx, double ty);
diff --git a/pdf2swf/xpdf/GlobalParams.cc b/pdf2swf/xpdf/GlobalParams.cc
index 0bc908ea..c1254302 100644
--- a/pdf2swf/xpdf/GlobalParams.cc
+++ b/pdf2swf/xpdf/GlobalParams.cc
@@ -2,16 +2,18 @@
//
// GlobalParams.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <string.h>
+#include <stdio.h>
#include <ctype.h>
#if HAVE_PAPER_H
#include <paper.h>
@@ -30,13 +32,63 @@
#include "FontEncodingTables.h"
#include "GlobalParams.h"
+#if MULTITHREADED
+# define lockGlobalParams gLockMutex(&mutex)
+# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
+# define lockCMapCache gLockMutex(&cMapCacheMutex)
+# define unlockGlobalParams gUnlockMutex(&mutex)
+# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex)
+# define unlockCMapCache gUnlockMutex(&cMapCacheMutex)
+#else
+# define lockGlobalParams
+# define lockUnicodeMapCache
+# define lockCMapCache
+# define unlockGlobalParams
+# define unlockUnicodeMapCache
+# define unlockCMapCache
+#endif
+
#include "NameToUnicodeTable.h"
#include "UnicodeMapTables.h"
-#include "DisplayFontTable.h"
#include "UTF8.h"
//------------------------------------------------------------------------
+#define cidToUnicodeCacheSize 4
+#define unicodeToUnicodeCacheSize 4
+
+//------------------------------------------------------------------------
+
+static struct {
+ char *name;
+ char *fileName;
+} displayFontTab[] = {
+ {"Courier", "n022003l.pfb"},
+ {"Courier-Bold", "n022004l.pfb"},
+ {"Courier-BoldOblique", "n022024l.pfb"},
+ {"Courier-Oblique", "n022023l.pfb"},
+ {"Helvetica", "n019003l.pfb"},
+ {"Helvetica-Bold", "n019004l.pfb"},
+ {"Helvetica-BoldOblique", "n019024l.pfb"},
+ {"Helvetica-Oblique", "n019023l.pfb"},
+ {"Symbol", "s050000l.pfb"},
+ {"Times-Bold", "n021004l.pfb"},
+ {"Times-BoldItalic", "n021024l.pfb"},
+ {"Times-Italic", "n021023l.pfb"},
+ {"Times-Roman", "n021003l.pfb"},
+ {"ZapfDingbats", "d050000l.pfb"},
+ {NULL}
+};
+
+static char *displayFontDirs[] = {
+ "/usr/share/ghostscript/fonts",
+ "/usr/local/share/ghostscript/fonts",
+ "/usr/share/fonts/default/Type1",
+ NULL
+};
+
+//------------------------------------------------------------------------
+
GlobalParams *globalParams = NULL;
//------------------------------------------------------------------------
@@ -48,10 +100,6 @@ DisplayFontParam::DisplayFontParam(GString *nameA,
name = nameA;
kind = kindA;
switch (kind) {
- case displayFontX:
- x.xlfd = NULL;
- x.encoding = NULL;
- break;
case displayFontT1:
t1.fileName = NULL;
break;
@@ -61,24 +109,9 @@ DisplayFontParam::DisplayFontParam(GString *nameA,
}
}
-DisplayFontParam::DisplayFontParam(char *nameA, char *xlfdA, char *encodingA) {
- name = new GString(nameA);
- kind = displayFontX;
- x.xlfd = new GString(xlfdA);
- x.encoding = new GString(encodingA);
-}
-
DisplayFontParam::~DisplayFontParam() {
delete name;
switch (kind) {
- case displayFontX:
- if (x.xlfd) {
- delete x.xlfd;
- }
- if (x.encoding) {
- delete x.encoding;
- }
- break;
case displayFontT1:
if (t1.fileName) {
delete t1.fileName;
@@ -118,11 +151,16 @@ PSFontParam::~PSFontParam() {
GlobalParams::GlobalParams(char *cfgFileName) {
UnicodeMap *map;
- DisplayFontParam *dfp;
GString *fileName;
FILE *f;
int i;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+ gInitMutex(&unicodeMapCacheMutex);
+ gInitMutex(&cMapCacheMutex);
+#endif
+
initBuiltinFontTables();
// scan the encoding in reverse because we want the lowest-numbered
@@ -136,6 +174,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
nameToUnicode = new NameToCharCode();
cidToUnicodes = new GHash(gTrue);
+ unicodeToUnicodes = new GHash(gTrue);
residentUnicodeMaps = new GHash();
unicodeMaps = new GHash(gTrue);
cMapDirs = new GHash(gTrue);
@@ -144,16 +183,30 @@ GlobalParams::GlobalParams(char *cfgFileName) {
displayCIDFonts = new GHash();
displayNamedCIDFonts = new GHash();
#if HAVE_PAPER_H
+ char *paperName;
const struct paper *paperType;
paperinit();
- paperType = paperinfo(systempapername());
- psPaperWidth = (int)paperpswidth(paperType);
- psPaperHeight = (int)paperpsheight(paperType);
+ if ((paperName = systempapername())) {
+ paperType = paperinfo(paperName);
+ psPaperWidth = (int)paperpswidth(paperType);
+ psPaperHeight = (int)paperpsheight(paperType);
+ } else {
+ error(-1, "No paper information available - using defaults");
+ psPaperWidth = defPaperWidth;
+ psPaperHeight = defPaperHeight;
+ }
paperdone();
#else
psPaperWidth = defPaperWidth;
psPaperHeight = defPaperHeight;
#endif
+ psImageableLLX = psImageableLLY = 0;
+ psImageableURX = psPaperWidth;
+ psImageableURY = psPaperHeight;
+ psCrop = gTrue;
+ psExpandSmaller = gFalse;
+ psShrinkLarger = gTrue;
+ psCenter = gTrue;
psDuplex = gFalse;
psLevel = psLevel2;
psFile = NULL;
@@ -174,15 +227,22 @@ GlobalParams::GlobalParams(char *cfgFileName) {
#else
textEOL = eolUnix;
#endif
+ textPageBreaks = gTrue;
+ textKeepTinyChars = gFalse;
fontDirs = new GList();
- initialZoom = new GString("1");
- t1libControl = fontRastAALow;
- freetypeControl = fontRastAALow;
+ initialZoom = new GString("125");
+ enableT1lib = gTrue;
+ enableFreeType = gTrue;
+ antialias = gTrue;
urlCommand = NULL;
+ movieCommand = NULL;
mapNumericCharNames = gTrue;
+ printCommands = gFalse;
errQuiet = gFalse;
- cidToUnicodeCache = new CIDToUnicodeCache();
+ cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
+ unicodeToUnicodeCache =
+ new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize);
unicodeMapCache = new UnicodeMapCache();
cMapCache = new CMapCache();
@@ -192,28 +252,23 @@ GlobalParams::GlobalParams(char *cfgFileName) {
}
// set up the residentUnicodeMaps table
- map = new UnicodeMap("Latin1", latin1UnicodeMapRanges, latin1UnicodeMapLen);
+ map = new UnicodeMap("Latin1", gFalse,
+ latin1UnicodeMapRanges, latin1UnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("ASCII7", ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
+ map = new UnicodeMap("ASCII7", gFalse,
+ ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("Symbol", symbolUnicodeMapRanges, symbolUnicodeMapLen);
+ map = new UnicodeMap("Symbol", gFalse,
+ symbolUnicodeMapRanges, symbolUnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("ZapfDingbats", zapfDingbatsUnicodeMapRanges,
+ map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
zapfDingbatsUnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("UTF-8", &mapUTF8);
+ map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
residentUnicodeMaps->add(map->getEncodingName(), map);
- map = new UnicodeMap("UCS-2", &mapUCS2);
+ map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
residentUnicodeMaps->add(map->getEncodingName(), map);
- // default displayFonts table
- for (i = 0; displayFontTab[i].name; ++i) {
- dfp = new DisplayFontParam(displayFontTab[i].name,
- displayFontTab[i].xlfd,
- displayFontTab[i].encoding);
- displayFonts->add(dfp->name, dfp);
- }
-
// look for a user config file, then a system-wide config file
f = NULL;
fileName = NULL;
@@ -235,7 +290,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
i = GetModuleFileName(NULL, buf, sizeof(buf));
if (i <= 0 || i >= sizeof(buf)) {
// error or path too long for buffer - just use the current dir
- buf[i] = '\0';
+ buf[0] = '\0';
}
fileName = grabPath(buf);
appendToPath(fileName, xpdfSysConfigFile);
@@ -249,6 +304,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
if (f) {
parseFile(fileName, f);
delete fileName;
+ fclose(f);
}
}
@@ -261,7 +317,7 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
FILE *f2;
line = 1;
- while (fgets(buf, sizeof(buf) - 1, f)) {
+ while (getLine(buf, sizeof(buf) - 1, f)) {
// break the line into tokens
tokens = new GList();
@@ -278,7 +334,7 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
}
tokens->append(new GString(p1, p2 - p1));
- p1 = p2 + 1;
+ p1 = *p2 ? p2 + 1 : p2;
}
if (tokens->getLength() > 0 &&
@@ -302,24 +358,30 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
parseNameToUnicode(tokens, fileName, line);
} else if (!cmd->cmp("cidToUnicode")) {
parseCIDToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("unicodeToUnicode")) {
+ parseUnicodeToUnicode(tokens, fileName, line);
} else if (!cmd->cmp("unicodeMap")) {
parseUnicodeMap(tokens, fileName, line);
} else if (!cmd->cmp("cMapDir")) {
parseCMapDir(tokens, fileName, line);
} else if (!cmd->cmp("toUnicodeDir")) {
parseToUnicodeDir(tokens, fileName, line);
- } else if (!cmd->cmp("displayFontX")) {
- parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line);
} else if (!cmd->cmp("displayFontT1")) {
parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
} else if (!cmd->cmp("displayFontTT")) {
parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
- } else if (!cmd->cmp("displayCIDFontX")) {
+ } else if (!cmd->cmp("displayNamedCIDFontT1")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontT1")) {
parseDisplayFont(tokens, displayCIDFonts,
- displayFontX, fileName, line);
- } else if (!cmd->cmp("displayNamedCIDFontX")) {
+ displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontTT")) {
parseDisplayFont(tokens, displayNamedCIDFonts,
- displayFontX, fileName, line);
+ 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")) {
@@ -331,6 +393,17 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
} else if (!cmd->cmp("psPaperSize")) {
parsePSPaperSize(tokens, fileName, line);
+ } else if (!cmd->cmp("psImageableArea")) {
+ parsePSImageableArea(tokens, fileName, line);
+ } else if (!cmd->cmp("psCrop")) {
+ parseYesNo("psCrop", &psCrop, tokens, fileName, line);
+ } else if (!cmd->cmp("psExpandSmaller")) {
+ parseYesNo("psExpandSmaller", &psExpandSmaller,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psShrinkLarger")) {
+ parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
+ } else if (!cmd->cmp("psCenter")) {
+ parseYesNo("psCenter", &psCenter, tokens, fileName, line);
} else if (!cmd->cmp("psDuplex")) {
parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
} else if (!cmd->cmp("psLevel")) {
@@ -354,29 +427,46 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
parseTextEncoding(tokens, fileName, line);
} else if (!cmd->cmp("textEOL")) {
parseTextEOL(tokens, fileName, line);
+ } else if (!cmd->cmp("textPageBreaks")) {
+ parseYesNo("textPageBreaks", &textPageBreaks,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("textKeepTinyChars")) {
+ parseYesNo("textKeepTinyChars", &textKeepTinyChars,
+ tokens, fileName, line);
} else if (!cmd->cmp("fontDir")) {
parseFontDir(tokens, fileName, line);
} else if (!cmd->cmp("initialZoom")) {
parseInitialZoom(tokens, fileName, line);
- } else if (!cmd->cmp("t1libControl")) {
- parseFontRastControl("t1libControl", &t1libControl,
- tokens, fileName, line);
- } else if (!cmd->cmp("freetypeControl")) {
- parseFontRastControl("freetypeControl", &freetypeControl,
- tokens, fileName, line);
+ } else if (!cmd->cmp("enableT1lib")) {
+ parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
+ } else if (!cmd->cmp("enableFreeType")) {
+ parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
+ } else if (!cmd->cmp("antialias")) {
+ parseYesNo("antialias", &antialias, tokens, fileName, line);
} else if (!cmd->cmp("urlCommand")) {
- parseURLCommand(tokens, fileName, line);
+ parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
+ } else if (!cmd->cmp("movieCommand")) {
+ parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
} else if (!cmd->cmp("mapNumericCharNames")) {
parseYesNo("mapNumericCharNames", &mapNumericCharNames,
tokens, fileName, line);
+ } else if (!cmd->cmp("printCommands")) {
+ parseYesNo("printCommands", &printCommands, tokens, fileName, line);
} else if (!cmd->cmp("errQuiet")) {
parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
- } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
- error(-1, "Unknown config file command");
- error(-1, "-- the config file format has changed since Xpdf 0.9x");
} else {
error(-1, "Unknown config file command '%s' (%s:%d)",
cmd->getCString(), fileName->getCString(), line);
+ if (!cmd->cmp("displayFontX") ||
+ !cmd->cmp("displayNamedCIDFontX") ||
+ !cmd->cmp("displayCIDFontX")) {
+ error(-1, "-- Xpdf no longer supports X fonts");
+ } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
+ error(-1, "-- The t1libControl and freetypeControl options have been replaced");
+ error(-1, " by the enableT1lib, enableFreeType, and antialias options");
+ } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
+ error(-1, "-- the config file format has changed since Xpdf 0.9x");
+ }
}
}
@@ -406,7 +496,7 @@ void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
return;
}
line2 = 1;
- while (fgets(buf, sizeof(buf), f)) {
+ while (getLine(buf, sizeof(buf), f)) {
tok1 = strtok(buf, " \t\r\n");
tok2 = strtok(NULL, " \t\r\n");
if (tok1 && tok2) {
@@ -437,6 +527,23 @@ void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
cidToUnicodes->add(collection->copy(), name->copy());
}
+void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
+ int line) {
+ GString *font, *file, *old;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ font = (GString *)tokens->get(1);
+ file = (GString *)tokens->get(2);
+ if ((old = (GString *)unicodeToUnicodes->remove(font))) {
+ delete old;
+ }
+ unicodeToUnicodes->add(font->copy(), file->copy());
+}
+
void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
int line) {
GString *encodingName, *name, *old;
@@ -493,13 +600,6 @@ void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
switch (kind) {
- case displayFontX:
- if (tokens->getLength() != 4) {
- goto err2;
- }
- param->x.xlfd = ((GString *)tokens->get(2))->copy();
- param->x.encoding = ((GString *)tokens->get(3))->copy();
- break;
case displayFontT1:
if (tokens->getLength() != 3) {
goto err2;
@@ -542,12 +642,28 @@ void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
psPaperWidth = atoi(tok->getCString());
tok = (GString *)tokens->get(2);
psPaperHeight = atoi(tok->getCString());
+ psImageableLLX = psImageableLLY = 0;
+ psImageableURX = psPaperWidth;
+ psImageableURY = psPaperHeight;
} else {
error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
fileName->getCString(), line);
}
}
+void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
+ int line) {
+ if (tokens->getLength() != 5) {
+ error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
+ psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
+ psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
+ psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
+}
+
void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
GString *tok;
@@ -680,34 +796,17 @@ void GlobalParams::parseInitialZoom(GList *tokens,
initialZoom = ((GString *)tokens->get(1))->copy();
}
-void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val,
- GList *tokens, GString *fileName,
- int line) {
- GString *tok;
-
+void GlobalParams::parseCommand(char *cmdName, GString **val,
+ GList *tokens, GString *fileName, int line) {
if (tokens->getLength() != 2) {
error(-1, "Bad '%s' config file command (%s:%d)",
cmdName, fileName->getCString(), line);
return;
}
- tok = (GString *)tokens->get(1);
- if (!setFontRastControl(val, tok->getCString())) {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ if (*val) {
+ delete *val;
}
-}
-
-void GlobalParams::parseURLCommand(GList *tokens, GString *fileName,
- int line) {
- if (tokens->getLength() != 2) {
- error(-1, "Bad 'urlCommand' config file command (%s:%d)",
- fileName->getCString(), line);
- return;
- }
- if (urlCommand) {
- delete urlCommand;
- }
- urlCommand = ((GString *)tokens->get(1))->copy();
+ *val = ((GString *)tokens->get(1))->copy();
}
void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
@@ -720,14 +819,21 @@ void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
return;
}
tok = (GString *)tokens->get(1);
- if (!tok->cmp("yes")) {
+ if (!parseYesNo2(tok->getCString(), flag)) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ }
+}
+
+GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
+ if (!strcmp(token, "yes")) {
*flag = gTrue;
- } else if (!tok->cmp("no")) {
+ } else if (!strcmp(token, "no")) {
*flag = gFalse;
} else {
- error(-1, "Bad '%s' config file command (%s:%d)",
- cmdName, fileName->getCString(), line);
+ return gFalse;
}
+ return gTrue;
}
GlobalParams::~GlobalParams() {
@@ -741,6 +847,7 @@ GlobalParams::~GlobalParams() {
delete nameToUnicode;
deleteGHash(cidToUnicodes, GString);
+ deleteGHash(unicodeToUnicodes, GString);
deleteGHash(residentUnicodeMaps, UnicodeMap);
deleteGHash(unicodeMaps, GString);
deleteGList(toUnicodeDirs, GString);
@@ -759,6 +866,9 @@ GlobalParams::~GlobalParams() {
if (urlCommand) {
delete urlCommand;
}
+ if (movieCommand) {
+ delete movieCommand;
+ }
cMapDirs->startIter(&iter);
while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
@@ -767,8 +877,63 @@ GlobalParams::~GlobalParams() {
delete cMapDirs;
delete cidToUnicodeCache;
+ delete unicodeToUnicodeCache;
delete unicodeMapCache;
delete cMapCache;
+
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+ gDestroyMutex(&unicodeMapCacheMutex);
+ gDestroyMutex(&cMapCacheMutex);
+#endif
+}
+
+//------------------------------------------------------------------------
+
+void GlobalParams::setupBaseFonts(char *dir) {
+ GString *fontName;
+ GString *fileName;
+ FILE *f;
+ DisplayFontParam *dfp;
+ int i, j;
+
+ for (i = 0; displayFontTab[i].name; ++i) {
+ fontName = new GString(displayFontTab[i].name);
+ if (getDisplayFont(fontName)) {
+ delete fontName;
+ continue;
+ }
+ fileName = NULL;
+ if (dir) {
+ fileName = appendToPath(new GString(dir), displayFontTab[i].fileName);
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ } else {
+ delete fileName;
+ fileName = NULL;
+ }
+ }
+#ifndef WIN32
+ for (j = 0; !fileName && displayFontDirs[j]; ++j) {
+ fileName = appendToPath(new GString(displayFontDirs[j]),
+ displayFontTab[i].fileName);
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ } else {
+ delete fileName;
+ fileName = NULL;
+ }
+ }
+#endif
+ if (!fileName) {
+ error(-1, "No display font for '%s'", displayFontTab[i].name);
+ delete fontName;
+ continue;
+ }
+ dfp = new DisplayFontParam(fontName, displayFontT1);
+ dfp->t1.fileName = fileName;
+ globalParams->addDisplayFont(dfp);
+ }
}
//------------------------------------------------------------------------
@@ -776,33 +941,39 @@ GlobalParams::~GlobalParams() {
//------------------------------------------------------------------------
CharCode GlobalParams::getMacRomanCharCode(char *charName) {
+ // no need to lock - macRomanReverseMap is constant
return macRomanReverseMap->lookup(charName);
}
Unicode GlobalParams::mapNameToUnicode(char *charName) {
+ // no need to lock - nameToUnicode is constant
return nameToUnicode->lookup(charName);
}
-FILE *GlobalParams::getCIDToUnicodeFile(GString *collection) {
- GString *fileName;
+UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
+ UnicodeMap *map;
- if (!(fileName = (GString *)cidToUnicodes->lookup(collection))) {
- return NULL;
+ lockGlobalParams;
+ map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
+ unlockGlobalParams;
+ if (map) {
+ map->incRefCnt();
}
- return fopen(fileName->getCString(), "r");
-}
-
-UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
- return (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
+ return map;
}
FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
GString *fileName;
+ FILE *f;
- if (!(fileName = (GString *)unicodeMaps->lookup(encodingName))) {
- return NULL;
+ lockGlobalParams;
+ if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
+ f = fopen(fileName->getCString(), "r");
+ } else {
+ f = NULL;
}
- return fopen(fileName->getCString(), "r");
+ unlockGlobalParams;
+ return f;
}
FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
@@ -812,7 +983,9 @@ FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
FILE *f;
int i;
+ lockGlobalParams;
if (!(list = (GList *)cMapDirs->lookup(collection))) {
+ unlockGlobalParams;
return NULL;
}
for (i = 0; i < list->getLength(); ++i) {
@@ -821,9 +994,11 @@ FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
f = fopen(fileName->getCString(), "r");
delete fileName;
if (f) {
+ unlockGlobalParams;
return f;
}
}
+ unlockGlobalParams;
return NULL;
}
@@ -832,35 +1007,140 @@ FILE *GlobalParams::findToUnicodeFile(GString *name) {
FILE *f;
int i;
+ lockGlobalParams;
for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
dir = (GString *)toUnicodeDirs->get(i);
fileName = appendToPath(dir->copy(), name->getCString());
f = fopen(fileName->getCString(), "r");
delete fileName;
if (f) {
+ unlockGlobalParams;
return f;
}
}
+ unlockGlobalParams;
return NULL;
}
DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
- return (DisplayFontParam *)displayFonts->lookup(fontName);
+ DisplayFontParam *dfp;
+
+ lockGlobalParams;
+ dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
+ unlockGlobalParams;
+ return dfp;
}
DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
GString *collection) {
DisplayFontParam *dfp;
+ lockGlobalParams;
if (!fontName ||
!(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
}
+ unlockGlobalParams;
return dfp;
}
+GString *GlobalParams::getPSFile() {
+ GString *s;
+
+ lockGlobalParams;
+ s = psFile ? psFile->copy() : (GString *)NULL;
+ unlockGlobalParams;
+ return s;
+}
+
+int GlobalParams::getPSPaperWidth() {
+ int w;
+
+ lockGlobalParams;
+ w = psPaperWidth;
+ unlockGlobalParams;
+ return w;
+}
+
+int GlobalParams::getPSPaperHeight() {
+ int h;
+
+ lockGlobalParams;
+ h = psPaperHeight;
+ unlockGlobalParams;
+ return h;
+}
+
+void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
+ lockGlobalParams;
+ *llx = psImageableLLX;
+ *lly = psImageableLLY;
+ *urx = psImageableURX;
+ *ury = psImageableURY;
+ unlockGlobalParams;
+}
+
+GBool GlobalParams::getPSCrop() {
+ GBool f;
+
+ lockGlobalParams;
+ f = psCrop;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getPSExpandSmaller() {
+ GBool f;
+
+ lockGlobalParams;
+ f = psExpandSmaller;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getPSShrinkLarger() {
+ GBool f;
+
+ lockGlobalParams;
+ f = psShrinkLarger;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getPSCenter() {
+ GBool f;
+
+ lockGlobalParams;
+ f = psCenter;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getPSDuplex() {
+ GBool d;
+
+ lockGlobalParams;
+ d = psDuplex;
+ unlockGlobalParams;
+ return d;
+}
+
+PSLevel GlobalParams::getPSLevel() {
+ PSLevel level;
+
+ lockGlobalParams;
+ level = psLevel;
+ unlockGlobalParams;
+ return level;
+}
+
PSFontParam *GlobalParams::getPSFont(GString *fontName) {
- return (PSFontParam *)psFonts->lookup(fontName);
+ PSFontParam *p;
+
+ lockGlobalParams;
+ p = (PSFontParam *)psFonts->lookup(fontName);
+ unlockGlobalParams;
+ return p;
}
PSFontParam *GlobalParams::getPSFont16(GString *fontName,
@@ -868,6 +1148,7 @@ PSFontParam *GlobalParams::getPSFont16(GString *fontName,
PSFontParam *p;
int i;
+ lockGlobalParams;
p = NULL;
if (fontName) {
for (i = 0; i < psNamedFonts16->getLength(); ++i) {
@@ -889,74 +1170,288 @@ PSFontParam *GlobalParams::getPSFont16(GString *fontName,
p = NULL;
}
}
+ unlockGlobalParams;
return p;
}
-GString *GlobalParams::findFontFile(GString *fontName,
- char *ext1, char *ext2) {
+GBool GlobalParams::getPSEmbedType1() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedType1;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSEmbedTrueType() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedTrueType;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSEmbedCIDPostScript() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedCIDPostScript;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSEmbedCIDTrueType() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedCIDTrueType;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSOPI() {
+ GBool opi;
+
+ lockGlobalParams;
+ opi = psOPI;
+ unlockGlobalParams;
+ return opi;
+}
+
+GBool GlobalParams::getPSASCIIHex() {
+ GBool ah;
+
+ lockGlobalParams;
+ ah = psASCIIHex;
+ unlockGlobalParams;
+ return ah;
+}
+
+GString *GlobalParams::getTextEncodingName() {
+ GString *s;
+
+ lockGlobalParams;
+ s = textEncoding->copy();
+ unlockGlobalParams;
+ return s;
+}
+
+EndOfLineKind GlobalParams::getTextEOL() {
+ EndOfLineKind eol;
+
+ lockGlobalParams;
+ eol = textEOL;
+ unlockGlobalParams;
+ return eol;
+}
+
+GBool GlobalParams::getTextPageBreaks() {
+ GBool pageBreaks;
+
+ lockGlobalParams;
+ pageBreaks = textPageBreaks;
+ unlockGlobalParams;
+ return pageBreaks;
+}
+
+GBool GlobalParams::getTextKeepTinyChars() {
+ GBool tiny;
+
+ lockGlobalParams;
+ tiny = textKeepTinyChars;
+ unlockGlobalParams;
+ return tiny;
+}
+
+GString *GlobalParams::findFontFile(GString *fontName, char **exts) {
GString *dir, *fileName;
+ char **ext;
FILE *f;
int i;
+ lockGlobalParams;
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);
- if ((f = fopen(fileName->getCString(), "r"))) {
+ fileName->append(*ext);
+ if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
+ unlockGlobalParams;
return fileName;
}
delete fileName;
}
}
+ unlockGlobalParams;
return NULL;
}
+GString *GlobalParams::getInitialZoom() {
+ GString *s;
+
+ lockGlobalParams;
+ s = initialZoom->copy();
+ unlockGlobalParams;
+ return s;
+}
+
+GBool GlobalParams::getEnableT1lib() {
+ GBool f;
+
+ lockGlobalParams;
+ f = enableT1lib;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getEnableFreeType() {
+ GBool f;
+
+ lockGlobalParams;
+ f = enableFreeType;
+ unlockGlobalParams;
+ return f;
+}
+
+
+GBool GlobalParams::getAntialias() {
+ GBool f;
+
+ lockGlobalParams;
+ f = antialias;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getMapNumericCharNames() {
+ GBool map;
+
+ lockGlobalParams;
+ map = mapNumericCharNames;
+ unlockGlobalParams;
+ return map;
+}
+
+GBool GlobalParams::getPrintCommands() {
+ GBool p;
+
+ lockGlobalParams;
+ p = printCommands;
+ unlockGlobalParams;
+ return p;
+}
+
+GBool GlobalParams::getErrQuiet() {
+ GBool q;
+
+ lockGlobalParams;
+ q = errQuiet;
+ unlockGlobalParams;
+ return q;
+}
+
CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
- return cidToUnicodeCache->getCIDToUnicode(collection);
+ GString *fileName;
+ CharCodeToUnicode *ctu;
+
+ lockGlobalParams;
+ if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
+ if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
+ (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
+ cidToUnicodeCache->add(ctu);
+ }
+ }
+ unlockGlobalParams;
+ return ctu;
+}
+
+CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
+ CharCodeToUnicode *ctu;
+ GHashIter *iter;
+ GString *fontPattern, *fileName;
+
+ lockGlobalParams;
+ fileName = NULL;
+ unicodeToUnicodes->startIter(&iter);
+ while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
+ if (strstr(fontName->getCString(), fontPattern->getCString())) {
+ unicodeToUnicodes->killIter(&iter);
+ break;
+ }
+ fileName = NULL;
+ }
+ if (fileName) {
+ if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
+ if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
+ unicodeToUnicodeCache->add(ctu);
+ }
+ }
+ } else {
+ ctu = NULL;
+ }
+ unlockGlobalParams;
+ return ctu;
}
UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
+ return getUnicodeMap2(encodingName);
+}
+
+UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
UnicodeMap *map;
- if ((map = getResidentUnicodeMap(encodingName))) {
- map->incRefCnt();
- return map;
+ if (!(map = getResidentUnicodeMap(encodingName))) {
+ lockUnicodeMapCache;
+ map = unicodeMapCache->getUnicodeMap(encodingName);
+ unlockUnicodeMapCache;
}
- return unicodeMapCache->getUnicodeMap(encodingName);
+ return map;
}
CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
- return cMapCache->getCMap(collection, cMapName);
+ CMap *cMap;
+
+ lockCMapCache;
+ cMap = cMapCache->getCMap(collection, cMapName);
+ unlockCMapCache;
+ return cMap;
}
UnicodeMap *GlobalParams::getTextEncoding() {
- return getUnicodeMap(textEncoding);
+ return getUnicodeMap2(textEncoding);
}
//------------------------------------------------------------------------
// functions to set parameters
//------------------------------------------------------------------------
+void GlobalParams::addDisplayFont(DisplayFontParam *param) {
+ DisplayFontParam *old;
+
+ lockGlobalParams;
+ if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
+ delete old;
+ }
+ displayFonts->add(param->name, param);
+ unlockGlobalParams;
+}
+
void GlobalParams::setPSFile(char *file) {
+ lockGlobalParams;
if (psFile) {
delete psFile;
}
psFile = new GString(file);
+ unlockGlobalParams;
}
GBool GlobalParams::setPSPaperSize(char *size) {
- if (!strcmp(size, "letter")) {
+ lockGlobalParams;
+ if (!strcmp(size, "match")) {
+ psPaperWidth = psPaperHeight = -1;
+ } else if (!strcmp(size, "letter")) {
psPaperWidth = 612;
psPaperHeight = 792;
} else if (!strcmp(size, "legal")) {
@@ -969,57 +1464,122 @@ GBool GlobalParams::setPSPaperSize(char *size) {
psPaperWidth = 842;
psPaperHeight = 1190;
} else {
+ unlockGlobalParams;
return gFalse;
}
+ psImageableLLX = psImageableLLY = 0;
+ psImageableURX = psPaperWidth;
+ psImageableURY = psPaperHeight;
+ unlockGlobalParams;
return gTrue;
}
void GlobalParams::setPSPaperWidth(int width) {
+ lockGlobalParams;
psPaperWidth = width;
+ psImageableLLX = 0;
+ psImageableURX = psPaperWidth;
+ unlockGlobalParams;
}
void GlobalParams::setPSPaperHeight(int height) {
+ lockGlobalParams;
psPaperHeight = height;
+ psImageableLLY = 0;
+ psImageableURY = psPaperHeight;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
+ lockGlobalParams;
+ psImageableLLX = llx;
+ psImageableLLY = lly;
+ psImageableURX = urx;
+ psImageableURY = ury;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSCrop(GBool crop) {
+ lockGlobalParams;
+ psCrop = crop;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSExpandSmaller(GBool expand) {
+ lockGlobalParams;
+ psExpandSmaller = expand;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSShrinkLarger(GBool shrink) {
+ lockGlobalParams;
+ psShrinkLarger = shrink;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSCenter(GBool center) {
+ lockGlobalParams;
+ psCenter = center;
+ unlockGlobalParams;
}
void GlobalParams::setPSDuplex(GBool duplex) {
+ lockGlobalParams;
psDuplex = duplex;
+ unlockGlobalParams;
}
void GlobalParams::setPSLevel(PSLevel level) {
+ lockGlobalParams;
psLevel = level;
+ unlockGlobalParams;
}
void GlobalParams::setPSEmbedType1(GBool embed) {
+ lockGlobalParams;
psEmbedType1 = embed;
+ unlockGlobalParams;
}
void GlobalParams::setPSEmbedTrueType(GBool embed) {
+ lockGlobalParams;
psEmbedTrueType = embed;
+ unlockGlobalParams;
}
void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
+ lockGlobalParams;
psEmbedCIDPostScript = embed;
+ unlockGlobalParams;
}
void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
+ lockGlobalParams;
psEmbedCIDTrueType = embed;
+ unlockGlobalParams;
}
void GlobalParams::setPSOPI(GBool opi) {
+ lockGlobalParams;
psOPI = opi;
+ unlockGlobalParams;
}
void GlobalParams::setPSASCIIHex(GBool hex) {
+ lockGlobalParams;
psASCIIHex = hex;
+ unlockGlobalParams;
}
void GlobalParams::setTextEncoding(char *encodingName) {
+ lockGlobalParams;
delete textEncoding;
textEncoding = new GString(encodingName);
+ unlockGlobalParams;
}
GBool GlobalParams::setTextEOL(char *s) {
+ lockGlobalParams;
if (!strcmp(s, "unix")) {
textEOL = eolUnix;
} else if (!strcmp(s, "dos")) {
@@ -1027,39 +1587,74 @@ GBool GlobalParams::setTextEOL(char *s) {
} else if (!strcmp(s, "mac")) {
textEOL = eolMac;
} else {
+ unlockGlobalParams;
return gFalse;
}
+ unlockGlobalParams;
return gTrue;
}
+void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
+ lockGlobalParams;
+ textPageBreaks = pageBreaks;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setTextKeepTinyChars(GBool keep) {
+ lockGlobalParams;
+ textKeepTinyChars = keep;
+ unlockGlobalParams;
+}
+
void GlobalParams::setInitialZoom(char *s) {
+ lockGlobalParams;
delete initialZoom;
initialZoom = new GString(s);
+ unlockGlobalParams;
}
-GBool GlobalParams::setT1libControl(char *s) {
- return setFontRastControl(&t1libControl, s);
+GBool GlobalParams::setEnableT1lib(char *s) {
+ GBool ok;
+
+ lockGlobalParams;
+ ok = parseYesNo2(s, &enableT1lib);
+ unlockGlobalParams;
+ return ok;
}
-GBool GlobalParams::setFreeTypeControl(char *s) {
- return setFontRastControl(&freetypeControl, s);
+GBool GlobalParams::setEnableFreeType(char *s) {
+ GBool ok;
+
+ lockGlobalParams;
+ ok = parseYesNo2(s, &enableFreeType);
+ unlockGlobalParams;
+ return ok;
}
-GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
- if (!strcmp(s, "none")) {
- *val = fontRastNone;
- } else if (!strcmp(s, "plain")) {
- *val = fontRastPlain;
- } else if (!strcmp(s, "low")) {
- *val = fontRastAALow;
- } else if (!strcmp(s, "high")) {
- *val = fontRastAAHigh;
- } else {
- return gFalse;
- }
- return gTrue;
+
+GBool GlobalParams::setAntialias(char *s) {
+ GBool ok;
+
+ lockGlobalParams;
+ ok = parseYesNo2(s, &antialias);
+ unlockGlobalParams;
+ return ok;
+}
+
+void GlobalParams::setMapNumericCharNames(GBool map) {
+ lockGlobalParams;
+ mapNumericCharNames = map;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPrintCommands(GBool printCommandsA) {
+ lockGlobalParams;
+ printCommands = printCommandsA;
+ unlockGlobalParams;
}
void GlobalParams::setErrQuiet(GBool errQuietA) {
+ lockGlobalParams;
errQuiet = errQuietA;
+ unlockGlobalParams;
}
diff --git a/pdf2swf/xpdf/GlobalParams.h b/pdf2swf/xpdf/GlobalParams.h
index b6511109..93ec06aa 100644
--- a/pdf2swf/xpdf/GlobalParams.h
+++ b/pdf2swf/xpdf/GlobalParams.h
@@ -2,14 +2,16 @@
//
// GlobalParams.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef GLOBALPARAMS_H
#define GLOBALPARAMS_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -17,12 +19,16 @@
#include "gtypes.h"
#include "CharTypes.h"
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
class GString;
class GList;
class GHash;
class NameToCharCode;
class CharCodeToUnicode;
-class CIDToUnicodeCache;
+class CharCodeToUnicodeCache;
class UnicodeMap;
class UnicodeMapCache;
class CMap;
@@ -37,7 +43,6 @@ extern GlobalParams *globalParams;
//------------------------------------------------------------------------
enum DisplayFontParamKind {
- displayFontX,
displayFontT1,
displayFontTT
};
@@ -51,10 +56,6 @@ public:
DisplayFontParamKind kind;
union {
struct {
- GString *xlfd;
- GString *encoding;
- } x;
- struct {
GString *fileName;
} t1;
struct {
@@ -63,18 +64,9 @@ public:
};
DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
- DisplayFontParam(char *nameA, char *xlfdA, char *encodingA);
~DisplayFontParam();
};
-// Font rasterizer control.
-enum FontRastControl {
- fontRastNone, // don't use this rasterizer
- fontRastPlain, // use it, without anti-aliasing
- fontRastAALow, // use it, with low-level anti-aliasing
- fontRastAAHigh // use it, with high-level anti-aliasing
-};
-
//------------------------------------------------------------------------
class PSFontParam {
@@ -123,53 +115,71 @@ public:
~GlobalParams();
+ void setupBaseFonts(char *dir);
+
//----- accessors
CharCode getMacRomanCharCode(char *charName);
Unicode mapNameToUnicode(char *charName);
- FILE *getCIDToUnicodeFile(GString *collection);
UnicodeMap *getResidentUnicodeMap(GString *encodingName);
FILE *getUnicodeMapFile(GString *encodingName);
FILE *findCMapFile(GString *collection, GString *cMapName);
FILE *findToUnicodeFile(GString *name);
DisplayFontParam *getDisplayFont(GString *fontName);
DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
- GString *getPSFile() { return psFile; }
- int getPSPaperWidth() { return psPaperWidth; }
- int getPSPaperHeight() { return psPaperHeight; }
- GBool getPSDuplex() { return psDuplex; }
- PSLevel getPSLevel() { return psLevel; }
+ GString *getPSFile();
+ int getPSPaperWidth();
+ int getPSPaperHeight();
+ void getPSImageableArea(int *llx, int *lly, int *urx, int *ury);
+ GBool getPSDuplex();
+ GBool getPSCrop();
+ GBool getPSExpandSmaller();
+ GBool getPSShrinkLarger();
+ GBool getPSCenter();
+ PSLevel getPSLevel();
PSFontParam *getPSFont(GString *fontName);
PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode);
- GBool getPSEmbedType1() { return psEmbedType1; }
- GBool getPSEmbedTrueType() { return psEmbedTrueType; }
- GBool getPSEmbedCIDPostScript() { return psEmbedCIDPostScript; }
- GBool getPSEmbedCIDTrueType() { return psEmbedCIDTrueType; }
- GBool getPSOPI() { return psOPI; }
- GBool getPSASCIIHex() { return psASCIIHex; }
- GString *getTextEncodingName() { return textEncoding; }
- EndOfLineKind getTextEOL() { return textEOL; }
- GString *findFontFile(GString *fontName, char *ext1, char *ext2);
- GString *getInitialZoom() { return initialZoom; }
- FontRastControl getT1libControl() { return t1libControl; }
- FontRastControl getFreeTypeControl() { return freetypeControl; }
+ GBool getPSEmbedType1();
+ GBool getPSEmbedTrueType();
+ GBool getPSEmbedCIDPostScript();
+ GBool getPSEmbedCIDTrueType();
+ GBool getPSOPI();
+ GBool getPSASCIIHex();
+ GString *getTextEncodingName();
+ EndOfLineKind getTextEOL();
+ GBool getTextPageBreaks();
+ GBool getTextKeepTinyChars();
+ GString *findFontFile(GString *fontName, char **exts);
+ GString *getInitialZoom();
+ GBool getEnableT1lib();
+ GBool getEnableFreeType();
+ GBool getAntialias();
GString *getURLCommand() { return urlCommand; }
- GBool getMapNumericCharNames() { return mapNumericCharNames; }
- GBool getErrQuiet() { return errQuiet; }
+ GString *getMovieCommand() { return movieCommand; }
+ GBool getMapNumericCharNames();
+ GBool getPrintCommands();
+ GBool getErrQuiet();
CharCodeToUnicode *getCIDToUnicode(GString *collection);
+ CharCodeToUnicode *getUnicodeToUnicode(GString *fontName);
UnicodeMap *getUnicodeMap(GString *encodingName);
CMap *getCMap(GString *collection, GString *cMapName);
UnicodeMap *getTextEncoding();
//----- functions to set parameters
+ void addDisplayFont(DisplayFontParam *param);
void setPSFile(char *file);
GBool setPSPaperSize(char *size);
void setPSPaperWidth(int width);
void setPSPaperHeight(int height);
+ void setPSImageableArea(int llx, int lly, int urx, int ury);
void setPSDuplex(GBool duplex);
+ void setPSCrop(GBool crop);
+ void setPSExpandSmaller(GBool expand);
+ void setPSShrinkLarger(GBool shrink);
+ void setPSCenter(GBool center);
void setPSLevel(PSLevel level);
void setPSEmbedType1(GBool embed);
void setPSEmbedTrueType(GBool embed);
@@ -179,9 +189,14 @@ public:
void setPSASCIIHex(GBool hex);
void setTextEncoding(char *encodingName);
GBool setTextEOL(char *s);
+ void setTextPageBreaks(GBool pageBreaks);
+ void setTextKeepTinyChars(GBool keep);
void setInitialZoom(char *s);
- GBool setT1libControl(char *s);
- GBool setFreeTypeControl(char *s);
+ GBool setEnableT1lib(char *s);
+ GBool setEnableFreeType(char *s);
+ GBool setAntialias(char *s);
+ void setMapNumericCharNames(GBool map);
+ void setPrintCommands(GBool printCommandsA);
void setErrQuiet(GBool errQuietA);
private:
@@ -189,6 +204,7 @@ private:
void parseFile(GString *fileName, FILE *f);
void parseNameToUnicode(GList *tokens, GString *fileName, int line);
void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
+ void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line);
void parseUnicodeMap(GList *tokens, GString *fileName, int line);
void parseCMapDir(GList *tokens, GString *fileName, int line);
void parseToUnicodeDir(GList *tokens, GString *fileName, int line);
@@ -197,6 +213,7 @@ private:
GString *fileName, int line);
void parsePSFile(GList *tokens, GString *fileName, int line);
void parsePSPaperSize(GList *tokens, GString *fileName, int line);
+ void parsePSImageableArea(GList *tokens, GString *fileName, int line);
void parsePSLevel(GList *tokens, GString *fileName, int line);
void parsePSFont(GList *tokens, GString *fileName, int line);
void parsePSFont16(char *cmdName, GList *fontList,
@@ -205,12 +222,12 @@ private:
void parseTextEOL(GList *tokens, GString *fileName, int line);
void parseFontDir(GList *tokens, GString *fileName, int line);
void parseInitialZoom(GList *tokens, GString *fileName, int line);
- void parseFontRastControl(char *cmdName, FontRastControl *val,
- GList *tokens, GString *fileName, int line);
- void parseURLCommand(GList *tokens, GString *fileName, int line);
+ void parseCommand(char *cmdName, GString **val,
+ GList *tokens, GString *fileName, int line);
void parseYesNo(char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line);
- GBool setFontRastControl(FontRastControl *val, char *s);
+ GBool parseYesNo2(char *token, GBool *flag);
+ UnicodeMap *getUnicodeMap2(GString *encodingName);
//----- static tables
@@ -224,6 +241,8 @@ private:
GHash *cidToUnicodes; // files for mappings from char collections
// to Unicode, indexed by collection name
// [GString]
+ GHash *unicodeToUnicodes; // files for Unicode-to-Unicode mappings,
+ // indexed by font name pattern [GString]
GHash *residentUnicodeMaps; // mappings from Unicode to char codes,
// indexed by encoding name [UnicodeMap]
GHash *unicodeMaps; // files for mappings from Unicode to char
@@ -240,6 +259,14 @@ private:
GString *psFile; // PostScript file or command (for xpdf)
int psPaperWidth; // paper size, in PostScript points, for
int psPaperHeight; // PostScript output
+ int psImageableLLX, // imageable area, in PostScript points,
+ psImageableLLY, // for PostScript output
+ psImageableURX,
+ psImageableURY;
+ GBool psCrop; // crop PS output to CropBox
+ GBool psExpandSmaller; // expand smaller pages to fill paper
+ GBool psShrinkLarger; // shrink larger pages to fit paper
+ GBool psCenter; // center pages on the paper
GBool psDuplex; // enable duplexing in PostScript?
PSLevel psLevel; // PostScript level to generate
GHash *psFonts; // PostScript font info, indexed by PDF
@@ -256,18 +283,29 @@ private:
// output
EndOfLineKind textEOL; // type of EOL marker to use for text
// output
+ GBool textPageBreaks; // insert end-of-page markers?
+ GBool textKeepTinyChars; // keep all characters in text output
GList *fontDirs; // list of font dirs [GString]
GString *initialZoom; // initial zoom level
- FontRastControl t1libControl; // t1lib rasterization mode
- FontRastControl // FreeType rasterization mode
- freetypeControl;
+ GBool enableT1lib; // t1lib enable flag
+ GBool enableFreeType; // FreeType enable flag
+ GBool antialias; // anti-aliasing enable flag
GString *urlCommand; // command executed for URL links
+ GString *movieCommand; // command executed for movie annotations
GBool mapNumericCharNames; // map numeric char names (from font subsets)?
+ GBool printCommands; // print the drawing commands
GBool errQuiet; // suppress error messages?
- CIDToUnicodeCache *cidToUnicodeCache;
+ CharCodeToUnicodeCache *cidToUnicodeCache;
+ CharCodeToUnicodeCache *unicodeToUnicodeCache;
UnicodeMapCache *unicodeMapCache;
CMapCache *cMapCache;
+
+#if MULTITHREADED
+ GMutex mutex;
+ GMutex unicodeMapCacheMutex;
+ GMutex cMapCacheMutex;
+#endif
};
#endif
diff --git a/pdf2swf/xpdf/JArithmeticDecoder.cc b/pdf2swf/xpdf/JArithmeticDecoder.cc
new file mode 100644
index 00000000..fd297445
--- /dev/null
+++ b/pdf2swf/xpdf/JArithmeticDecoder.cc
@@ -0,0 +1,300 @@
+//========================================================================
+//
+// JArithmeticDecoder.cc
+//
+// Copyright 2002-2004 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "Object.h"
+#include "Stream.h"
+#include "JArithmeticDecoder.h"
+
+//------------------------------------------------------------------------
+// JArithmeticDecoderStates
+//------------------------------------------------------------------------
+
+JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) {
+ contextSize = contextSizeA;
+ cxTab = (Guchar *)gmalloc(contextSize * sizeof(Guchar));
+ reset();
+}
+
+JArithmeticDecoderStats::~JArithmeticDecoderStats() {
+ gfree(cxTab);
+}
+
+JArithmeticDecoderStats *JArithmeticDecoderStats::copy() {
+ JArithmeticDecoderStats *stats;
+
+ stats = new JArithmeticDecoderStats(contextSize);
+ memcpy(stats->cxTab, cxTab, contextSize);
+ return stats;
+}
+
+void JArithmeticDecoderStats::reset() {
+ memset(cxTab, 0, contextSize);
+}
+
+void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) {
+ memcpy(cxTab, stats->cxTab, contextSize);
+}
+
+void JArithmeticDecoderStats::setEntry(Guint cx, int i, int mps) {
+ cxTab[cx] = (i << 1) + mps;
+}
+
+//------------------------------------------------------------------------
+// JArithmeticDecoder
+//------------------------------------------------------------------------
+
+Guint JArithmeticDecoder::qeTab[47] = {
+ 0x56010000, 0x34010000, 0x18010000, 0x0AC10000,
+ 0x05210000, 0x02210000, 0x56010000, 0x54010000,
+ 0x48010000, 0x38010000, 0x30010000, 0x24010000,
+ 0x1C010000, 0x16010000, 0x56010000, 0x54010000,
+ 0x51010000, 0x48010000, 0x38010000, 0x34010000,
+ 0x30010000, 0x28010000, 0x24010000, 0x22010000,
+ 0x1C010000, 0x18010000, 0x16010000, 0x14010000,
+ 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000,
+ 0x08A10000, 0x05210000, 0x04410000, 0x02A10000,
+ 0x02210000, 0x01410000, 0x01110000, 0x00850000,
+ 0x00490000, 0x00250000, 0x00150000, 0x00090000,
+ 0x00050000, 0x00010000, 0x56010000
+};
+
+int JArithmeticDecoder::nmpsTab[47] = {
+ 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46
+};
+
+int JArithmeticDecoder::nlpsTab[47] = {
+ 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14,
+ 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46
+};
+
+int JArithmeticDecoder::switchTab[47] = {
+ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+JArithmeticDecoder::JArithmeticDecoder() {
+ str = NULL;
+}
+
+JArithmeticDecoder::~JArithmeticDecoder() {
+ while (dataLen > 0) {
+ readByte();
+ }
+}
+
+inline Guint JArithmeticDecoder::readByte() {
+ if (dataLen == 0) {
+ return 0xff;
+ }
+ if (dataLen > 0) {
+ --dataLen;
+ }
+ return (Guint)str->getChar() & 0xff;
+}
+
+void JArithmeticDecoder::start() {
+ buf0 = readByte();
+ buf1 = readByte();
+
+ // INITDEC
+ c = (buf0 ^ 0xff) << 16;
+ byteIn();
+ c <<= 7;
+ ct -= 7;
+ a = 0x80000000;
+}
+
+int JArithmeticDecoder::decodeBit(Guint context,
+ JArithmeticDecoderStats *stats) {
+ int bit;
+ Guint qe;
+ int iCX, mpsCX;
+
+ iCX = stats->cxTab[context] >> 1;
+ mpsCX = stats->cxTab[context] & 1;
+ qe = qeTab[iCX];
+ a -= qe;
+ if (c < a) {
+ if (a & 0x80000000) {
+ bit = mpsCX;
+ } else {
+ // MPS_EXCHANGE
+ if (a < qe) {
+ bit = 1 - mpsCX;
+ if (switchTab[iCX]) {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
+ } else {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
+ }
+ } else {
+ bit = mpsCX;
+ stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
+ }
+ // RENORMD
+ do {
+ if (ct == 0) {
+ byteIn();
+ }
+ a <<= 1;
+ c <<= 1;
+ --ct;
+ } while (!(a & 0x80000000));
+ }
+ } else {
+ c -= a;
+ // LPS_EXCHANGE
+ if (a < qe) {
+ bit = mpsCX;
+ stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
+ } else {
+ bit = 1 - mpsCX;
+ if (switchTab[iCX]) {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
+ } else {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
+ }
+ }
+ a = qe;
+ // RENORMD
+ do {
+ if (ct == 0) {
+ byteIn();
+ }
+ a <<= 1;
+ c <<= 1;
+ --ct;
+ } while (!(a & 0x80000000));
+ }
+ return bit;
+}
+
+int JArithmeticDecoder::decodeByte(Guint context,
+ JArithmeticDecoderStats *stats) {
+ int byte;
+ int i;
+
+ byte = 0;
+ for (i = 0; i < 8; ++i) {
+ byte = (byte << 1) | decodeBit(context, stats);
+ }
+ return byte;
+}
+
+GBool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) {
+ int s;
+ Guint v;
+ int i;
+
+ prev = 1;
+ s = decodeIntBit(stats);
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ v = 0;
+ for (i = 0; i < 32; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 4436;
+ } else {
+ v = 0;
+ for (i = 0; i < 12; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 340;
+ }
+ } else {
+ v = 0;
+ for (i = 0; i < 8; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 84;
+ }
+ } else {
+ v = 0;
+ for (i = 0; i < 6; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 20;
+ }
+ } else {
+ v = decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ v += 4;
+ }
+ } else {
+ v = decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ }
+
+ if (s) {
+ if (v == 0) {
+ return gFalse;
+ }
+ *x = -(int)v;
+ } else {
+ *x = (int)v;
+ }
+ return gTrue;
+}
+
+int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) {
+ int bit;
+
+ bit = decodeBit(prev, stats);
+ if (prev < 0x100) {
+ prev = (prev << 1) | bit;
+ } else {
+ prev = (((prev << 1) | bit) & 0x1ff) | 0x100;
+ }
+ return bit;
+}
+
+Guint JArithmeticDecoder::decodeIAID(Guint codeLen,
+ JArithmeticDecoderStats *stats) {
+ Guint i;
+ int bit;
+
+ prev = 1;
+ for (i = 0; i < codeLen; ++i) {
+ bit = decodeBit(prev, stats);
+ prev = (prev << 1) | bit;
+ }
+ return prev - (1 << codeLen);
+}
+
+void JArithmeticDecoder::byteIn() {
+ if (buf0 == 0xff) {
+ if (buf1 > 0x8f) {
+ ct = 8;
+ } else {
+ buf0 = buf1;
+ buf1 = readByte();
+ c = c + 0xfe00 - (buf0 << 9);
+ ct = 7;
+ }
+ } else {
+ buf0 = buf1;
+ buf1 = readByte();
+ c = c + 0xff00 - (buf0 << 8);
+ ct = 8;
+ }
+}
diff --git a/pdf2swf/xpdf/JArithmeticDecoder.h b/pdf2swf/xpdf/JArithmeticDecoder.h
new file mode 100644
index 00000000..a348017d
--- /dev/null
+++ b/pdf2swf/xpdf/JArithmeticDecoder.h
@@ -0,0 +1,91 @@
+//========================================================================
+//
+// JArithmeticDecoder.h
+//
+// Arithmetic decoder used by the JBIG2 and JPEG2000 decoders.
+//
+// Copyright 2002-2004 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef JARITHMETICDECODER_H
+#define JARITHMETICDECODER_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+class Stream;
+
+//------------------------------------------------------------------------
+// JArithmeticDecoderStats
+//------------------------------------------------------------------------
+
+class JArithmeticDecoderStats {
+public:
+
+ JArithmeticDecoderStats(int contextSizeA);
+ ~JArithmeticDecoderStats();
+ JArithmeticDecoderStats *copy();
+ void reset();
+ int getContextSize() { return contextSize; }
+ void copyFrom(JArithmeticDecoderStats *stats);
+ void setEntry(Guint cx, int i, int mps);
+
+private:
+
+ Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx]
+ int contextSize;
+
+ friend class JArithmeticDecoder;
+};
+
+//------------------------------------------------------------------------
+// JArithmeticDecoder
+//------------------------------------------------------------------------
+
+class JArithmeticDecoder {
+public:
+
+ JArithmeticDecoder();
+ ~JArithmeticDecoder();
+ void setStream(Stream *strA)
+ { str = strA; dataLen = -1; }
+ void setStream(Stream *strA, int dataLenA)
+ { str = strA; dataLen = dataLenA; }
+ void start();
+ int decodeBit(Guint context, JArithmeticDecoderStats *stats);
+ int decodeByte(Guint context, JArithmeticDecoderStats *stats);
+
+ // Returns false for OOB, otherwise sets *<x> and returns true.
+ GBool decodeInt(int *x, JArithmeticDecoderStats *stats);
+
+ Guint decodeIAID(Guint codeLen,
+ JArithmeticDecoderStats *stats);
+
+private:
+
+ Guint readByte();
+ int decodeIntBit(JArithmeticDecoderStats *stats);
+ void byteIn();
+
+ static Guint qeTab[47];
+ static int nmpsTab[47];
+ static int nlpsTab[47];
+ static int switchTab[47];
+
+ Guint buf0, buf1;
+ Guint c, a;
+ int ct;
+
+ Guint prev; // for the integer decoder
+
+ Stream *str;
+ int dataLen;
+};
+
+#endif
diff --git a/pdf2swf/xpdf/JBIG2Stream.cc b/pdf2swf/xpdf/JBIG2Stream.cc
new file mode 100644
index 00000000..c1bf4f78
--- /dev/null
+++ b/pdf2swf/xpdf/JBIG2Stream.cc
@@ -0,0 +1,3337 @@
+//========================================================================
+//
+// JBIG2Stream.cc
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include "GList.h"
+#include "Error.h"
+#include "JArithmeticDecoder.h"
+#include "JBIG2Stream.h"
+
+//~ share these tables
+#include "Stream-CCITT.h"
+
+//------------------------------------------------------------------------
+
+static int contextSize[4] = { 16, 13, 10, 10 };
+static int refContextSize[2] = { 13, 10 };
+
+//------------------------------------------------------------------------
+// JBIG2HuffmanTable
+//------------------------------------------------------------------------
+
+#define jbig2HuffmanLOW 0xfffffffd
+#define jbig2HuffmanOOB 0xfffffffe
+#define jbig2HuffmanEOT 0xffffffff
+
+struct JBIG2HuffmanTable {
+ int val;
+ Guint prefixLen;
+ Guint rangeLen; // can also be LOW, OOB, or EOT
+ Guint prefix;
+};
+
+JBIG2HuffmanTable huffTableA[] = {
+ { 0, 1, 4, 0x000 },
+ { 16, 2, 8, 0x002 },
+ { 272, 3, 16, 0x006 },
+ { 65808, 3, 32, 0x007 },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableB[] = {
+ { 0, 1, 0, 0x000 },
+ { 1, 2, 0, 0x002 },
+ { 2, 3, 0, 0x006 },
+ { 3, 4, 3, 0x00e },
+ { 11, 5, 6, 0x01e },
+ { 75, 6, 32, 0x03e },
+ { 0, 6, jbig2HuffmanOOB, 0x03f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableC[] = {
+ { 0, 1, 0, 0x000 },
+ { 1, 2, 0, 0x002 },
+ { 2, 3, 0, 0x006 },
+ { 3, 4, 3, 0x00e },
+ { 11, 5, 6, 0x01e },
+ { 0, 6, jbig2HuffmanOOB, 0x03e },
+ { 75, 7, 32, 0x0fe },
+ { -256, 8, 8, 0x0fe },
+ { -257, 8, jbig2HuffmanLOW, 0x0ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableD[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 0, 0x002 },
+ { 3, 3, 0, 0x006 },
+ { 4, 4, 3, 0x00e },
+ { 12, 5, 6, 0x01e },
+ { 76, 5, 32, 0x01f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableE[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 0, 0x002 },
+ { 3, 3, 0, 0x006 },
+ { 4, 4, 3, 0x00e },
+ { 12, 5, 6, 0x01e },
+ { 76, 6, 32, 0x03e },
+ { -255, 7, 8, 0x07e },
+ { -256, 7, jbig2HuffmanLOW, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableF[] = {
+ { 0, 2, 7, 0x000 },
+ { 128, 3, 7, 0x002 },
+ { 256, 3, 8, 0x003 },
+ { -1024, 4, 9, 0x008 },
+ { -512, 4, 8, 0x009 },
+ { -256, 4, 7, 0x00a },
+ { -32, 4, 5, 0x00b },
+ { 512, 4, 9, 0x00c },
+ { 1024, 4, 10, 0x00d },
+ { -2048, 5, 10, 0x01c },
+ { -128, 5, 6, 0x01d },
+ { -64, 5, 5, 0x01e },
+ { -2049, 6, jbig2HuffmanLOW, 0x03e },
+ { 2048, 6, 32, 0x03f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableG[] = {
+ { -512, 3, 8, 0x000 },
+ { 256, 3, 8, 0x001 },
+ { 512, 3, 9, 0x002 },
+ { 1024, 3, 10, 0x003 },
+ { -1024, 4, 9, 0x008 },
+ { -256, 4, 7, 0x009 },
+ { -32, 4, 5, 0x00a },
+ { 0, 4, 5, 0x00b },
+ { 128, 4, 7, 0x00c },
+ { -128, 5, 6, 0x01a },
+ { -64, 5, 5, 0x01b },
+ { 32, 5, 5, 0x01c },
+ { 64, 5, 6, 0x01d },
+ { -1025, 5, jbig2HuffmanLOW, 0x01e },
+ { 2048, 5, 32, 0x01f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableH[] = {
+ { 0, 2, 1, 0x000 },
+ { 0, 2, jbig2HuffmanOOB, 0x001 },
+ { 4, 3, 4, 0x004 },
+ { -1, 4, 0, 0x00a },
+ { 22, 4, 4, 0x00b },
+ { 38, 4, 5, 0x00c },
+ { 2, 5, 0, 0x01a },
+ { 70, 5, 6, 0x01b },
+ { 134, 5, 7, 0x01c },
+ { 3, 6, 0, 0x03a },
+ { 20, 6, 1, 0x03b },
+ { 262, 6, 7, 0x03c },
+ { 646, 6, 10, 0x03d },
+ { -2, 7, 0, 0x07c },
+ { 390, 7, 8, 0x07d },
+ { -15, 8, 3, 0x0fc },
+ { -5, 8, 1, 0x0fd },
+ { -7, 9, 1, 0x1fc },
+ { -3, 9, 0, 0x1fd },
+ { -16, 9, jbig2HuffmanLOW, 0x1fe },
+ { 1670, 9, 32, 0x1ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableI[] = {
+ { 0, 2, jbig2HuffmanOOB, 0x000 },
+ { -1, 3, 1, 0x002 },
+ { 1, 3, 1, 0x003 },
+ { 7, 3, 5, 0x004 },
+ { -3, 4, 1, 0x00a },
+ { 43, 4, 5, 0x00b },
+ { 75, 4, 6, 0x00c },
+ { 3, 5, 1, 0x01a },
+ { 139, 5, 7, 0x01b },
+ { 267, 5, 8, 0x01c },
+ { 5, 6, 1, 0x03a },
+ { 39, 6, 2, 0x03b },
+ { 523, 6, 8, 0x03c },
+ { 1291, 6, 11, 0x03d },
+ { -5, 7, 1, 0x07c },
+ { 779, 7, 9, 0x07d },
+ { -31, 8, 4, 0x0fc },
+ { -11, 8, 2, 0x0fd },
+ { -15, 9, 2, 0x1fc },
+ { -7, 9, 1, 0x1fd },
+ { -32, 9, jbig2HuffmanLOW, 0x1fe },
+ { 3339, 9, 32, 0x1ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableJ[] = {
+ { -2, 2, 2, 0x000 },
+ { 6, 2, 6, 0x001 },
+ { 0, 2, jbig2HuffmanOOB, 0x002 },
+ { -3, 5, 0, 0x018 },
+ { 2, 5, 0, 0x019 },
+ { 70, 5, 5, 0x01a },
+ { 3, 6, 0, 0x036 },
+ { 102, 6, 5, 0x037 },
+ { 134, 6, 6, 0x038 },
+ { 198, 6, 7, 0x039 },
+ { 326, 6, 8, 0x03a },
+ { 582, 6, 9, 0x03b },
+ { 1094, 6, 10, 0x03c },
+ { -21, 7, 4, 0x07a },
+ { -4, 7, 0, 0x07b },
+ { 4, 7, 0, 0x07c },
+ { 2118, 7, 11, 0x07d },
+ { -5, 8, 0, 0x0fc },
+ { 5, 8, 0, 0x0fd },
+ { -22, 8, jbig2HuffmanLOW, 0x0fe },
+ { 4166, 8, 32, 0x0ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableK[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 1, 0x002 },
+ { 4, 4, 0, 0x00c },
+ { 5, 4, 1, 0x00d },
+ { 7, 5, 1, 0x01c },
+ { 9, 5, 2, 0x01d },
+ { 13, 6, 2, 0x03c },
+ { 17, 7, 2, 0x07a },
+ { 21, 7, 3, 0x07b },
+ { 29, 7, 4, 0x07c },
+ { 45, 7, 5, 0x07d },
+ { 77, 7, 6, 0x07e },
+ { 141, 7, 32, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableL[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 0, 0x002 },
+ { 3, 3, 1, 0x006 },
+ { 5, 5, 0, 0x01c },
+ { 6, 5, 1, 0x01d },
+ { 8, 6, 1, 0x03c },
+ { 10, 7, 0, 0x07a },
+ { 11, 7, 1, 0x07b },
+ { 13, 7, 2, 0x07c },
+ { 17, 7, 3, 0x07d },
+ { 25, 7, 4, 0x07e },
+ { 41, 8, 5, 0x0fe },
+ { 73, 8, 32, 0x0ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableM[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 3, 0, 0x004 },
+ { 7, 3, 3, 0x005 },
+ { 3, 4, 0, 0x00c },
+ { 5, 4, 1, 0x00d },
+ { 4, 5, 0, 0x01c },
+ { 15, 6, 1, 0x03a },
+ { 17, 6, 2, 0x03b },
+ { 21, 6, 3, 0x03c },
+ { 29, 6, 4, 0x03d },
+ { 45, 6, 5, 0x03e },
+ { 77, 7, 6, 0x07e },
+ { 141, 7, 32, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableN[] = {
+ { 0, 1, 0, 0x000 },
+ { -2, 3, 0, 0x004 },
+ { -1, 3, 0, 0x005 },
+ { 1, 3, 0, 0x006 },
+ { 2, 3, 0, 0x007 },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableO[] = {
+ { 0, 1, 0, 0x000 },
+ { -1, 3, 0, 0x004 },
+ { 1, 3, 0, 0x005 },
+ { -2, 4, 0, 0x00c },
+ { 2, 4, 0, 0x00d },
+ { -4, 5, 1, 0x01c },
+ { 3, 5, 1, 0x01d },
+ { -8, 6, 2, 0x03c },
+ { 5, 6, 2, 0x03d },
+ { -24, 7, 4, 0x07c },
+ { 9, 7, 4, 0x07d },
+ { -25, 7, jbig2HuffmanLOW, 0x07e },
+ { 25, 7, 32, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+//------------------------------------------------------------------------
+// JBIG2HuffmanDecoder
+//------------------------------------------------------------------------
+
+class JBIG2HuffmanDecoder {
+public:
+
+ JBIG2HuffmanDecoder();
+ ~JBIG2HuffmanDecoder();
+ void setStream(Stream *strA) { str = strA; }
+
+ void reset();
+
+ // Returns false for OOB, otherwise sets *<x> and returns true.
+ GBool decodeInt(int *x, JBIG2HuffmanTable *table);
+
+ Guint readBits(Guint n);
+ Guint readBit();
+
+ // Sort the table by prefix length and assign prefix values.
+ void buildTable(JBIG2HuffmanTable *table, Guint len);
+
+private:
+
+ Stream *str;
+ Guint buf;
+ Guint bufLen;
+};
+
+JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
+ str = NULL;
+ reset();
+}
+
+JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
+}
+
+void JBIG2HuffmanDecoder::reset() {
+ buf = 0;
+ bufLen = 0;
+}
+
+//~ optimize this
+GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
+ Guint i, len, prefix;
+
+ i = 0;
+ len = 0;
+ prefix = 0;
+ while (table[i].rangeLen != jbig2HuffmanEOT) {
+ while (len < table[i].prefixLen) {
+ prefix = (prefix << 1) | readBit();
+ ++len;
+ }
+ 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;
+ }
+ ++i;
+ }
+ return gFalse;
+}
+
+Guint JBIG2HuffmanDecoder::readBits(Guint n) {
+ Guint x, mask, nLeft;
+
+ mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
+ if (bufLen >= n) {
+ x = (buf >> (bufLen - n)) & mask;
+ bufLen -= n;
+ } else {
+ x = buf & ((1 << bufLen) - 1);
+ nLeft = n - bufLen;
+ bufLen = 0;
+ while (nLeft >= 8) {
+ x = (x << 8) | (str->getChar() & 0xff);
+ nLeft -= 8;
+ }
+ if (nLeft > 0) {
+ buf = str->getChar();
+ bufLen = 8 - nLeft;
+ x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
+ }
+ }
+ return x;
+}
+
+Guint JBIG2HuffmanDecoder::readBit() {
+ if (bufLen == 0) {
+ buf = str->getChar();
+ bufLen = 8;
+ }
+ --bufLen;
+ return (buf >> bufLen) & 1;
+}
+
+void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
+ 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 (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
+ prefix <<= table[i].prefixLen - table[i-1].prefixLen;
+ table[i].prefix = prefix++;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2MMRDecoder
+//------------------------------------------------------------------------
+
+class JBIG2MMRDecoder {
+public:
+
+ JBIG2MMRDecoder();
+ ~JBIG2MMRDecoder();
+ void setStream(Stream *strA) { str = strA; }
+ void reset();
+ int get2DCode();
+ int getBlackCode();
+ int getWhiteCode();
+ Guint get24Bits();
+ void skipTo(Guint length);
+
+private:
+
+ Stream *str;
+ Guint buf;
+ Guint bufLen;
+ Guint nBytesRead;
+};
+
+JBIG2MMRDecoder::JBIG2MMRDecoder() {
+ str = NULL;
+ reset();
+}
+
+JBIG2MMRDecoder::~JBIG2MMRDecoder() {
+}
+
+void JBIG2MMRDecoder::reset() {
+ buf = 0;
+ bufLen = 0;
+ nBytesRead = 0;
+}
+
+int JBIG2MMRDecoder::get2DCode() {
+ CCITTCode *p;
+
+ if (bufLen == 0) {
+ buf = str->getChar() & 0xff;
+ bufLen = 8;
+ ++nBytesRead;
+ p = &twoDimTab1[(buf >> 1) & 0x7f];
+ } else if (bufLen == 8) {
+ p = &twoDimTab1[(buf >> 1) & 0x7f];
+ } else {
+ p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
+ if (p->bits < 0 || p->bits > (int)bufLen) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
+ }
+ }
+ if (p->bits < 0) {
+ error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
+ return 0;
+ }
+ bufLen -= p->bits;
+ return p->n;
+}
+
+int JBIG2MMRDecoder::getWhiteCode() {
+ CCITTCode *p;
+ Guint code;
+
+ if (bufLen == 0) {
+ buf = str->getChar() & 0xff;
+ bufLen = 8;
+ ++nBytesRead;
+ }
+ while (1) {
+ if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
+ if (bufLen <= 12) {
+ code = buf << (12 - bufLen);
+ } else {
+ code = buf >> (bufLen - 12);
+ }
+ p = &whiteTab1[code & 0x1f];
+ } else {
+ if (bufLen <= 9) {
+ code = buf << (9 - bufLen);
+ } else {
+ code = buf >> (bufLen - 9);
+ }
+ p = &whiteTab2[code & 0x1ff];
+ }
+ if (p->bits > 0 && p->bits <= (int)bufLen) {
+ bufLen -= p->bits;
+ return p->n;
+ }
+ if (bufLen >= 12) {
+ break;
+ }
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ }
+ error(str->getPos(), "Bad white code in JBIG2 MMR stream");
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ --bufLen;
+ return 1;
+}
+
+int JBIG2MMRDecoder::getBlackCode() {
+ CCITTCode *p;
+ Guint code;
+
+ if (bufLen == 0) {
+ buf = str->getChar() & 0xff;
+ bufLen = 8;
+ ++nBytesRead;
+ }
+ while (1) {
+ 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) {
+ if (bufLen <= 12) {
+ code = buf << (12 - bufLen);
+ } else {
+ code = buf >> (bufLen - 12);
+ }
+ p = &blackTab2[(code & 0xff) - 64];
+ } else {
+ if (bufLen <= 6) {
+ code = buf << (6 - bufLen);
+ } else {
+ code = buf >> (bufLen - 6);
+ }
+ p = &blackTab3[code & 0x3f];
+ }
+ if (p->bits > 0 && p->bits <= (int)bufLen) {
+ bufLen -= p->bits;
+ return p->n;
+ }
+ if (bufLen >= 13) {
+ break;
+ }
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ }
+ error(str->getPos(), "Bad black code in JBIG2 MMR stream");
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ --bufLen;
+ return 1;
+}
+
+Guint JBIG2MMRDecoder::get24Bits() {
+ while (bufLen < 24) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ }
+ return (buf >> (bufLen - 24)) & 0xffffff;
+}
+
+void JBIG2MMRDecoder::skipTo(Guint length) {
+ while (nBytesRead < length) {
+ str->getChar();
+ ++nBytesRead;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2Segment
+//------------------------------------------------------------------------
+
+enum JBIG2SegmentType {
+ jbig2SegBitmap,
+ jbig2SegSymbolDict,
+ jbig2SegPatternDict,
+ jbig2SegCodeTable
+};
+
+class JBIG2Segment {
+public:
+
+ JBIG2Segment(Guint segNumA) { segNum = segNumA; }
+ virtual ~JBIG2Segment() {}
+ void setSegNum(Guint segNumA) { segNum = segNumA; }
+ Guint getSegNum() { return segNum; }
+ virtual JBIG2SegmentType getType() = 0;
+
+private:
+
+ Guint segNum;
+};
+
+//------------------------------------------------------------------------
+// JBIG2Bitmap
+//------------------------------------------------------------------------
+
+struct JBIG2BitmapPtr {
+ Guchar *p;
+ int shift;
+ int x;
+};
+
+class JBIG2Bitmap: public JBIG2Segment {
+public:
+
+ JBIG2Bitmap(Guint segNumA, int wA, int hA);
+ virtual ~JBIG2Bitmap();
+ virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
+ JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
+ JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
+ void expand(int newH, Guint pixel);
+ void clearToZero();
+ void clearToOne();
+ int getWidth() { return w; }
+ int getHeight() { return h; }
+ int getPixel(int x, int y)
+ { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
+ (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
+ void setPixel(int x, int y)
+ { 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; }
+ int getDataSize() { return h * line; }
+
+private:
+
+ JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
+
+ int w, h, line;
+ Guchar *data;
+};
+
+JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
+ JBIG2Segment(segNumA)
+{
+ w = wA;
+ h = hA;
+ line = (wA + 7) >> 3;
+ data = (Guchar *)gmalloc(h * line);
+}
+
+JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
+ JBIG2Segment(segNumA)
+{
+ w = bitmap->w;
+ h = bitmap->h;
+ line = bitmap->line;
+ data = (Guchar *)gmalloc(h * line);
+ memcpy(data, bitmap->data, h * line);
+}
+
+JBIG2Bitmap::~JBIG2Bitmap() {
+ gfree(data);
+}
+
+//~ optimize this
+JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
+ JBIG2Bitmap *slice;
+ Guint xx, yy;
+
+ slice = new JBIG2Bitmap(0, wA, hA);
+ slice->clearToZero();
+ for (yy = 0; yy < hA; ++yy) {
+ for (xx = 0; xx < wA; ++xx) {
+ if (getPixel(x + xx, y + yy)) {
+ slice->setPixel(xx, yy);
+ }
+ }
+ }
+ return slice;
+}
+
+void JBIG2Bitmap::expand(int newH, Guint pixel) {
+ if (newH <= h) {
+ return;
+ }
+ data = (Guchar *)grealloc(data, newH * line);
+ if (pixel) {
+ memset(data + h * line, 0xff, (newH - h) * line);
+ } else {
+ memset(data + h * line, 0x00, (newH - h) * line);
+ }
+ h = newH;
+}
+
+void JBIG2Bitmap::clearToZero() {
+ memset(data, 0, h * line);
+}
+
+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);
+}
+
+void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
+ Guint combOp) {
+ int x0, x1, y0, y1, xx, yy;
+ Guchar *srcPtr, *destPtr;
+ Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
+ GBool oneByte;
+
+ if (y < 0) {
+ y0 = -y;
+ } else {
+ y0 = 0;
+ }
+ if (y + bitmap->h > h) {
+ y1 = h - y;
+ } else {
+ y1 = bitmap->h;
+ }
+ if (y0 >= y1) {
+ return;
+ }
+
+ if (x >= 0) {
+ x0 = x & ~7;
+ } else {
+ x0 = 0;
+ }
+ x1 = x + bitmap->w;
+ if (x1 > w) {
+ x1 = w;
+ }
+ if (x0 >= x1) {
+ return;
+ }
+
+ s1 = x & 7;
+ s2 = 8 - s1;
+ m1 = 0xff >> (x1 & 7);
+ m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
+ m3 = (0xff >> s1) & m2;
+
+ oneByte = x0 == ((x1 - 1) & ~7);
+
+ for (yy = y0; yy < y1; ++yy) {
+
+ // one byte per line -- need to mask both left and right side
+ if (oneByte) {
+ if (x >= 0) {
+ destPtr = data + (y + yy) * line + (x >> 3);
+ srcPtr = bitmap->data + yy * bitmap->line;
+ dest = *destPtr;
+ src1 = *srcPtr;
+ switch (combOp) {
+ case 0: // or
+ dest |= (src1 >> s1) & m2;
+ break;
+ case 1: // and
+ dest &= ((0xff00 | src1) >> s1) | m1;
+ break;
+ case 2: // xor
+ dest ^= (src1 >> s1) & m2;
+ break;
+ case 3: // xnor
+ dest ^= ((src1 ^ 0xff) >> s1) & m2;
+ break;
+ case 4: // replace
+ dest = (dest & ~m3) | ((src1 >> s1) & m3);
+ break;
+ }
+ *destPtr = dest;
+ } else {
+ destPtr = data + (y + yy) * line;
+ srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
+ dest = *destPtr;
+ src1 = *srcPtr;
+ switch (combOp) {
+ case 0: // or
+ dest |= src1 & m2;
+ break;
+ case 1: // and
+ dest &= src1 | m1;
+ break;
+ case 2: // xor
+ dest ^= src1 & m2;
+ break;
+ case 3: // xnor
+ dest ^= (src1 ^ 0xff) & m2;
+ break;
+ case 4: // replace
+ dest = (src1 & m2) | (dest & m1);
+ break;
+ }
+ *destPtr = dest;
+ }
+
+ // multiple bytes per line -- need to mask left side of left-most
+ // byte and right side of right-most byte
+ } else {
+
+ // left-most byte
+ if (x >= 0) {
+ destPtr = data + (y + yy) * line + (x >> 3);
+ srcPtr = bitmap->data + yy * bitmap->line;
+ src1 = *srcPtr++;
+ dest = *destPtr;
+ switch (combOp) {
+ case 0: // or
+ dest |= src1 >> s1;
+ break;
+ case 1: // and
+ dest &= (0xff00 | src1) >> s1;
+ break;
+ case 2: // xor
+ dest ^= src1 >> s1;
+ break;
+ case 3: // xnor
+ dest ^= (src1 ^ 0xff) >> s1;
+ break;
+ case 4: // replace
+ dest = (dest & (0xff << s2)) | (src1 >> s1);
+ break;
+ }
+ *destPtr++ = dest;
+ xx = x0 + 8;
+ } else {
+ destPtr = data + (y + yy) * line;
+ srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
+ src1 = *srcPtr++;
+ xx = x0;
+ }
+
+ // middle bytes
+ for (; xx < x1 - 8; xx += 8) {
+ dest = *destPtr;
+ src0 = src1;
+ src1 = *srcPtr++;
+ src = (((src0 << 8) | src1) >> s1) & 0xff;
+ switch (combOp) {
+ case 0: // or
+ dest |= src;
+ break;
+ case 1: // and
+ dest &= src;
+ break;
+ case 2: // xor
+ dest ^= src;
+ break;
+ case 3: // xnor
+ dest ^= src ^ 0xff;
+ break;
+ case 4: // replace
+ dest = src;
+ break;
+ }
+ *destPtr++ = dest;
+ }
+
+ // right-most byte
+ dest = *destPtr;
+ src0 = src1;
+ src1 = *srcPtr++;
+ src = (((src0 << 8) | src1) >> s1) & 0xff;
+ switch (combOp) {
+ case 0: // or
+ dest |= src & m2;
+ break;
+ case 1: // and
+ dest &= src | m1;
+ break;
+ case 2: // xor
+ dest ^= src & m2;
+ break;
+ case 3: // xnor
+ dest ^= (src ^ 0xff) & m2;
+ break;
+ case 4: // replace
+ dest = (src & m2) | (dest & m1);
+ break;
+ }
+ *destPtr = dest;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2SymbolDict
+//------------------------------------------------------------------------
+
+class JBIG2SymbolDict: public JBIG2Segment {
+public:
+
+ JBIG2SymbolDict(Guint segNumA, Guint sizeA);
+ virtual ~JBIG2SymbolDict();
+ virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
+ Guint getSize() { return size; }
+ void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
+ JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
+ void setGenericRegionStats(JArithmeticDecoderStats *stats)
+ { genericRegionStats = stats; }
+ void setRefinementRegionStats(JArithmeticDecoderStats *stats)
+ { refinementRegionStats = stats; }
+ JArithmeticDecoderStats *getGenericRegionStats()
+ { return genericRegionStats; }
+ JArithmeticDecoderStats *getRefinementRegionStats()
+ { return refinementRegionStats; }
+
+private:
+
+ Guint size;
+ JBIG2Bitmap **bitmaps;
+ JArithmeticDecoderStats *genericRegionStats;
+ JArithmeticDecoderStats *refinementRegionStats;
+};
+
+JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
+ JBIG2Segment(segNumA)
+{
+ size = sizeA;
+ bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
+ genericRegionStats = NULL;
+ refinementRegionStats = NULL;
+}
+
+JBIG2SymbolDict::~JBIG2SymbolDict() {
+ Guint i;
+
+ for (i = 0; i < size; ++i) {
+ delete bitmaps[i];
+ }
+ gfree(bitmaps);
+ if (genericRegionStats) {
+ delete genericRegionStats;
+ }
+ if (refinementRegionStats) {
+ delete refinementRegionStats;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2PatternDict
+//------------------------------------------------------------------------
+
+class JBIG2PatternDict: public JBIG2Segment {
+public:
+
+ JBIG2PatternDict(Guint segNumA, Guint sizeA);
+ virtual ~JBIG2PatternDict();
+ virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
+ Guint getSize() { return size; }
+ void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
+ JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
+
+private:
+
+ Guint size;
+ JBIG2Bitmap **bitmaps;
+};
+
+JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
+ JBIG2Segment(segNumA)
+{
+ size = sizeA;
+ bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
+}
+
+JBIG2PatternDict::~JBIG2PatternDict() {
+ Guint i;
+
+ for (i = 0; i < size; ++i) {
+ delete bitmaps[i];
+ }
+ gfree(bitmaps);
+}
+
+//------------------------------------------------------------------------
+// JBIG2CodeTable
+//------------------------------------------------------------------------
+
+class JBIG2CodeTable: public JBIG2Segment {
+public:
+
+ JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
+ virtual ~JBIG2CodeTable();
+ virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
+ JBIG2HuffmanTable *getHuffTable() { return table; }
+
+private:
+
+ JBIG2HuffmanTable *table;
+};
+
+JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
+ JBIG2Segment(segNumA)
+{
+ table = tableA;
+}
+
+JBIG2CodeTable::~JBIG2CodeTable() {
+ gfree(table);
+}
+
+//------------------------------------------------------------------------
+// JBIG2Stream
+//------------------------------------------------------------------------
+
+JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
+ FilterStream(strA)
+{
+ pageBitmap = NULL;
+
+ arithDecoder = new JArithmeticDecoder();
+ genericRegionStats = new JArithmeticDecoderStats(1 << 1);
+ refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
+ iadhStats = new JArithmeticDecoderStats(1 << 9);
+ iadwStats = new JArithmeticDecoderStats(1 << 9);
+ iaexStats = new JArithmeticDecoderStats(1 << 9);
+ iaaiStats = new JArithmeticDecoderStats(1 << 9);
+ iadtStats = new JArithmeticDecoderStats(1 << 9);
+ iaitStats = new JArithmeticDecoderStats(1 << 9);
+ iafsStats = new JArithmeticDecoderStats(1 << 9);
+ iadsStats = new JArithmeticDecoderStats(1 << 9);
+ iardxStats = new JArithmeticDecoderStats(1 << 9);
+ iardyStats = new JArithmeticDecoderStats(1 << 9);
+ iardwStats = new JArithmeticDecoderStats(1 << 9);
+ iardhStats = new JArithmeticDecoderStats(1 << 9);
+ iariStats = new JArithmeticDecoderStats(1 << 9);
+ iaidStats = new JArithmeticDecoderStats(1 << 1);
+ huffDecoder = new JBIG2HuffmanDecoder();
+ mmrDecoder = new JBIG2MMRDecoder();
+
+ segments = globalSegments = new GList();
+ if (globalsStream->isStream()) {
+ curStr = globalsStream->getStream();
+ curStr->reset();
+ arithDecoder->setStream(curStr);
+ huffDecoder->setStream(curStr);
+ mmrDecoder->setStream(curStr);
+ readSegments();
+ }
+
+ segments = NULL;
+ curStr = NULL;
+ dataPtr = dataEnd = NULL;
+}
+
+JBIG2Stream::~JBIG2Stream() {
+ delete arithDecoder;
+ delete genericRegionStats;
+ delete refinementRegionStats;
+ delete iadhStats;
+ delete iadwStats;
+ delete iaexStats;
+ delete iaaiStats;
+ delete iadtStats;
+ delete iaitStats;
+ delete iafsStats;
+ delete iadsStats;
+ delete iardxStats;
+ delete iardyStats;
+ delete iardwStats;
+ delete iardhStats;
+ delete iariStats;
+ delete iaidStats;
+ delete huffDecoder;
+ delete mmrDecoder;
+ if (pageBitmap) {
+ delete pageBitmap;
+ }
+ if (segments) {
+ deleteGList(segments, JBIG2Segment);
+ }
+ if (globalSegments) {
+ deleteGList(globalSegments, JBIG2Segment);
+ }
+ delete str;
+}
+
+void JBIG2Stream::reset() {
+ if (pageBitmap) {
+ delete pageBitmap;
+ pageBitmap = NULL;
+ }
+ if (segments) {
+ deleteGList(segments, JBIG2Segment);
+ }
+ segments = new GList();
+
+ curStr = str;
+ curStr->reset();
+ arithDecoder->setStream(curStr);
+ huffDecoder->setStream(curStr);
+ mmrDecoder->setStream(curStr);
+ readSegments();
+
+ if (pageBitmap) {
+ dataPtr = pageBitmap->getDataPtr();
+ dataEnd = dataPtr + pageBitmap->getDataSize();
+ } else {
+ dataPtr = NULL;
+ }
+}
+
+int JBIG2Stream::getChar() {
+ if (dataPtr && dataPtr < dataEnd) {
+ return (*dataPtr++ ^ 0xff) & 0xff;
+ }
+ return EOF;
+}
+
+int JBIG2Stream::lookChar() {
+ if (dataPtr && dataPtr < dataEnd) {
+ return (*dataPtr ^ 0xff) & 0xff;
+ }
+ return EOF;
+}
+
+GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) {
+ return NULL;
+}
+
+GBool JBIG2Stream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+void JBIG2Stream::readSegments() {
+ Guint segNum, segFlags, segType, page, segLength;
+ Guint refFlags, nRefSegs;
+ Guint *refSegs;
+ int c1, c2, c3;
+ Guint i;
+
+ while (readULong(&segNum)) {
+
+ // segment header flags
+ if (!readUByte(&segFlags)) {
+ goto eofError1;
+ }
+ segType = segFlags & 0x3f;
+
+ // referred-to segment count and retention flags
+ if (!readUByte(&refFlags)) {
+ goto eofError1;
+ }
+ nRefSegs = refFlags >> 5;
+ if (nRefSegs == 7) {
+ if ((c1 = curStr->getChar()) == EOF ||
+ (c2 = curStr->getChar()) == EOF ||
+ (c3 = curStr->getChar()) == EOF) {
+ goto eofError1;
+ }
+ refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
+ nRefSegs = refFlags & 0x1fffffff;
+ for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
+ c1 = curStr->getChar();
+ }
+ }
+
+ // referred-to segment numbers
+ refSegs = (Guint *)gmalloc(nRefSegs * sizeof(Guint));
+ if (segNum <= 256) {
+ for (i = 0; i < nRefSegs; ++i) {
+ if (!readUByte(&refSegs[i])) {
+ goto eofError2;
+ }
+ }
+ } else if (segNum <= 65536) {
+ for (i = 0; i < nRefSegs; ++i) {
+ if (!readUWord(&refSegs[i])) {
+ goto eofError2;
+ }
+ }
+ } else {
+ for (i = 0; i < nRefSegs; ++i) {
+ if (!readULong(&refSegs[i])) {
+ goto eofError2;
+ }
+ }
+ }
+
+ // segment page association
+ if (segFlags & 0x40) {
+ if (!readULong(&page)) {
+ goto eofError2;
+ }
+ } else {
+ if (!readUByte(&page)) {
+ goto eofError2;
+ }
+ }
+
+ // segment data length
+ if (!readULong(&segLength)) {
+ goto eofError2;
+ }
+
+ // read the segment data
+ switch (segType) {
+ case 0:
+ readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs);
+ break;
+ case 4:
+ readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
+ break;
+ case 6:
+ readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
+ break;
+ case 7:
+ readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
+ break;
+ case 16:
+ readPatternDictSeg(segNum, segLength);
+ break;
+ case 20:
+ readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 22:
+ readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 23:
+ readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 36:
+ readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
+ break;
+ case 38:
+ readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
+ break;
+ case 39:
+ readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
+ break;
+ case 40:
+ readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 42:
+ readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 43:
+ readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 48:
+ readPageInfoSeg(segLength);
+ break;
+ case 50:
+ readEndOfStripeSeg(segLength);
+ break;
+ case 52:
+ readProfilesSeg(segLength);
+ break;
+ case 53:
+ readCodeTableSeg(segNum, segLength);
+ break;
+ case 62:
+ readExtensionSeg(segLength);
+ break;
+ default:
+ error(getPos(), "Unknown segment type in JBIG2 stream");
+ for (i = 0; i < segLength; ++i) {
+ if ((c1 = curStr->getChar()) == EOF) {
+ goto eofError2;
+ }
+ }
+ break;
+ }
+
+ gfree(refSegs);
+ }
+
+ return;
+
+ eofError2:
+ gfree(refSegs);
+ eofError1:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
+ Guint *refSegs, Guint nRefSegs) {
+ JBIG2SymbolDict *symbolDict;
+ JBIG2HuffmanTable *huffDHTable, *huffDWTable;
+ JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
+ JBIG2Segment *seg;
+ GList *codeTables;
+ JBIG2SymbolDict *inputSymbolDict;
+ Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
+ Guint huffDH, huffDW, huffBMSize, huffAggInst;
+ Guint contextUsed, contextRetained;
+ int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
+ Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
+ JBIG2Bitmap **bitmaps;
+ JBIG2Bitmap *collBitmap, *refBitmap;
+ Guint *symWidths;
+ Guint symHeight, symWidth, totalWidth, x, symID;
+ int dh, dw, refAggNum, refDX, refDY, bmSize;
+ GBool ex;
+ int run, cnt;
+ Guint i, j, k;
+ Guchar *p;
+
+ // symbol dictionary flags
+ if (!readUWord(&flags)) {
+ goto eofError;
+ }
+ sdTemplate = (flags >> 10) & 3;
+ sdrTemplate = (flags >> 12) & 1;
+ huff = flags & 1;
+ refAgg = (flags >> 1) & 1;
+ huffDH = (flags >> 2) & 3;
+ huffDW = (flags >> 4) & 3;
+ huffBMSize = (flags >> 6) & 1;
+ huffAggInst = (flags >> 7) & 1;
+ contextUsed = (flags >> 8) & 1;
+ contextRetained = (flags >> 9) & 1;
+
+ // symbol dictionary AT flags
+ if (!huff) {
+ if (sdTemplate == 0) {
+ if (!readByte(&sdATX[0]) ||
+ !readByte(&sdATY[0]) ||
+ !readByte(&sdATX[1]) ||
+ !readByte(&sdATY[1]) ||
+ !readByte(&sdATX[2]) ||
+ !readByte(&sdATY[2]) ||
+ !readByte(&sdATX[3]) ||
+ !readByte(&sdATY[3])) {
+ goto eofError;
+ }
+ } else {
+ if (!readByte(&sdATX[0]) ||
+ !readByte(&sdATY[0])) {
+ goto eofError;
+ }
+ }
+ }
+
+ // symbol dictionary refinement AT flags
+ if (refAgg && !sdrTemplate) {
+ if (!readByte(&sdrATX[0]) ||
+ !readByte(&sdrATY[0]) ||
+ !readByte(&sdrATX[1]) ||
+ !readByte(&sdrATY[1])) {
+ goto eofError;
+ }
+ }
+
+ // SDNUMEXSYMS and SDNUMNEWSYMS
+ if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
+ goto eofError;
+ }
+
+ // get referenced segments: input symbol dictionaries and code tables
+ codeTables = new GList();
+ numInputSyms = 0;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
+ } else if (seg->getType() == jbig2SegCodeTable) {
+ codeTables->append(seg);
+ }
+ }
+
+ // compute symbol code length
+ symCodeLen = 0;
+ i = 1;
+ while (i < numInputSyms + numNewSyms) {
+ ++symCodeLen;
+ i <<= 1;
+ }
+
+ // get the input symbol bitmaps
+ bitmaps = (JBIG2Bitmap **)gmalloc((numInputSyms + numNewSyms) *
+ sizeof(JBIG2Bitmap *));
+ k = 0;
+ inputSymbolDict = NULL;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ inputSymbolDict = (JBIG2SymbolDict *)seg;
+ for (j = 0; j < inputSymbolDict->getSize(); ++j) {
+ bitmaps[k++] = inputSymbolDict->getBitmap(j);
+ }
+ }
+ }
+
+ // get the Huffman tables
+ huffDHTable = huffDWTable = NULL; // make gcc happy
+ huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
+ i = 0;
+ if (huff) {
+ if (huffDH == 0) {
+ huffDHTable = huffTableD;
+ } else if (huffDH == 1) {
+ huffDHTable = huffTableE;
+ } else {
+ huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffDW == 0) {
+ huffDWTable = huffTableB;
+ } else if (huffDW == 1) {
+ huffDWTable = huffTableC;
+ } else {
+ huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffBMSize == 0) {
+ huffBMSizeTable = huffTableA;
+ } else {
+ huffBMSizeTable =
+ ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffAggInst == 0) {
+ huffAggInstTable = huffTableA;
+ } else {
+ huffAggInstTable =
+ ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ }
+ delete codeTables;
+
+ // set up the Huffman decoder
+ if (huff) {
+ huffDecoder->reset();
+
+ // set up the arithmetic decoder
+ } else {
+ if (contextUsed && inputSymbolDict) {
+ resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
+ } else {
+ resetGenericStats(sdTemplate, 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) {
+ symWidths = (Guint *)gmalloc(numNewSyms * sizeof(Guint));
+ }
+
+ symHeight = 0;
+ i = 0;
+ while (i < numNewSyms) {
+
+ // read the height class delta height
+ if (huff) {
+ huffDecoder->decodeInt(&dh, huffDHTable);
+ } else {
+ arithDecoder->decodeInt(&dh, iadhStats);
+ }
+ symHeight += dh;
+ symWidth = 0;
+ totalWidth = 0;
+ j = i;
+
+ // read the symbols in this height class
+ while (1) {
+
+ // read the delta width
+ if (huff) {
+ if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
+ break;
+ }
+ } else {
+ if (!arithDecoder->decodeInt(&dw, iadwStats)) {
+ break;
+ }
+ }
+ symWidth += dw;
+
+ // using a collective bitmap, so don't read a bitmap here
+ if (huff && !refAgg) {
+ symWidths[i] = symWidth;
+ totalWidth += symWidth;
+
+ // refinement/aggregate coding
+ } else if (refAgg) {
+ if (huff) {
+ if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
+ break;
+ }
+ } else {
+ if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
+ 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);
+ huffDecoder->decodeInt(&refDY, huffTableO);
+ huffDecoder->decodeInt(&bmSize, huffTableA);
+ huffDecoder->reset();
+ arithDecoder->start();
+ } else {
+ symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
+ arithDecoder->decodeInt(&refDX, iardxStats);
+ arithDecoder->decodeInt(&refDY, iardyStats);
+ }
+ refBitmap = bitmaps[symID];
+ bitmaps[numInputSyms + i] =
+ readGenericRefinementRegion(symWidth, symHeight,
+ sdrTemplate, gFalse,
+ refBitmap, refDX, refDY,
+ sdrATX, sdrATY);
+ //~ do we need to use the bmSize value here (in Huffman mode)?
+ } else {
+ bitmaps[numInputSyms + i] =
+ readTextRegion(huff, gTrue, symWidth, symHeight,
+ refAggNum, 0, numInputSyms + i, NULL,
+ symCodeLen, bitmaps, 0, 0, 0, 1, 0,
+ huffTableF, huffTableH, huffTableK, huffTableO,
+ huffTableO, huffTableO, huffTableO, huffTableA,
+ sdrTemplate, sdrATX, sdrATY);
+ }
+
+ // non-ref/agg coding
+ } else {
+ bitmaps[numInputSyms + i] =
+ readGenericBitmap(gFalse, symWidth, symHeight,
+ sdTemplate, gFalse, gFalse, NULL,
+ sdATX, sdATY, 0);
+ }
+
+ ++i;
+ }
+
+ // read the collective bitmap
+ if (huff && !refAgg) {
+ huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
+ 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++ = curStr->getChar();
+ }
+ } else {
+ collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
+ 0, gFalse, gFalse, NULL, NULL, NULL,
+ bmSize);
+ }
+ x = 0;
+ for (; j < i; ++j) {
+ bitmaps[numInputSyms + j] =
+ collBitmap->getSlice(x, 0, symWidths[j], symHeight);
+ x += symWidths[j];
+ }
+ delete collBitmap;
+ }
+ }
+
+ // create the symbol dict object
+ symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
+
+ // exported symbol list
+ i = j = 0;
+ ex = gFalse;
+ while (i < numInputSyms + numNewSyms) {
+ if (huff) {
+ huffDecoder->decodeInt(&run, huffTableA);
+ } else {
+ arithDecoder->decodeInt(&run, iaexStats);
+ }
+ if (ex) {
+ for (cnt = 0; cnt < run; ++cnt) {
+ symbolDict->setBitmap(j++, bitmaps[i++]->copy());
+ }
+ } else {
+ i += run;
+ }
+ ex = !ex;
+ }
+
+ for (i = 0; i < numNewSyms; ++i) {
+ delete bitmaps[numInputSyms + i];
+ }
+ gfree(bitmaps);
+ if (symWidths) {
+ gfree(symWidths);
+ }
+
+ // save the arithmetic decoder stats
+ if (!huff && contextRetained) {
+ symbolDict->setGenericRegionStats(genericRegionStats->copy());
+ if (refAgg) {
+ symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
+ }
+ }
+
+ // store the new symbol dict
+ segments->append(symbolDict);
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs) {
+ JBIG2Bitmap *bitmap;
+ JBIG2HuffmanTable runLengthTab[36];
+ JBIG2HuffmanTable *symCodeTab;
+ JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
+ JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
+ JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
+ JBIG2Segment *seg;
+ GList *codeTables;
+ JBIG2SymbolDict *symbolDict;
+ JBIG2Bitmap **syms;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, huff, refine, logStrips, refCorner, transposed;
+ Guint combOp, defPixel, templ;
+ int sOffset;
+ Guint huffFlags, huffFS, huffDS, huffDT;
+ Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
+ Guint numInstances, numSyms, symCodeLen;
+ int atx[2], aty[2];
+ Guint i, k, kk;
+ int j;
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the text region header
+ if (!readUWord(&flags)) {
+ goto eofError;
+ }
+ huff = flags & 1;
+ refine = (flags >> 1) & 1;
+ logStrips = (flags >> 2) & 3;
+ refCorner = (flags >> 4) & 3;
+ transposed = (flags >> 6) & 1;
+ 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
+ if (huff) {
+ if (!readUWord(&huffFlags)) {
+ goto eofError;
+ }
+ huffFS = huffFlags & 3;
+ huffDS = (huffFlags >> 2) & 3;
+ huffDT = (huffFlags >> 4) & 3;
+ huffRDW = (huffFlags >> 6) & 3;
+ huffRDH = (huffFlags >> 8) & 3;
+ huffRDX = (huffFlags >> 10) & 3;
+ huffRDY = (huffFlags >> 12) & 3;
+ huffRSize = (huffFlags >> 14) & 1;
+ }
+ if (refine && templ == 0) {
+ if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
+ !readByte(&atx[1]) || !readByte(&aty[1])) {
+ goto eofError;
+ }
+ }
+ if (!readULong(&numInstances)) {
+ goto eofError;
+ }
+
+ // get symbol dictionaries and tables
+ codeTables = new GList();
+ numSyms = 0;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ numSyms += ((JBIG2SymbolDict *)seg)->getSize();
+ } else if (seg->getType() == jbig2SegCodeTable) {
+ codeTables->append(seg);
+ }
+ }
+ symCodeLen = 0;
+ i = 1;
+ while (i < numSyms) {
+ ++symCodeLen;
+ i <<= 1;
+ }
+
+ // get the symbol bitmaps
+ syms = (JBIG2Bitmap **)gmalloc(numSyms * sizeof(JBIG2Bitmap *));
+ kk = 0;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ symbolDict = (JBIG2SymbolDict *)seg;
+ for (k = 0; k < symbolDict->getSize(); ++k) {
+ syms[kk++] = symbolDict->getBitmap(k);
+ }
+ }
+ }
+
+ // get the Huffman tables
+ huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
+ huffRDWTable = huffRDHTable = NULL; // make gcc happy
+ huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
+ i = 0;
+ if (huff) {
+ if (huffFS == 0) {
+ huffFSTable = huffTableF;
+ } else if (huffFS == 1) {
+ huffFSTable = huffTableG;
+ } else {
+ huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffDS == 0) {
+ huffDSTable = huffTableH;
+ } else if (huffDS == 1) {
+ huffDSTable = huffTableI;
+ } else if (huffDS == 2) {
+ huffDSTable = huffTableJ;
+ } else {
+ huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffDT == 0) {
+ huffDTTable = huffTableK;
+ } else if (huffDT == 1) {
+ huffDTTable = huffTableL;
+ } else if (huffDT == 2) {
+ huffDTTable = huffTableM;
+ } else {
+ huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDW == 0) {
+ huffRDWTable = huffTableN;
+ } else if (huffRDW == 1) {
+ huffRDWTable = huffTableO;
+ } else {
+ huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDH == 0) {
+ huffRDHTable = huffTableN;
+ } else if (huffRDH == 1) {
+ huffRDHTable = huffTableO;
+ } else {
+ huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDX == 0) {
+ huffRDXTable = huffTableN;
+ } else if (huffRDX == 1) {
+ huffRDXTable = huffTableO;
+ } else {
+ huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDY == 0) {
+ huffRDYTable = huffTableN;
+ } else if (huffRDY == 1) {
+ huffRDYTable = huffTableO;
+ } else {
+ huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRSize == 0) {
+ huffRSizeTable = huffTableA;
+ } else {
+ huffRSizeTable =
+ ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ }
+ delete codeTables;
+
+ // symbol ID Huffman decoding table
+ if (huff) {
+ huffDecoder->reset();
+ for (i = 0; i < 32; ++i) {
+ runLengthTab[i].val = i;
+ runLengthTab[i].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[i].rangeLen = 0;
+ }
+ runLengthTab[32].val = 0x103;
+ runLengthTab[32].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[32].rangeLen = 2;
+ runLengthTab[33].val = 0x203;
+ runLengthTab[33].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[33].rangeLen = 3;
+ 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) *
+ sizeof(JBIG2HuffmanTable));
+ for (i = 0; i < numSyms; ++i) {
+ symCodeTab[i].val = i;
+ symCodeTab[i].rangeLen = 0;
+ }
+ i = 0;
+ while (i < numSyms) {
+ huffDecoder->decodeInt(&j, runLengthTab);
+ if (j > 0x200) {
+ for (j -= 0x200; j && i < numSyms; --j) {
+ symCodeTab[i++].prefixLen = 0;
+ }
+ } else if (j > 0x100) {
+ for (j -= 0x100; j && i < numSyms; --j) {
+ symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
+ ++i;
+ }
+ } else {
+ symCodeTab[i++].prefixLen = j;
+ }
+ }
+ symCodeTab[numSyms].prefixLen = 0;
+ symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
+ huffDecoder->buildTable(symCodeTab, numSyms);
+ huffDecoder->reset();
+
+ // set up the arithmetic decoder
+ } else {
+ symCodeTab = NULL;
+ resetIntStats(symCodeLen);
+ arithDecoder->start();
+ }
+ if (refine) {
+ resetRefinementStats(templ, NULL);
+ }
+
+ bitmap = readTextRegion(huff, refine, w, h, numInstances,
+ logStrips, numSyms, symCodeTab, symCodeLen, syms,
+ defPixel, combOp, transposed, refCorner, sOffset,
+ huffFSTable, huffDSTable, huffDTTable,
+ huffRDWTable, huffRDHTable,
+ huffRDXTable, huffRDYTable, huffRSizeTable,
+ templ, atx, aty);
+
+ gfree(syms);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ bitmap->setSegNum(segNum);
+ segments->append(bitmap);
+ }
+
+ // clean up the Huffman decoder
+ if (huff) {
+ gfree(symCodeTab);
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
+ int w, int h,
+ Guint numInstances,
+ Guint logStrips,
+ int numSyms,
+ JBIG2HuffmanTable *symCodeTab,
+ Guint symCodeLen,
+ JBIG2Bitmap **syms,
+ Guint defPixel, Guint combOp,
+ Guint transposed, Guint refCorner,
+ int sOffset,
+ JBIG2HuffmanTable *huffFSTable,
+ JBIG2HuffmanTable *huffDSTable,
+ JBIG2HuffmanTable *huffDTTable,
+ JBIG2HuffmanTable *huffRDWTable,
+ JBIG2HuffmanTable *huffRDHTable,
+ JBIG2HuffmanTable *huffRDXTable,
+ JBIG2HuffmanTable *huffRDYTable,
+ JBIG2HuffmanTable *huffRSizeTable,
+ Guint templ,
+ int *atx, int *aty) {
+ JBIG2Bitmap *bitmap;
+ JBIG2Bitmap *symbolBitmap;
+ Guint strips;
+ int t, dt, tt, s, ds, sFirst, j;
+ int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
+ Guint symID, inst, bw, bh;
+
+ strips = 1 << logStrips;
+
+ // allocate the bitmap
+ bitmap = new JBIG2Bitmap(0, w, h);
+ if (defPixel) {
+ bitmap->clearToOne();
+ } else {
+ bitmap->clearToZero();
+ }
+
+ // decode initial T value
+ if (huff) {
+ huffDecoder->decodeInt(&t, huffDTTable);
+ } else {
+ arithDecoder->decodeInt(&t, iadtStats);
+ }
+ t *= -(int)strips;
+
+ inst = 0;
+ sFirst = 0;
+ while (inst < numInstances) {
+
+ // decode delta-T
+ if (huff) {
+ huffDecoder->decodeInt(&dt, huffDTTable);
+ } else {
+ arithDecoder->decodeInt(&dt, iadtStats);
+ }
+ t += dt * strips;
+
+ // first S value
+ if (huff) {
+ huffDecoder->decodeInt(&ds, huffFSTable);
+ } else {
+ arithDecoder->decodeInt(&ds, iafsStats);
+ }
+ sFirst += ds;
+ s = sFirst;
+
+ // read the instances
+ while (1) {
+
+ // T value
+ if (strips == 1) {
+ dt = 0;
+ } else if (huff) {
+ dt = huffDecoder->readBits(logStrips);
+ } else {
+ arithDecoder->decodeInt(&dt, iaitStats);
+ }
+ tt = t + dt;
+
+ // symbol ID
+ if (huff) {
+ if (symCodeTab) {
+ huffDecoder->decodeInt(&j, symCodeTab);
+ symID = (Guint)j;
+ } else {
+ symID = huffDecoder->readBits(symCodeLen);
+ }
+ } else {
+ symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
+ }
+
+ // get the symbol bitmap
+ symbolBitmap = NULL;
+ if (refine) {
+ if (huff) {
+ ri = (int)huffDecoder->readBit();
+ } else {
+ arithDecoder->decodeInt(&ri, iariStats);
+ }
+ } else {
+ ri = 0;
+ }
+ if (ri) {
+ if (huff) {
+ huffDecoder->decodeInt(&rdw, huffRDWTable);
+ huffDecoder->decodeInt(&rdh, huffRDHTable);
+ huffDecoder->decodeInt(&rdx, huffRDXTable);
+ huffDecoder->decodeInt(&rdy, huffRDYTable);
+ huffDecoder->decodeInt(&bmSize, huffRSizeTable);
+ huffDecoder->reset();
+ arithDecoder->start();
+ } else {
+ arithDecoder->decodeInt(&rdw, iardwStats);
+ arithDecoder->decodeInt(&rdh, iardhStats);
+ arithDecoder->decodeInt(&rdx, iardxStats);
+ arithDecoder->decodeInt(&rdy, iardyStats);
+ }
+ refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
+ refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
+
+ symbolBitmap =
+ readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
+ rdh + syms[symID]->getHeight(),
+ templ, gFalse, syms[symID],
+ refDX, refDY, atx, aty);
+ //~ do we need to use the bmSize value here (in Huffman mode)?
+ } else {
+ symbolBitmap = syms[symID];
+ }
+
+ // combine the symbol bitmap into the region bitmap
+ //~ something is wrong here - refCorner shouldn't degenerate into
+ //~ two cases
+ bw = symbolBitmap->getWidth() - 1;
+ bh = symbolBitmap->getHeight() - 1;
+ if (transposed) {
+ switch (refCorner) {
+ case 0: // bottom left
+ bitmap->combine(symbolBitmap, tt, s, combOp);
+ break;
+ case 1: // top left
+ bitmap->combine(symbolBitmap, tt, s, combOp);
+ break;
+ case 2: // bottom right
+ bitmap->combine(symbolBitmap, tt - bw, s, combOp);
+ break;
+ case 3: // top right
+ bitmap->combine(symbolBitmap, tt - bw, s, combOp);
+ break;
+ }
+ s += bh;
+ } else {
+ switch (refCorner) {
+ case 0: // bottom left
+ bitmap->combine(symbolBitmap, s, tt - bh, combOp);
+ break;
+ case 1: // top left
+ bitmap->combine(symbolBitmap, s, tt, combOp);
+ break;
+ case 2: // bottom right
+ bitmap->combine(symbolBitmap, s, tt - bh, combOp);
+ break;
+ case 3: // top right
+ bitmap->combine(symbolBitmap, s, tt, combOp);
+ break;
+ }
+ s += bw;
+ }
+ if (ri) {
+ delete symbolBitmap;
+ }
+
+ // next instance
+ ++inst;
+
+ // next S value
+ if (huff) {
+ if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
+ break;
+ }
+ } else {
+ if (!arithDecoder->decodeInt(&ds, iadsStats)) {
+ break;
+ }
+ }
+ s += sOffset + ds;
+ }
+ }
+
+ return bitmap;
+}
+
+void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
+ JBIG2PatternDict *patternDict;
+ JBIG2Bitmap *bitmap;
+ Guint flags, patternW, patternH, grayMax, templ, mmr;
+ int atx[4], aty[4];
+ Guint i, x;
+
+ // halftone dictionary flags, pattern width and height, max gray value
+ if (!readUByte(&flags) ||
+ !readUByte(&patternW) ||
+ !readUByte(&patternH) ||
+ !readULong(&grayMax)) {
+ goto eofError;
+ }
+ templ = (flags >> 1) & 3;
+ mmr = flags & 1;
+
+ // set up the arithmetic decoder
+ if (!mmr) {
+ resetGenericStats(templ, NULL);
+ arithDecoder->start();
+ }
+
+ // read the bitmap
+ atx[0] = -(int)patternW; aty[0] = 0;
+ atx[1] = -3; aty[1] = -1;
+ atx[2] = 2; aty[2] = -2;
+ atx[3] = -2; aty[3] = -2;
+ bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
+ templ, gFalse, gFalse, NULL,
+ atx, aty, length - 7);
+
+ // create the pattern dict object
+ patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
+
+ // split up the bitmap
+ x = 0;
+ for (i = 0; i <= grayMax; ++i) {
+ patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
+ x += patternW;
+ }
+
+ // free memory
+ delete bitmap;
+
+ // store the new pattern dict
+ segments->append(patternDict);
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs) {
+ JBIG2Bitmap *bitmap;
+ JBIG2Segment *seg;
+ JBIG2PatternDict *patternDict;
+ JBIG2Bitmap *skipBitmap;
+ Guint *grayImg;
+ JBIG2Bitmap *grayBitmap;
+ JBIG2Bitmap *patternBitmap;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, mmr, templ, enableSkip, combOp;
+ Guint gridW, gridH, stepX, stepY, patW, patH;
+ int atx[4], aty[4];
+ int gridX, gridY, xx, yy, bit, j;
+ Guint bpp, m, n, i;
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the halftone region header
+ if (!readUByte(&flags)) {
+ goto eofError;
+ }
+ mmr = flags & 1;
+ templ = (flags >> 1) & 3;
+ enableSkip = (flags >> 3) & 1;
+ combOp = (flags >> 4) & 7;
+ if (!readULong(&gridW) || !readULong(&gridH) ||
+ !readLong(&gridX) || !readLong(&gridY) ||
+ !readUWord(&stepX) || !readUWord(&stepY)) {
+ goto eofError;
+ }
+
+ // get pattern dictionary
+ if (nRefSegs != 1) {
+ error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
+ return;
+ }
+ seg = findSegment(refSegs[0]);
+ if (seg->getType() != jbig2SegPatternDict) {
+ error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
+ return;
+ }
+ patternDict = (JBIG2PatternDict *)seg;
+ bpp = 0;
+ i = 1;
+ while (i < patternDict->getSize()) {
+ ++bpp;
+ i <<= 1;
+ }
+ patW = patternDict->getBitmap(0)->getWidth();
+ patH = patternDict->getBitmap(0)->getHeight();
+
+ // set up the arithmetic decoder
+ if (!mmr) {
+ resetGenericStats(templ, NULL);
+ arithDecoder->start();
+ }
+
+ // allocate the bitmap
+ bitmap = new JBIG2Bitmap(segNum, w, h);
+ if (flags & 0x80) { // HDEFPIXEL
+ bitmap->clearToOne();
+ } else {
+ bitmap->clearToZero();
+ }
+
+ // compute the skip bitmap
+ skipBitmap = NULL;
+ if (enableSkip) {
+ skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
+ skipBitmap->clearToZero();
+ for (m = 0; m < gridH; ++m) {
+ xx = gridX + m * stepY;
+ yy = gridY + m * stepX;
+ for (n = 0; n < gridW; ++n) {
+ if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
+ ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
+ skipBitmap->setPixel(n, m);
+ }
+ }
+ }
+ }
+
+ // read the gray-scale image
+ grayImg = (Guint *)gmalloc(gridW * gridH * sizeof(Guint));
+ memset(grayImg, 0, gridW * gridH * sizeof(Guint));
+ atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1;
+ atx[1] = -3; aty[1] = -1;
+ atx[2] = 2; aty[2] = -2;
+ atx[3] = -2; aty[3] = -2;
+ for (j = bpp - 1; j >= 0; --j) {
+ grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
+ enableSkip, skipBitmap, atx, aty, -1);
+ i = 0;
+ for (m = 0; m < gridH; ++m) {
+ for (n = 0; n < gridW; ++n) {
+ bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
+ grayImg[i] = (grayImg[i] << 1) | bit;
+ ++i;
+ }
+ }
+ delete grayBitmap;
+ }
+
+ // decode the image
+ i = 0;
+ for (m = 0; m < gridH; ++m) {
+ xx = gridX + m * stepY;
+ yy = gridY + m * stepX;
+ for (n = 0; n < gridW; ++n) {
+ if (!(enableSkip && skipBitmap->getPixel(n, m))) {
+ patternBitmap = patternDict->getBitmap(grayImg[i]);
+ bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
+ }
+ xx += stepX;
+ yy -= stepY;
+ ++i;
+ }
+ }
+
+ gfree(grayImg);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ segments->append(bitmap);
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length) {
+ JBIG2Bitmap *bitmap;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, mmr, templ, tpgdOn;
+ int atx[4], aty[4];
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the generic region segment header
+ if (!readUByte(&flags)) {
+ goto eofError;
+ }
+ mmr = flags & 1;
+ templ = (flags >> 1) & 3;
+ tpgdOn = (flags >> 3) & 1;
+
+ // AT flags
+ if (!mmr) {
+ if (templ == 0) {
+ if (!readByte(&atx[0]) ||
+ !readByte(&aty[0]) ||
+ !readByte(&atx[1]) ||
+ !readByte(&aty[1]) ||
+ !readByte(&atx[2]) ||
+ !readByte(&aty[2]) ||
+ !readByte(&atx[3]) ||
+ !readByte(&aty[3])) {
+ goto eofError;
+ }
+ } else {
+ if (!readByte(&atx[0]) ||
+ !readByte(&aty[0])) {
+ goto eofError;
+ }
+ }
+ }
+
+ // set up the arithmetic decoder
+ if (!mmr) {
+ resetGenericStats(templ, NULL);
+ arithDecoder->start();
+ }
+
+ // read the bitmap
+ bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
+ NULL, atx, aty, mmr ? 0 : length - 18);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ bitmap->setSegNum(segNum);
+ segments->append(bitmap);
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
+ int templ, GBool tpgdOn,
+ GBool useSkip, JBIG2Bitmap *skip,
+ int *atx, int *aty,
+ int mmrDataLength) {
+ 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;
+
+ bitmap = new JBIG2Bitmap(0, w, h);
+ bitmap->clearToZero();
+
+ //----- MMR decode
+
+ if (mmr) {
+
+ mmrDecoder->reset();
+ refLine = (int *)gmalloc((w + 2) * sizeof(int));
+ codingLine = (int *)gmalloc((w + 2) * sizeof(int));
+ codingLine[0] = codingLine[1] = w;
+
+ for (y = 0; y < h; ++y) {
+
+ // copy coding line to ref line
+ for (i = 0; codingLine[i] < w; ++i) {
+ refLine[i] = codingLine[i];
+ }
+ refLine[i] = refLine[i + 1] = w;
+
+ // decode a line
+ refI = 0; // b1 = refLine[refI]
+ codingI = 0; // a1 = codingLine[codingI]
+ a0 = 0;
+ do {
+ code1 = mmrDecoder->get2DCode();
+ switch (code1) {
+ case twoDimPass:
+ if (refLine[refI] < w) {
+ a0 = refLine[refI + 1];
+ refI += 2;
+ }
+ break;
+ case twoDimHoriz:
+ if (codingI & 1) {
+ code1 = 0;
+ do {
+ code1 += code3 = mmrDecoder->getBlackCode();
+ } while (code3 >= 64);
+ code2 = 0;
+ do {
+ code2 += code3 = mmrDecoder->getWhiteCode();
+ } while (code3 >= 64);
+ } else {
+ code1 = 0;
+ do {
+ code1 += code3 = mmrDecoder->getWhiteCode();
+ } while (code3 >= 64);
+ code2 = 0;
+ do {
+ code2 += code3 = mmrDecoder->getBlackCode();
+ } while (code3 >= 64);
+ }
+ if (code1 > 0 || code2 > 0) {
+ a0 = codingLine[codingI++] = a0 + code1;
+ a0 = codingLine[codingI++] = a0 + code2;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVert0:
+ a0 = codingLine[codingI++] = refLine[refI];
+ if (refLine[refI] < w) {
+ ++refI;
+ }
+ break;
+ case twoDimVertR1:
+ a0 = codingLine[codingI++] = refLine[refI] + 1;
+ if (refLine[refI] < w) {
+ ++refI;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVertR2:
+ a0 = codingLine[codingI++] = refLine[refI] + 2;
+ if (refLine[refI] < w) {
+ ++refI;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVertR3:
+ a0 = codingLine[codingI++] = refLine[refI] + 3;
+ if (refLine[refI] < w) {
+ ++refI;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVertL1:
+ a0 = codingLine[codingI++] = refLine[refI] - 1;
+ if (refI > 0) {
+ --refI;
+ } else {
+ ++refI;
+ }
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ break;
+ case twoDimVertL2:
+ a0 = codingLine[codingI++] = refLine[refI] - 2;
+ if (refI > 0) {
+ --refI;
+ } else {
+ ++refI;
+ }
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ break;
+ case twoDimVertL3:
+ a0 = codingLine[codingI++] = refLine[refI] - 3;
+ if (refI > 0) {
+ --refI;
+ } else {
+ ++refI;
+ }
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ break;
+ default:
+ error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
+ break;
+ }
+ } while (a0 < w);
+ codingLine[codingI++] = w;
+
+ // convert the run lengths to a bitmap line
+ i = 0;
+ while (codingLine[i] < w) {
+ for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
+ bitmap->setPixel(x, y);
+ }
+ i += 2;
+ }
+ }
+
+ if (mmrDataLength >= 0) {
+ mmrDecoder->skipTo(mmrDataLength);
+ } else {
+ if (mmrDecoder->get24Bits() != 0x001001) {
+ error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
+ }
+ }
+
+ gfree(refLine);
+ gfree(codingLine);
+
+ //----- arithmetic decode
+
+ } else {
+ // set up the typical row context
+ ltpCX = 0; // make gcc happy
+ if (tpgdOn) {
+ switch (templ) {
+ case 0:
+ ltpCX = 0x3953; // 001 11001 0101 0011
+ break;
+ case 1:
+ ltpCX = 0x079a; // 0011 11001 101 0
+ break;
+ case 2:
+ ltpCX = 0x0e3; // 001 1100 01 1
+ break;
+ case 3:
+ ltpCX = 0x18a; // 01100 0101 1
+ break;
+ }
+ }
+
+ ltp = 0;
+ cx = cx0 = cx1 = cx2 = 0; // make gcc happy
+ for (y = 0; y < h; ++y) {
+
+ // check for a "typical" (duplicate) row
+ if (tpgdOn) {
+ if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
+ ltp = !ltp;
+ }
+ if (ltp) {
+ bitmap->duplicateRow(y, y-1);
+ continue;
+ }
+ }
+
+ switch (templ) {
+ case 0:
+
+ // 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:
+
+ // 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)) & 0x0f;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x07;
+ }
+ break;
+
+ case 2:
+
+ // 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 << 7) | (cx1 << 3) | (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)) & 0x0f;
+ cx2 = ((cx2 << 1) | pix) & 0x03;
+ }
+ break;
+
+ case 3:
+
+ // 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);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx1 << 5) | (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
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x0f;
+ }
+ break;
+ }
+ }
+ }
+
+ return bitmap;
+}
+
+void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs,
+ Guint nRefSegs) {
+ JBIG2Bitmap *bitmap, *refBitmap;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, templ, tpgrOn;
+ int atx[2], aty[2];
+ JBIG2Segment *seg;
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the generic refinement region segment header
+ if (!readUByte(&flags)) {
+ goto eofError;
+ }
+ templ = flags & 1;
+ tpgrOn = (flags >> 1) & 1;
+
+ // AT flags
+ if (!templ) {
+ if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
+ !readByte(&atx[1]) || !readByte(&aty[1])) {
+ goto eofError;
+ }
+ }
+
+ // resize the page bitmap if needed
+ if (nRefSegs == 0 || imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ }
+
+ // get referenced bitmap
+ if (nRefSegs > 1) {
+ error(getPos(), "Bad reference in JBIG2 generic refinement segment");
+ return;
+ }
+ if (nRefSegs == 1) {
+ seg = findSegment(refSegs[0]);
+ if (seg->getType() != jbig2SegBitmap) {
+ error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
+ return;
+ }
+ refBitmap = (JBIG2Bitmap *)seg;
+ } else {
+ refBitmap = pageBitmap->getSlice(x, y, w, h);
+ }
+
+ // set up the arithmetic decoder
+ resetRefinementStats(templ, NULL);
+ arithDecoder->start();
+
+ // read
+ bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
+ refBitmap, 0, 0, atx, aty);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ bitmap->setSegNum(segNum);
+ segments->append(bitmap);
+ }
+
+ // delete the referenced bitmap
+ if (nRefSegs == 1) {
+ discardSegment(refSegs[0]);
+ } else {
+ delete refBitmap;
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
+ int templ, GBool tpgrOn,
+ JBIG2Bitmap *refBitmap,
+ int refDX, int refDY,
+ int *atx, int *aty) {
+ 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);
+ bitmap->clearToZero();
+
+ // set up the typical row context
+ if (templ) {
+ ltpCX = 0x008;
+ } else {
+ ltpCX = 0x0010;
+ }
+
+ ltp = 0;
+ for (y = 0; y < h; ++y) {
+
+ if (templ) {
+
+ // 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) {
+ 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;
+ }
+ }
+
+ // 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);
+ }
+ }
+
+ } 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);
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+
+ return bitmap;
+}
+
+void JBIG2Stream::readPageInfoSeg(Guint length) {
+ Guint xRes, yRes, flags, striping;
+
+ if (!readULong(&pageW) || !readULong(&pageH) ||
+ !readULong(&xRes) || !readULong(&yRes) ||
+ !readUByte(&flags) || !readUWord(&striping)) {
+ goto eofError;
+ }
+ pageDefPixel = (flags >> 2) & 1;
+ defCombOp = (flags >> 3) & 3;
+
+ // allocate the page bitmap
+ if (pageH == 0xffffffff) {
+ curPageH = striping & 0x7fff;
+ } else {
+ curPageH = pageH;
+ }
+ pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
+
+ // default pixel value
+ if (pageDefPixel) {
+ pageBitmap->clearToOne();
+ } else {
+ pageBitmap->clearToZero();
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readEndOfStripeSeg(Guint length) {
+ Guint i;
+
+ // skip the segment
+ for (i = 0; i < length; ++i) {
+ curStr->getChar();
+ }
+}
+
+void JBIG2Stream::readProfilesSeg(Guint length) {
+ Guint i;
+
+ // skip the segment
+ for (i = 0; i < length; ++i) {
+ curStr->getChar();
+ }
+}
+
+void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
+ JBIG2HuffmanTable *huffTab;
+ Guint flags, oob, prefixBits, rangeBits;
+ int lowVal, highVal, val;
+ Guint huffTabSize, i;
+
+ if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
+ goto eofError;
+ }
+ oob = flags & 1;
+ prefixBits = ((flags >> 1) & 7) + 1;
+ rangeBits = ((flags >> 4) & 7) + 1;
+
+ huffDecoder->reset();
+ huffTabSize = 8;
+ huffTab = (JBIG2HuffmanTable *)
+ gmalloc(huffTabSize * sizeof(JBIG2HuffmanTable));
+ i = 0;
+ val = lowVal;
+ while (val < highVal) {
+ if (i == huffTabSize) {
+ huffTabSize *= 2;
+ huffTab = (JBIG2HuffmanTable *)
+ grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
+ }
+ huffTab[i].val = val;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
+ val += 1 << huffTab[i].rangeLen;
+ ++i;
+ }
+ if (i + oob + 3 > huffTabSize) {
+ huffTabSize = i + oob + 3;
+ huffTab = (JBIG2HuffmanTable *)
+ grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
+ }
+ huffTab[i].val = lowVal - 1;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = jbig2HuffmanLOW;
+ ++i;
+ huffTab[i].val = highVal;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = 32;
+ ++i;
+ if (oob) {
+ huffTab[i].val = 0;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = jbig2HuffmanOOB;
+ ++i;
+ }
+ huffTab[i].val = 0;
+ huffTab[i].prefixLen = 0;
+ huffTab[i].rangeLen = jbig2HuffmanEOT;
+ huffDecoder->buildTable(huffTab, i);
+
+ // create and store the new table segment
+ segments->append(new JBIG2CodeTable(segNum, huffTab));
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readExtensionSeg(Guint length) {
+ Guint i;
+
+ // skip the segment
+ for (i = 0; i < length; ++i) {
+ curStr->getChar();
+ }
+}
+
+JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
+ JBIG2Segment *seg;
+ int i;
+
+ for (i = 0; i < globalSegments->getLength(); ++i) {
+ seg = (JBIG2Segment *)globalSegments->get(i);
+ if (seg->getSegNum() == segNum) {
+ return seg;
+ }
+ }
+ for (i = 0; i < segments->getLength(); ++i) {
+ seg = (JBIG2Segment *)segments->get(i);
+ if (seg->getSegNum() == segNum) {
+ return seg;
+ }
+ }
+ return NULL;
+}
+
+void JBIG2Stream::discardSegment(Guint segNum) {
+ JBIG2Segment *seg;
+ int i;
+
+ for (i = 0; i < globalSegments->getLength(); ++i) {
+ seg = (JBIG2Segment *)globalSegments->get(i);
+ if (seg->getSegNum() == segNum) {
+ globalSegments->del(i);
+ return;
+ }
+ }
+ for (i = 0; i < segments->getLength(); ++i) {
+ seg = (JBIG2Segment *)segments->get(i);
+ if (seg->getSegNum() == segNum) {
+ segments->del(i);
+ return;
+ }
+ }
+}
+
+void JBIG2Stream::resetGenericStats(Guint templ,
+ JArithmeticDecoderStats *prevStats) {
+ int size;
+
+ size = contextSize[templ];
+ if (prevStats && prevStats->getContextSize() == size) {
+ if (genericRegionStats->getContextSize() == size) {
+ genericRegionStats->copyFrom(prevStats);
+ } else {
+ delete genericRegionStats;
+ genericRegionStats = prevStats->copy();
+ }
+ } else {
+ if (genericRegionStats->getContextSize() == size) {
+ genericRegionStats->reset();
+ } else {
+ delete genericRegionStats;
+ genericRegionStats = new JArithmeticDecoderStats(1 << size);
+ }
+ }
+}
+
+void JBIG2Stream::resetRefinementStats(Guint templ,
+ JArithmeticDecoderStats *prevStats) {
+ int size;
+
+ size = refContextSize[templ];
+ if (prevStats && prevStats->getContextSize() == size) {
+ if (refinementRegionStats->getContextSize() == size) {
+ refinementRegionStats->copyFrom(prevStats);
+ } else {
+ delete refinementRegionStats;
+ refinementRegionStats = prevStats->copy();
+ }
+ } else {
+ if (refinementRegionStats->getContextSize() == size) {
+ refinementRegionStats->reset();
+ } else {
+ delete refinementRegionStats;
+ refinementRegionStats = new JArithmeticDecoderStats(1 << size);
+ }
+ }
+}
+
+void JBIG2Stream::resetIntStats(int symCodeLen) {
+ iadhStats->reset();
+ iadwStats->reset();
+ iaexStats->reset();
+ iaaiStats->reset();
+ iadtStats->reset();
+ iaitStats->reset();
+ iafsStats->reset();
+ iadsStats->reset();
+ iardxStats->reset();
+ iardyStats->reset();
+ iardwStats->reset();
+ iardhStats->reset();
+ iariStats->reset();
+ if (iaidStats->getContextSize() == symCodeLen + 1) {
+ iaidStats->reset();
+ } else {
+ delete iaidStats;
+ iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
+ }
+}
+
+GBool JBIG2Stream::readUByte(Guint *x) {
+ int c0;
+
+ if ((c0 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)c0;
+ return gTrue;
+}
+
+GBool JBIG2Stream::readByte(int *x) {
+ int c0;
+
+ if ((c0 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = c0;
+ if (c0 & 0x80) {
+ *x |= -1 - 0xff;
+ }
+ return gTrue;
+}
+
+GBool JBIG2Stream::readUWord(Guint *x) {
+ int c0, c1;
+
+ if ((c0 = curStr->getChar()) == EOF ||
+ (c1 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)((c0 << 8) | c1);
+ return gTrue;
+}
+
+GBool JBIG2Stream::readULong(Guint *x) {
+ int c0, c1, c2, c3;
+
+ if ((c0 = curStr->getChar()) == EOF ||
+ (c1 = curStr->getChar()) == EOF ||
+ (c2 = curStr->getChar()) == EOF ||
+ (c3 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
+ return gTrue;
+}
+
+GBool JBIG2Stream::readLong(int *x) {
+ int c0, c1, c2, c3;
+
+ if ((c0 = curStr->getChar()) == EOF ||
+ (c1 = curStr->getChar()) == EOF ||
+ (c2 = curStr->getChar()) == EOF ||
+ (c3 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
+ if (c0 & 0x80) {
+ *x |= -1 - (int)0xffffffff;
+ }
+ return gTrue;
+}
diff --git a/pdf2swf/xpdf/JBIG2Stream.h b/pdf2swf/xpdf/JBIG2Stream.h
new file mode 100644
index 00000000..ed26d4e5
--- /dev/null
+++ b/pdf2swf/xpdf/JBIG2Stream.h
@@ -0,0 +1,143 @@
+//========================================================================
+//
+// JBIG2Stream.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef JBIG2STREAM_H
+#define JBIG2STREAM_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+#include "Stream.h"
+
+class GList;
+class JBIG2Segment;
+class JBIG2Bitmap;
+class JArithmeticDecoder;
+class JArithmeticDecoderStats;
+class JBIG2HuffmanDecoder;
+struct JBIG2HuffmanTable;
+class JBIG2MMRDecoder;
+
+//------------------------------------------------------------------------
+
+class JBIG2Stream: public FilterStream {
+public:
+
+ JBIG2Stream(Stream *strA, Object *globalsStream);
+ virtual ~JBIG2Stream();
+ virtual StreamKind getKind() { return strJBIG2; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ void readSegments();
+ void readSymbolDictSeg(Guint segNum, Guint length,
+ Guint *refSegs, Guint nRefSegs);
+ void readTextRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs);
+ JBIG2Bitmap *readTextRegion(GBool huff, GBool refine,
+ int w, int h,
+ Guint numInstances,
+ Guint logStrips,
+ int numSyms,
+ JBIG2HuffmanTable *symCodeTab,
+ Guint symCodeLen,
+ JBIG2Bitmap **syms,
+ Guint defPixel, Guint combOp,
+ Guint transposed, Guint refCorner,
+ int sOffset,
+ JBIG2HuffmanTable *huffFSTable,
+ JBIG2HuffmanTable *huffDSTable,
+ JBIG2HuffmanTable *huffDTTable,
+ JBIG2HuffmanTable *huffRDWTable,
+ JBIG2HuffmanTable *huffRDHTable,
+ JBIG2HuffmanTable *huffRDXTable,
+ JBIG2HuffmanTable *huffRDYTable,
+ JBIG2HuffmanTable *huffRSizeTable,
+ Guint templ,
+ int *atx, int *aty);
+ void readPatternDictSeg(Guint segNum, Guint length);
+ void readHalftoneRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs);
+ void readGenericRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length);
+ JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h,
+ int templ, GBool tpgdOn,
+ GBool useSkip, JBIG2Bitmap *skip,
+ int *atx, int *aty,
+ int mmrDataLength);
+ void readGenericRefinementRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs,
+ Guint nRefSegs);
+ JBIG2Bitmap *readGenericRefinementRegion(int w, int h,
+ int templ, GBool tpgrOn,
+ JBIG2Bitmap *refBitmap,
+ int refDX, int refDY,
+ int *atx, int *aty);
+ void readPageInfoSeg(Guint length);
+ void readEndOfStripeSeg(Guint length);
+ void readProfilesSeg(Guint length);
+ void readCodeTableSeg(Guint segNum, Guint length);
+ void readExtensionSeg(Guint length);
+ JBIG2Segment *findSegment(Guint segNum);
+ void discardSegment(Guint segNum);
+ void resetGenericStats(Guint templ,
+ JArithmeticDecoderStats *prevStats);
+ void resetRefinementStats(Guint templ,
+ JArithmeticDecoderStats *prevStats);
+ void resetIntStats(int symCodeLen);
+ GBool readUByte(Guint *x);
+ GBool readByte(int *x);
+ GBool readUWord(Guint *x);
+ GBool readULong(Guint *x);
+ GBool readLong(int *x);
+
+ Guint pageW, pageH, curPageH;
+ Guint pageDefPixel;
+ JBIG2Bitmap *pageBitmap;
+ Guint defCombOp;
+ GList *segments; // [JBIG2Segment]
+ GList *globalSegments; // [JBIG2Segment]
+ Stream *curStr;
+ Guchar *dataPtr;
+ Guchar *dataEnd;
+
+ JArithmeticDecoder *arithDecoder;
+ JArithmeticDecoderStats *genericRegionStats;
+ JArithmeticDecoderStats *refinementRegionStats;
+ JArithmeticDecoderStats *iadhStats;
+ JArithmeticDecoderStats *iadwStats;
+ JArithmeticDecoderStats *iaexStats;
+ JArithmeticDecoderStats *iaaiStats;
+ JArithmeticDecoderStats *iadtStats;
+ JArithmeticDecoderStats *iaitStats;
+ JArithmeticDecoderStats *iafsStats;
+ JArithmeticDecoderStats *iadsStats;
+ JArithmeticDecoderStats *iardxStats;
+ JArithmeticDecoderStats *iardyStats;
+ JArithmeticDecoderStats *iardwStats;
+ JArithmeticDecoderStats *iardhStats;
+ JArithmeticDecoderStats *iariStats;
+ JArithmeticDecoderStats *iaidStats;
+ JBIG2HuffmanDecoder *huffDecoder;
+ JBIG2MMRDecoder *mmrDecoder;
+};
+
+#endif
diff --git a/pdf2swf/xpdf/JPXStream.cc b/pdf2swf/xpdf/JPXStream.cc
new file mode 100644
index 00000000..defa7d2a
--- /dev/null
+++ b/pdf2swf/xpdf/JPXStream.cc
@@ -0,0 +1,2822 @@
+//========================================================================
+//
+// JPXStream.cc
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "Error.h"
+#include "JArithmeticDecoder.h"
+#include "JPXStream.h"
+
+//~ to do:
+// - precincts
+// - ROI
+// - progression order changes
+// - packed packet headers
+// - support for palettes, channel maps, etc.
+// - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
+// - can we assume that QCC segments must come after the QCD segment?
+// - skip EPH markers (readTilePartData)
+// - handle tilePartToEOC in readTilePartData
+// - deal with multiple codeword segments (readTilePartData,
+// readCodeBlockData)
+// - progression orders 2, 3, and 4
+// - in coefficient decoding (readCodeBlockData):
+// - termination pattern: terminate after every coding pass
+// - error resilience segmentation symbol
+// - selective arithmetic coding bypass
+// - vertically causal context formation
+// - coeffs longer than 31 bits (should just ignore the extra bits?)
+// - handle boxes larger than 2^32 bytes
+// - the fixed-point arithmetic won't handle 16-bit pixels
+
+//------------------------------------------------------------------------
+
+// number of contexts for the arithmetic decoder
+#define jpxNContexts 19
+
+#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
+#define jpxContextSign 9 // 9 - 13: sign
+#define jpxContextMagRef 14 // 14 -16: magnitude refinement
+#define jpxContextRunLength 17 // cleanup: run length
+#define jpxContextUniform 18 // cleanup: first signif coeff
+
+//------------------------------------------------------------------------
+
+#define jpxPassSigProp 0
+#define jpxPassMagRef 1
+#define jpxPassCleanup 2
+
+//------------------------------------------------------------------------
+
+// arithmetic decoder context for the significance propagation and
+// cleanup passes:
+// [horiz][vert][diag][subband]
+// where subband = 0 for HL
+// = 1 for LH and LL
+// = 2 for HH
+static Guint sigPropContext[3][3][5][3] = {
+ {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0
+ { 1, 1, 3 }, // horiz=0, vert=0, diag=1
+ { 2, 2, 6 }, // horiz=0, vert=0, diag=2
+ { 2, 2, 8 }, // horiz=0, vert=0, diag=3
+ { 2, 2, 8 }}, // horiz=0, vert=0, diag=4
+ {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0
+ { 6, 3, 4 }, // horiz=0, vert=1, diag=1
+ { 6, 3, 7 }, // horiz=0, vert=1, diag=2
+ { 6, 3, 8 }, // horiz=0, vert=1, diag=3
+ { 6, 3, 8 }}, // horiz=0, vert=1, diag=4
+ {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0
+ { 8, 4, 5 }, // horiz=0, vert=2, diag=1
+ { 8, 4, 7 }, // horiz=0, vert=2, diag=2
+ { 8, 4, 8 }, // horiz=0, vert=2, diag=3
+ { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4
+ {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0
+ { 3, 6, 4 }, // horiz=1, vert=0, diag=1
+ { 3, 6, 7 }, // horiz=1, vert=0, diag=2
+ { 3, 6, 8 }, // horiz=1, vert=0, diag=3
+ { 3, 6, 8 }}, // horiz=1, vert=0, diag=4
+ {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0
+ { 7, 7, 5 }, // horiz=1, vert=1, diag=1
+ { 7, 7, 7 }, // horiz=1, vert=1, diag=2
+ { 7, 7, 8 }, // horiz=1, vert=1, diag=3
+ { 7, 7, 8 }}, // horiz=1, vert=1, diag=4
+ {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0
+ { 8, 7, 5 }, // horiz=1, vert=2, diag=1
+ { 8, 7, 7 }, // horiz=1, vert=2, diag=2
+ { 8, 7, 8 }, // horiz=1, vert=2, diag=3
+ { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4
+ {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0
+ { 4, 8, 5 }, // horiz=2, vert=0, diag=1
+ { 4, 8, 7 }, // horiz=2, vert=0, diag=2
+ { 4, 8, 8 }, // horiz=2, vert=0, diag=3
+ { 4, 8, 8 }}, // horiz=2, vert=0, diag=4
+ {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0
+ { 7, 8, 5 }, // horiz=2, vert=1, diag=1
+ { 7, 8, 7 }, // horiz=2, vert=1, diag=2
+ { 7, 8, 8 }, // horiz=2, vert=1, diag=3
+ { 7, 8, 8 }}, // horiz=2, vert=1, diag=4
+ {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0
+ { 8, 8, 5 }, // horiz=2, vert=2, diag=1
+ { 8, 8, 7 }, // horiz=2, vert=2, diag=2
+ { 8, 8, 8 }, // horiz=2, vert=2, diag=3
+ { 8, 8, 8 }}} // horiz=2, vert=2, diag=4
+};
+
+// arithmetic decoder context and xor bit for the sign bit in the
+// significance propagation pass:
+// [horiz][vert][k]
+// where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
+// and k = 0 for the context
+// = 1 for the xor bit
+static Guint signContext[5][5][2] = {
+ {{ 13, 1 }, // horiz=-2, vert=-2
+ { 13, 1 }, // horiz=-2, vert=-1
+ { 12, 1 }, // horiz=-2, vert= 0
+ { 11, 1 }, // horiz=-2, vert=+1
+ { 11, 1 }}, // horiz=-2, vert=+2
+ {{ 13, 1 }, // horiz=-1, vert=-2
+ { 13, 1 }, // horiz=-1, vert=-1
+ { 12, 1 }, // horiz=-1, vert= 0
+ { 11, 1 }, // horiz=-1, vert=+1
+ { 11, 1 }}, // horiz=-1, vert=+2
+ {{ 10, 1 }, // horiz= 0, vert=-2
+ { 10, 1 }, // horiz= 0, vert=-1
+ { 9, 0 }, // horiz= 0, vert= 0
+ { 10, 0 }, // horiz= 0, vert=+1
+ { 10, 0 }}, // horiz= 0, vert=+2
+ {{ 11, 0 }, // horiz=+1, vert=-2
+ { 11, 0 }, // horiz=+1, vert=-1
+ { 12, 0 }, // horiz=+1, vert= 0
+ { 13, 0 }, // horiz=+1, vert=+1
+ { 13, 0 }}, // horiz=+1, vert=+2
+ {{ 11, 0 }, // horiz=+2, vert=-2
+ { 11, 0 }, // horiz=+2, vert=-1
+ { 12, 0 }, // horiz=+2, vert= 0
+ { 13, 0 }, // horiz=+2, vert=+1
+ { 13, 0 }}, // horiz=+2, vert=+2
+};
+
+//------------------------------------------------------------------------
+
+// constants used in the IDWT
+#define idwtAlpha -1.586134342059924
+#define idwtBeta -0.052980118572961
+#define idwtGamma 0.882911075530934
+#define idwtDelta 0.443506852043971
+#define idwtKappa 1.230174104914001
+#define idwtIKappa (1.0 / idwtKappa)
+
+// number of bits to the right of the decimal point for the fixed
+// point arithmetic used in the IDWT
+#define fracBits 16
+
+//------------------------------------------------------------------------
+
+// floor(x / y)
+#define jpxFloorDiv(x, y) ((x) / (y))
+
+// floor(x / 2^y)
+#define jpxFloorDivPow2(x, y) ((x) >> (y))
+
+// ceil(x / y)
+#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
+
+// ceil(x / 2^y)
+#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
+
+//------------------------------------------------------------------------
+
+JPXStream::JPXStream(Stream *strA):
+ FilterStream(strA)
+{
+ nComps = 0;
+ bpc = NULL;
+ width = height = 0;
+ haveCS = gFalse;
+ havePalette = gFalse;
+ haveCompMap = gFalse;
+ haveChannelDefn = gFalse;
+
+ img.tiles = NULL;
+ bitBuf = 0;
+ bitBufLen = 0;
+ bitBufSkip = gFalse;
+ byteCount = 0;
+}
+
+JPXStream::~JPXStream() {
+ JPXTile *tile;
+ JPXTileComp *tileComp;
+ JPXResLevel *resLevel;
+ JPXPrecinct *precinct;
+ JPXSubband *subband;
+ JPXCodeBlock *cb;
+ Guint comp, i, k, r, pre, sb;
+
+ gfree(bpc);
+ if (havePalette) {
+ gfree(palette.bpc);
+ gfree(palette.c);
+ }
+ if (haveCompMap) {
+ gfree(compMap.comp);
+ gfree(compMap.type);
+ gfree(compMap.pComp);
+ }
+ if (haveChannelDefn) {
+ gfree(channelDefn.idx);
+ gfree(channelDefn.type);
+ gfree(channelDefn.assoc);
+ }
+
+ if (img.tiles) {
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ tile = &img.tiles[i];
+ if (tile->tileComps) {
+ for (comp = 0; comp < img.nComps; ++comp) {
+ tileComp = &tile->tileComps[comp];
+ gfree(tileComp->quantSteps);
+ gfree(tileComp->data);
+ gfree(tileComp->buf);
+ if (tileComp->resLevels) {
+ for (r = 0; r <= tileComp->nDecompLevels; ++r) {
+ resLevel = &tileComp->resLevels[r];
+ if (resLevel->precincts) {
+ for (pre = 0; pre < 1; ++pre) {
+ precinct = &resLevel->precincts[pre];
+ if (precinct->subbands) {
+ for (sb = 0; sb < (r == 0 ? 1 : 3); ++sb) {
+ subband = &precinct->subbands[sb];
+ gfree(subband->inclusion);
+ gfree(subband->zeroBitPlane);
+ if (subband->cbs) {
+ for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
+ cb = &subband->cbs[k];
+ gfree(cb->coeffs);
+ if (cb->stats) {
+ delete cb->stats;
+ }
+ }
+ gfree(subband->cbs);
+ }
+ }
+ gfree(precinct->subbands);
+ }
+ }
+ gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts);
+ }
+ }
+ gfree(img.tiles[i].tileComps[comp].resLevels);
+ }
+ }
+ gfree(img.tiles[i].tileComps);
+ }
+ }
+ gfree(img.tiles);
+ }
+ delete str;
+}
+
+void JPXStream::reset() {
+ str->reset();
+ if (readBoxes()) {
+ curY = img.yOffset;
+ } else {
+ // readBoxes reported an error, so we go immediately to EOF
+ curY = img.ySize;
+ }
+ curX = img.xOffset;
+ curComp = 0;
+ readBufLen = 0;
+}
+
+int JPXStream::getChar() {
+ int c;
+
+ if (readBufLen < 8) {
+ fillReadBuf();
+ }
+ if (readBufLen == 8) {
+ c = readBuf & 0xff;
+ readBufLen = 0;
+ } else if (readBufLen > 8) {
+ c = (readBuf >> (readBufLen - 8)) & 0xff;
+ readBufLen -= 8;
+ } else if (readBufLen == 0) {
+ c = EOF;
+ } else {
+ c = (readBuf << (8 - readBufLen)) & 0xff;
+ readBufLen = 0;
+ }
+ return c;
+}
+
+int JPXStream::lookChar() {
+ int c;
+
+ if (readBufLen < 8) {
+ fillReadBuf();
+ }
+ if (readBufLen == 8) {
+ c = readBuf & 0xff;
+ } else if (readBufLen > 8) {
+ c = (readBuf >> (readBufLen - 8)) & 0xff;
+ } else if (readBufLen == 0) {
+ c = EOF;
+ } else {
+ c = (readBuf << (8 - readBufLen)) & 0xff;
+ }
+ return c;
+}
+
+void JPXStream::fillReadBuf() {
+ JPXTileComp *tileComp;
+ Guint tileIdx, tx, ty;
+ int pix, pixBits;
+
+ do {
+ if (curY >= img.ySize) {
+ return;
+ }
+ tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles
+ + (curX - img.xTileOffset) / img.xTileSize;
+#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
+ tileComp = &img.tiles[tileIdx].tileComps[curComp];
+#else
+ tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
+#endif
+ tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep);
+ ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep);
+ pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx];
+ pixBits = tileComp->prec;
+#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
+ if (++curComp == img.nComps) {
+#else
+ if (havePalette) {
+ if (pix >= 0 && pix < palette.nEntries) {
+ pix = palette.c[pix * palette.nComps + curComp];
+ } else {
+ pix =
+ pixBits = palette.bpc[curComp];
+ }
+ if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {
+#endif
+ curComp = 0;
+ if (++curX == img.xSize) {
+ curX = img.xOffset;
+ ++curY;
+ }
+ }
+ if (pixBits == 8) {
+ readBuf = (readBuf << 8) | (pix & 0xff);
+ } else {
+ readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1));
+ }
+ readBufLen += pixBits;
+ } while (readBufLen < 8);
+}
+
+GString *JPXStream::getPSFilter(int psLevel, char *indent) {
+ return NULL;
+}
+
+GBool JPXStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+GBool JPXStream::readBoxes() {
+ Guint boxType, boxLen, dataLen;
+ Guint bpc1, compression, unknownColorspace, ipr;
+ Guint i, j;
+
+ haveImgHdr = gFalse;
+
+ // check for a naked JPEG 2000 codestream (without the JP2/JPX
+ // wrapper) -- this appears to be a violation of the PDF spec, but
+ // Acrobat allows it
+ if (str->lookChar() == 0xff) {
+ error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
+ readCodestream(0);
+ nComps = img.nComps;
+ bpc = (Guint *)gmalloc(nComps * sizeof(Guint));
+ for (i = 0; i < nComps; ++i) {
+ bpc[i] = img.tiles[0].tileComps[i].prec;
+ }
+ width = img.xSize - img.xOffset;
+ height = img.ySize - img.yOffset;
+ return gTrue;
+ }
+
+ while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
+ switch (boxType) {
+ case 0x6a703268: // JP2 header
+ // this is a grouping box ('superbox') which has no real
+ // contents and doesn't appear to be used consistently, i.e.,
+ // some things which should be subboxes of the JP2 header box
+ // show up outside of it - so we simply ignore the JP2 header
+ // box
+ break;
+ case 0x69686472: // image header
+ if (!readULong(&height) ||
+ !readULong(&width) ||
+ !readUWord(&nComps) ||
+ !readUByte(&bpc1) ||
+ !readUByte(&compression) ||
+ !readUByte(&unknownColorspace) ||
+ !readUByte(&ipr)) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ if (compression != 7) {
+ error(getPos(), "Unknown compression type in JPX stream");
+ return gFalse;
+ }
+ bpc = (Guint *)gmalloc(nComps * sizeof(Guint));
+ for (i = 0; i < nComps; ++i) {
+ bpc[i] = bpc1;
+ }
+ haveImgHdr = gTrue;
+ break;
+ case 0x62706363: // bits per component
+ if (!haveImgHdr) {
+ error(getPos(), "Found bits per component box before image header box in JPX stream");
+ return gFalse;
+ }
+ if (dataLen != nComps) {
+ error(getPos(), "Invalid bits per component box in JPX stream");
+ return gFalse;
+ }
+ for (i = 0; i < nComps; ++i) {
+ if (!readUByte(&bpc[i])) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x636F6C72: // color specification
+ if (!readColorSpecBox(dataLen)) {
+ return gFalse;
+ }
+ break;
+ case 0x70636c72: // palette
+ if (!readUWord(&palette.nEntries) ||
+ !readUByte(&palette.nComps)) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ palette.bpc = (Guint *)gmalloc(palette.nComps * sizeof(Guint));
+ palette.c =
+ (int *)gmalloc(palette.nEntries * palette.nComps * sizeof(int));
+ for (i = 0; i < palette.nComps; ++i) {
+ if (!readUByte(&palette.bpc[i])) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ ++palette.bpc[i];
+ }
+ for (i = 0; i < palette.nEntries; ++i) {
+ for (j = 0; j < palette.nComps; ++j) {
+ if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3,
+ (palette.bpc[j] & 0x80) ? gTrue : gFalse,
+ &palette.c[i * palette.nComps + j])) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ }
+ }
+ havePalette = gTrue;
+ break;
+ case 0x636d6170: // component mapping
+ compMap.nChannels = dataLen / 4;
+ compMap.comp = (Guint *)gmalloc(compMap.nChannels * sizeof(Guint));
+ compMap.type = (Guint *)gmalloc(compMap.nChannels * sizeof(Guint));
+ compMap.pComp = (Guint *)gmalloc(compMap.nChannels * sizeof(Guint));
+ for (i = 0; i < compMap.nChannels; ++i) {
+ if (!readUWord(&compMap.comp[i]) ||
+ !readUByte(&compMap.type[i]) ||
+ !readUByte(&compMap.pComp[i])) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ }
+ haveCompMap = gTrue;
+ break;
+ case 0x63646566: // channel definition
+ if (!readUWord(&channelDefn.nChannels)) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ channelDefn.idx =
+ (Guint *)gmalloc(channelDefn.nChannels * sizeof(Guint));
+ channelDefn.type =
+ (Guint *)gmalloc(channelDefn.nChannels * sizeof(Guint));
+ channelDefn.assoc =
+ (Guint *)gmalloc(channelDefn.nChannels * sizeof(Guint));
+ for (i = 0; i < channelDefn.nChannels; ++i) {
+ if (!readUWord(&channelDefn.idx[i]) ||
+ !readUWord(&channelDefn.type[i]) ||
+ !readUWord(&channelDefn.assoc[i])) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ }
+ haveChannelDefn = gTrue;
+ break;
+ case 0x6A703263: // contiguous codestream
+ if (!bpc) {
+ error(getPos(), "JPX stream is missing the image header box");
+ return gFalse;
+ }
+ if (!haveCS) {
+ error(getPos(), "JPX stream has no supported color spec");
+ return gFalse;
+ }
+ if (!readCodestream(dataLen)) {
+ return gFalse;
+ }
+ break;
+ default:
+ for (i = 0; i < dataLen; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Unexpected EOF in JPX stream");
+ return gFalse;
+ }
+ }
+ break;
+ }
+ }
+ return gTrue;
+}
+
+GBool JPXStream::readColorSpecBox(Guint dataLen) {
+ JPXColorSpec newCS;
+ Guint csApprox, csEnum;
+ Guint i;
+ GBool ok;
+
+ ok = gFalse;
+ if (!readUByte(&newCS.meth) ||
+ !readByte(&newCS.prec) ||
+ !readUByte(&csApprox)) {
+ goto err;
+ }
+ switch (newCS.meth) {
+ case 1: // enumerated colorspace
+ if (!readULong(&csEnum)) {
+ goto err;
+ }
+ newCS.enumerated.type = (JPXColorSpaceType)csEnum;
+ switch (newCS.enumerated.type) {
+ case jpxCSBiLevel:
+ ok = gTrue;
+ break;
+ case jpxCSYCbCr1:
+ ok = gTrue;
+ break;
+ case jpxCSYCbCr2:
+ ok = gTrue;
+ break;
+ case jpxCSYCBCr3:
+ ok = gTrue;
+ break;
+ case jpxCSPhotoYCC:
+ ok = gTrue;
+ break;
+ case jpxCSCMY:
+ ok = gTrue;
+ break;
+ case jpxCSCMYK:
+ ok = gTrue;
+ break;
+ case jpxCSYCCK:
+ ok = gTrue;
+ break;
+ case jpxCSCIELab:
+ if (dataLen == 3 + 7*4) {
+ if (!readULong(&newCS.enumerated.cieLab.rl) ||
+ !readULong(&newCS.enumerated.cieLab.ol) ||
+ !readULong(&newCS.enumerated.cieLab.ra) ||
+ !readULong(&newCS.enumerated.cieLab.oa) ||
+ !readULong(&newCS.enumerated.cieLab.rb) ||
+ !readULong(&newCS.enumerated.cieLab.ob) ||
+ !readULong(&newCS.enumerated.cieLab.il)) {
+ goto err;
+ }
+ } else if (dataLen == 3) {
+ //~ this assumes the 8-bit case
+ newCS.enumerated.cieLab.rl = 100;
+ newCS.enumerated.cieLab.ol = 0;
+ newCS.enumerated.cieLab.ra = 255;
+ newCS.enumerated.cieLab.oa = 128;
+ newCS.enumerated.cieLab.rb = 255;
+ newCS.enumerated.cieLab.ob = 96;
+ newCS.enumerated.cieLab.il = 0x00443530;
+ } else {
+ goto err;
+ }
+ ok = gTrue;
+ break;
+ case jpxCSsRGB:
+ ok = gTrue;
+ break;
+ case jpxCSGrayscale:
+ ok = gTrue;
+ break;
+ case jpxCSBiLevel2:
+ ok = gTrue;
+ break;
+ case jpxCSCIEJab:
+ // not allowed in PDF
+ goto err;
+ case jpxCSCISesRGB:
+ ok = gTrue;
+ break;
+ case jpxCSROMMRGB:
+ ok = gTrue;
+ break;
+ case jpxCSsRGBYCbCr:
+ ok = gTrue;
+ break;
+ case jpxCSYPbPr1125:
+ ok = gTrue;
+ break;
+ case jpxCSYPbPr1250:
+ ok = gTrue;
+ break;
+ default:
+ goto err;
+ }
+ break;
+ case 2: // restricted ICC profile
+ case 3: // any ICC profile (JPX)
+ case 4: // vendor color (JPX)
+ for (i = 0; i < dataLen - 3; ++i) {
+ if (str->getChar() == EOF) {
+ goto err;
+ }
+ }
+ break;
+ }
+
+ if (ok && (!haveCS || newCS.prec > cs.prec)) {
+ cs = newCS;
+ haveCS = gTrue;
+ }
+
+ return gTrue;
+
+ err:
+ error(getPos(), "Error in JPX color spec");
+ return gFalse;
+}
+
+GBool JPXStream::readCodestream(Guint len) {
+ JPXTile *tile;
+ JPXTileComp *tileComp;
+ int segType;
+ GBool haveSIZ, haveCOD, haveQCD, haveSOT;
+ Guint precinctSize, style;
+ Guint segLen, capabilities, comp, i, j, r;
+
+ //----- main header
+ haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
+ do {
+ if (!readMarkerHdr(&segType, &segLen)) {
+ error(getPos(), "Error in JPX codestream");
+ return gFalse;
+ }
+ switch (segType) {
+ case 0x4f: // SOC - start of codestream
+ // marker only
+ break;
+ case 0x51: // SIZ - image and tile size
+ if (!readUWord(&capabilities) ||
+ !readULong(&img.xSize) ||
+ !readULong(&img.ySize) ||
+ !readULong(&img.xOffset) ||
+ !readULong(&img.yOffset) ||
+ !readULong(&img.xTileSize) ||
+ !readULong(&img.yTileSize) ||
+ !readULong(&img.xTileOffset) ||
+ !readULong(&img.yTileOffset) ||
+ !readUWord(&img.nComps)) {
+ error(getPos(), "Error in JPX SIZ marker segment");
+ return gFalse;
+ }
+ if (haveImgHdr && img.nComps != nComps) {
+ error(getPos(), "Different number of components in JPX SIZ marker segment");
+ return gFalse;
+ }
+ img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
+ / img.xTileSize;
+ img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
+ / img.yTileSize;
+ img.tiles = (JPXTile *)gmalloc(img.nXTiles * img.nYTiles *
+ sizeof(JPXTile));
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ img.tiles[i].tileComps = (JPXTileComp *)gmalloc(img.nComps *
+ sizeof(JPXTileComp));
+ for (comp = 0; comp < img.nComps; ++comp) {
+ img.tiles[i].tileComps[comp].quantSteps = NULL;
+ img.tiles[i].tileComps[comp].data = NULL;
+ img.tiles[i].tileComps[comp].buf = NULL;
+ img.tiles[i].tileComps[comp].resLevels = NULL;
+ }
+ }
+ for (comp = 0; comp < img.nComps; ++comp) {
+ if (!readUByte(&img.tiles[0].tileComps[comp].prec) ||
+ !readUByte(&img.tiles[0].tileComps[comp].hSep) ||
+ !readUByte(&img.tiles[0].tileComps[comp].vSep)) {
+ error(getPos(), "Error in JPX SIZ marker segment");
+ return gFalse;
+ }
+ img.tiles[0].tileComps[comp].sgned =
+ (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse;
+ img.tiles[0].tileComps[comp].prec =
+ (img.tiles[0].tileComps[comp].prec & 0x7f) + 1;
+ for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
+ img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp];
+ }
+ }
+ haveSIZ = gTrue;
+ break;
+ case 0x52: // COD - coding style default
+ if (!readUByte(&img.tiles[0].tileComps[0].style) ||
+ !readUByte(&img.tiles[0].progOrder) ||
+ !readUWord(&img.tiles[0].nLayers) ||
+ !readUByte(&img.tiles[0].multiComp) ||
+ !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) ||
+ !readUByte(&img.tiles[0].tileComps[0].codeBlockW) ||
+ !readUByte(&img.tiles[0].tileComps[0].codeBlockH) ||
+ !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) ||
+ !readUByte(&img.tiles[0].tileComps[0].transform)) {
+ error(getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ img.tiles[0].tileComps[0].codeBlockW += 2;
+ img.tiles[0].tileComps[0].codeBlockH += 2;
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ if (i != 0) {
+ img.tiles[i].progOrder = img.tiles[0].progOrder;
+ img.tiles[i].nLayers = img.tiles[0].nLayers;
+ img.tiles[i].multiComp = img.tiles[0].multiComp;
+ }
+ for (comp = 0; comp < img.nComps; ++comp) {
+ if (!(i == 0 && comp == 0)) {
+ img.tiles[i].tileComps[comp].style =
+ img.tiles[0].tileComps[0].style;
+ img.tiles[i].tileComps[comp].nDecompLevels =
+ img.tiles[0].tileComps[0].nDecompLevels;
+ img.tiles[i].tileComps[comp].codeBlockW =
+ img.tiles[0].tileComps[0].codeBlockW;
+ img.tiles[i].tileComps[comp].codeBlockH =
+ img.tiles[0].tileComps[0].codeBlockH;
+ img.tiles[i].tileComps[comp].codeBlockStyle =
+ img.tiles[0].tileComps[0].codeBlockStyle;
+ img.tiles[i].tileComps[comp].transform =
+ img.tiles[0].tileComps[0].transform;
+ }
+ img.tiles[i].tileComps[comp].resLevels =
+ (JPXResLevel *)gmalloc(
+ (img.tiles[i].tileComps[comp].nDecompLevels + 1) *
+ sizeof(JPXResLevel));
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
+ img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
+ }
+ }
+ }
+ for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
+ if (img.tiles[0].tileComps[0].style & 0x01) {
+ if (!readUByte(&precinctSize)) {
+ error(getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
+ precinctSize & 0x0f;
+ img.tiles[0].tileComps[0].resLevels[r].precinctHeight =
+ (precinctSize >> 4) & 0x0f;
+ } else {
+ img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15;
+ img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15;
+ }
+ }
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ for (comp = 0; comp < img.nComps; ++comp) {
+ if (!(i == 0 && comp == 0)) {
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
+ img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
+ img.tiles[0].tileComps[0].resLevels[r].precinctWidth;
+ img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
+ img.tiles[0].tileComps[0].resLevels[r].precinctHeight;
+ }
+ }
+ }
+ }
+ haveCOD = gTrue;
+ break;
+ case 0x53: // COC - coding style component
+ if (!haveCOD) {
+ error(getPos(), "JPX COC marker segment before COD segment");
+ return gFalse;
+ }
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
+ (img.nComps <= 256 && !readUByte(&comp)) ||
+ comp >= img.nComps ||
+ !readUByte(&style) ||
+ !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) ||
+ !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) ||
+ !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) ||
+ !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) ||
+ !readUByte(&img.tiles[0].tileComps[comp].transform)) {
+ error(getPos(), "Error in JPX COC marker segment");
+ return gFalse;
+ }
+ img.tiles[0].tileComps[comp].style =
+ (img.tiles[0].tileComps[comp].style & ~1) | (style & 1);
+ img.tiles[0].tileComps[comp].codeBlockW += 2;
+ img.tiles[0].tileComps[comp].codeBlockH += 2;
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ if (i != 0) {
+ img.tiles[i].tileComps[comp].style =
+ img.tiles[0].tileComps[comp].style;
+ img.tiles[i].tileComps[comp].nDecompLevels =
+ img.tiles[0].tileComps[comp].nDecompLevels;
+ img.tiles[i].tileComps[comp].codeBlockW =
+ img.tiles[0].tileComps[comp].codeBlockW;
+ img.tiles[i].tileComps[comp].codeBlockH =
+ img.tiles[0].tileComps[comp].codeBlockH;
+ img.tiles[i].tileComps[comp].codeBlockStyle =
+ img.tiles[0].tileComps[comp].codeBlockStyle;
+ img.tiles[i].tileComps[comp].transform =
+ img.tiles[0].tileComps[comp].transform;
+ }
+ img.tiles[i].tileComps[comp].resLevels =
+ (JPXResLevel *)grealloc(
+ img.tiles[i].tileComps[comp].resLevels,
+ (img.tiles[i].tileComps[comp].nDecompLevels + 1) *
+ sizeof(JPXResLevel));
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
+ img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
+ }
+ }
+ for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
+ if (img.tiles[0].tileComps[comp].style & 0x01) {
+ if (!readUByte(&precinctSize)) {
+ error(getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
+ precinctSize & 0x0f;
+ img.tiles[0].tileComps[comp].resLevels[r].precinctHeight =
+ (precinctSize >> 4) & 0x0f;
+ } else {
+ img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15;
+ img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15;
+ }
+ }
+ for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
+ img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
+ img.tiles[0].tileComps[comp].resLevels[r].precinctWidth;
+ img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
+ img.tiles[0].tileComps[comp].resLevels[r].precinctHeight;
+ }
+ }
+ break;
+ case 0x5c: // QCD - quantization default
+ if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
+ img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
+ img.tiles[0].tileComps[0].quantSteps =
+ (Guint *)grealloc(img.tiles[0].tileComps[0].quantSteps,
+ img.tiles[0].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
+ if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ }
+ } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) {
+ img.tiles[0].tileComps[0].nQuantSteps = 1;
+ img.tiles[0].tileComps[0].quantSteps =
+ (Guint *)grealloc(img.tiles[0].tileComps[0].quantSteps,
+ img.tiles[0].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
+ img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
+ img.tiles[0].tileComps[0].quantSteps =
+ (Guint *)grealloc(img.tiles[0].tileComps[0].quantSteps,
+ img.tiles[0].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
+ if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ }
+ } else {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ for (comp = 0; comp < img.nComps; ++comp) {
+ if (!(i == 0 && comp == 0)) {
+ img.tiles[i].tileComps[comp].quantStyle =
+ img.tiles[0].tileComps[0].quantStyle;
+ img.tiles[i].tileComps[comp].nQuantSteps =
+ img.tiles[0].tileComps[0].nQuantSteps;
+ img.tiles[i].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[i].tileComps[comp].quantSteps,
+ img.tiles[0].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) {
+ img.tiles[i].tileComps[comp].quantSteps[j] =
+ img.tiles[0].tileComps[0].quantSteps[j];
+ }
+ }
+ }
+ }
+ haveQCD = gTrue;
+ break;
+ case 0x5d: // QCC - quantization component
+ if (!haveQCD) {
+ error(getPos(), "JPX QCC marker segment before QCD segment");
+ return gFalse;
+ }
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
+ (img.nComps <= 256 && !readUByte(&comp)) ||
+ comp >= img.nComps ||
+ !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
+ img.tiles[0].tileComps[comp].nQuantSteps =
+ segLen - (img.nComps > 256 ? 5 : 4);
+ img.tiles[0].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[0].tileComps[comp].quantSteps,
+ img.tiles[0].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
+ if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ }
+ } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) {
+ img.tiles[0].tileComps[comp].nQuantSteps = 1;
+ img.tiles[0].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[0].tileComps[comp].quantSteps,
+ img.tiles[0].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
+ img.tiles[0].tileComps[comp].nQuantSteps =
+ (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
+ img.tiles[0].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[0].tileComps[comp].quantSteps,
+ img.tiles[0].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
+ if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ }
+ } else {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
+ img.tiles[i].tileComps[comp].quantStyle =
+ img.tiles[0].tileComps[comp].quantStyle;
+ img.tiles[i].tileComps[comp].nQuantSteps =
+ img.tiles[0].tileComps[comp].nQuantSteps;
+ img.tiles[i].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[i].tileComps[comp].quantSteps,
+ img.tiles[0].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) {
+ img.tiles[i].tileComps[comp].quantSteps[j] =
+ img.tiles[0].tileComps[comp].quantSteps[j];
+ }
+ }
+ break;
+ case 0x5e: // RGN - region of interest
+#if 1 //~ ROI is unimplemented
+ fprintf(stderr, "RGN\n");
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PPM marker segment");
+ return gFalse;
+ }
+ }
+#else
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
+ (img.nComps <= 256 && !readUByte(&comp)) ||
+ comp >= img.nComps ||
+ !readUByte(&compInfo[comp].defROI.style) ||
+ !readUByte(&compInfo[comp].defROI.shift)) {
+ error(getPos(), "Error in JPX RGN marker segment");
+ return gFalse;
+ }
+#endif
+ break;
+ case 0x5f: // POC - progression order change
+#if 1 //~ progression order changes are unimplemented
+ fprintf(stderr, "POC\n");
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PPM marker segment");
+ return gFalse;
+ }
+ }
+#else
+ nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
+ progs = (JPXProgOrder *)gmalloc(nProgs * sizeof(JPXProgOrder));
+ for (i = 0; i < nProgs; ++i) {
+ if (!readUByte(&progs[i].startRes) ||
+ !(img.nComps > 256 && readUWord(&progs[i].startComp)) ||
+ !(img.nComps <= 256 && readUByte(&progs[i].startComp)) ||
+ !readUWord(&progs[i].endLayer) ||
+ !readUByte(&progs[i].endRes) ||
+ !(img.nComps > 256 && readUWord(&progs[i].endComp)) ||
+ !(img.nComps <= 256 && readUByte(&progs[i].endComp)) ||
+ !readUByte(&progs[i].progOrder)) {
+ error(getPos(), "Error in JPX POC marker segment");
+ return gFalse;
+ }
+ }
+#endif
+ break;
+ case 0x60: // PPM - packed packet headers, main header
+#if 1 //~ packed packet headers are unimplemented
+ fprintf(stderr, "PPM\n");
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PPM marker segment");
+ return gFalse;
+ }
+ }
+#endif
+ break;
+ case 0x55: // TLM - tile-part lengths
+ // skipped
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX TLM marker segment");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x57: // PLM - packet length, main header
+ // skipped
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PLM marker segment");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x63: // CRG - component registration
+ // skipped
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX CRG marker segment");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x64: // COM - comment
+ // skipped
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX COM marker segment");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x90: // SOT - start of tile
+ haveSOT = gTrue;
+ break;
+ default:
+ error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ break;
+ }
+ }
+ break;
+ }
+ } while (!haveSOT);
+
+ if (!haveSIZ) {
+ error(getPos(), "Missing SIZ marker segment in JPX stream");
+ return gFalse;
+ }
+ if (!haveCOD) {
+ error(getPos(), "Missing COD marker segment in JPX stream");
+ return gFalse;
+ }
+ if (!haveQCD) {
+ error(getPos(), "Missing QCD marker segment in JPX stream");
+ return gFalse;
+ }
+
+ //----- read the tile-parts
+ while (1) {
+ if (!readTilePart()) {
+ return gFalse;
+ }
+ if (!readMarkerHdr(&segType, &segLen)) {
+ error(getPos(), "Error in JPX codestream");
+ return gFalse;
+ }
+ if (segType != 0x90) { // SOT - start of tile
+ break;
+ }
+ }
+
+ if (segType != 0xd9) { // EOC - end of codestream
+ error(getPos(), "Missing EOC marker in JPX codestream");
+ return gFalse;
+ }
+
+ //----- finish decoding the image
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
+ tile = &img.tiles[i];
+ for (comp = 0; comp < img.nComps; ++comp) {
+ tileComp = &tile->tileComps[comp];
+ inverseTransform(tileComp);
+ }
+ if (!inverseMultiCompAndDC(tile)) {
+ return gFalse;
+ }
+ }
+
+ //~ can free memory below tileComps here, and also tileComp.buf
+
+ return gTrue;
+}
+
+GBool JPXStream::readTilePart() {
+ JPXTile *tile;
+ JPXTileComp *tileComp;
+ JPXResLevel *resLevel;
+ JPXPrecinct *precinct;
+ JPXSubband *subband;
+ JPXCodeBlock *cb;
+ GBool haveSOD;
+ Guint tileIdx, tilePartLen, tilePartIdx, nTileParts;
+ GBool tilePartToEOC;
+ Guint precinctSize, style;
+ Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
+ Guint i, j, k, cbX, cbY, r, pre, sb, cbi;
+ int segType, level;
+
+ // process the SOT marker segment
+ if (!readUWord(&tileIdx) ||
+ !readULong(&tilePartLen) ||
+ !readUByte(&tilePartIdx) ||
+ !readUByte(&nTileParts)) {
+ error(getPos(), "Error in JPX SOT marker segment");
+ return gFalse;
+ }
+
+ if (tileIdx >= img.nXTiles * img.nYTiles) {
+ error(getPos(), "Weird tile index in JPX stream");
+ return gFalse;
+ }
+
+ tilePartToEOC = tilePartLen == 0;
+ tilePartLen -= 12; // subtract size of SOT segment
+
+ haveSOD = gFalse;
+ do {
+ if (!readMarkerHdr(&segType, &segLen)) {
+ error(getPos(), "Error in JPX tile-part codestream");
+ return gFalse;
+ }
+ tilePartLen -= 2 + segLen;
+ switch (segType) {
+ case 0x52: // COD - coding style default
+ if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
+ !readUByte(&img.tiles[tileIdx].progOrder) ||
+ !readUWord(&img.tiles[tileIdx].nLayers) ||
+ !readUByte(&img.tiles[tileIdx].multiComp) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
+ error(getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
+ img.tiles[tileIdx].tileComps[0].codeBlockH += 2;
+ for (comp = 0; comp < img.nComps; ++comp) {
+ if (comp != 0) {
+ img.tiles[tileIdx].tileComps[comp].style =
+ img.tiles[tileIdx].tileComps[0].style;
+ img.tiles[tileIdx].tileComps[comp].nDecompLevels =
+ img.tiles[tileIdx].tileComps[0].nDecompLevels;
+ img.tiles[tileIdx].tileComps[comp].codeBlockW =
+ img.tiles[tileIdx].tileComps[0].codeBlockW;
+ img.tiles[tileIdx].tileComps[comp].codeBlockH =
+ img.tiles[tileIdx].tileComps[0].codeBlockH;
+ img.tiles[tileIdx].tileComps[comp].codeBlockStyle =
+ img.tiles[tileIdx].tileComps[0].codeBlockStyle;
+ img.tiles[tileIdx].tileComps[comp].transform =
+ img.tiles[tileIdx].tileComps[0].transform;
+ }
+ img.tiles[tileIdx].tileComps[comp].resLevels =
+ (JPXResLevel *)grealloc(
+ img.tiles[tileIdx].tileComps[comp].resLevels,
+ (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1) *
+ sizeof(JPXResLevel));
+ for (r = 0;
+ r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
+ ++r) {
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
+ }
+ }
+ for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
+ if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
+ if (!readUByte(&precinctSize)) {
+ error(getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
+ precinctSize & 0x0f;
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight =
+ (precinctSize >> 4) & 0x0f;
+ } else {
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15;
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15;
+ }
+ }
+ for (comp = 1; comp < img.nComps; ++comp) {
+ for (r = 0;
+ r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
+ ++r) {
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth;
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight;
+ }
+ }
+ break;
+ case 0x53: // COC - coding style component
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
+ (img.nComps <= 256 && !readUByte(&comp)) ||
+ comp >= img.nComps ||
+ !readUByte(&style) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) ||
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
+ error(getPos(), "Error in JPX COC marker segment");
+ return gFalse;
+ }
+ img.tiles[tileIdx].tileComps[comp].style =
+ (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1);
+ img.tiles[tileIdx].tileComps[comp].codeBlockW += 2;
+ img.tiles[tileIdx].tileComps[comp].codeBlockH += 2;
+ img.tiles[tileIdx].tileComps[comp].resLevels =
+ (JPXResLevel *)grealloc(
+ img.tiles[tileIdx].tileComps[comp].resLevels,
+ (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1) *
+ sizeof(JPXResLevel));
+ for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
+ }
+ for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
+ if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
+ if (!readUByte(&precinctSize)) {
+ error(getPos(), "Error in JPX COD marker segment");
+ return gFalse;
+ }
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
+ precinctSize & 0x0f;
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
+ (precinctSize >> 4) & 0x0f;
+ } else {
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15;
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15;
+ }
+ }
+ break;
+ case 0x5c: // QCD - quantization default
+ if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
+ img.tiles[tileIdx].tileComps[0].nQuantSteps =
+ segLen - 3;
+ img.tiles[tileIdx].tileComps[0].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[0].quantSteps,
+ img.tiles[tileIdx].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
+ if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ }
+ } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) {
+ img.tiles[tileIdx].tileComps[0].nQuantSteps = 1;
+ img.tiles[tileIdx].tileComps[0].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[0].quantSteps,
+ img.tiles[tileIdx].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
+ img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
+ img.tiles[tileIdx].tileComps[0].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[0].quantSteps,
+ img.tiles[tileIdx].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
+ if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ }
+ } else {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ for (comp = 1; comp < img.nComps; ++comp) {
+ img.tiles[tileIdx].tileComps[comp].quantStyle =
+ img.tiles[tileIdx].tileComps[0].quantStyle;
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps =
+ img.tiles[tileIdx].tileComps[0].nQuantSteps;
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
+ img.tiles[tileIdx].tileComps[0].nQuantSteps *
+ sizeof(Guint));
+ for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) {
+ img.tiles[tileIdx].tileComps[comp].quantSteps[j] =
+ img.tiles[tileIdx].tileComps[0].quantSteps[j];
+ }
+ }
+ break;
+ case 0x5d: // QCC - quantization component
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
+ (img.nComps <= 256 && !readUByte(&comp)) ||
+ comp >= img.nComps ||
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps =
+ segLen - (img.nComps > 256 ? 5 : 4);
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
+ if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ }
+ } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
+ == 0x01) {
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1;
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
+ == 0x02) {
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps =
+ (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
+ (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps *
+ sizeof(Guint));
+ for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
+ if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
+ error(getPos(), "Error in JPX QCD marker segment");
+ return gFalse;
+ }
+ }
+ } else {
+ error(getPos(), "Error in JPX QCC marker segment");
+ return gFalse;
+ }
+ break;
+ case 0x5e: // RGN - region of interest
+#if 1 //~ ROI is unimplemented
+ fprintf(stderr, "RGN\n");
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PPM marker segment");
+ return gFalse;
+ }
+ }
+#else
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
+ (img.nComps <= 256 && !readUByte(&comp)) ||
+ comp >= img.nComps ||
+ !readUByte(&compInfo[comp].roi.style) ||
+ !readUByte(&compInfo[comp].roi.shift)) {
+ error(getPos(), "Error in JPX RGN marker segment");
+ return gFalse;
+ }
+#endif
+ break;
+ case 0x5f: // POC - progression order change
+#if 1 //~ progression order changes are unimplemented
+ fprintf(stderr, "POC\n");
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PPM marker segment");
+ return gFalse;
+ }
+ }
+#else
+ nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
+ tileProgs = (JPXProgOrder *)gmalloc(nTileProgs * sizeof(JPXProgOrder));
+ for (i = 0; i < nTileProgs; ++i) {
+ if (!readUByte(&tileProgs[i].startRes) ||
+ !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) ||
+ !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) ||
+ !readUWord(&tileProgs[i].endLayer) ||
+ !readUByte(&tileProgs[i].endRes) ||
+ !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) ||
+ !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) ||
+ !readUByte(&tileProgs[i].progOrder)) {
+ error(getPos(), "Error in JPX POC marker segment");
+ return gFalse;
+ }
+ }
+#endif
+ break;
+ case 0x61: // PPT - packed packet headers, tile-part hdr
+#if 1 //~ packed packet headers are unimplemented
+ fprintf(stderr, "PPT\n");
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PPT marker segment");
+ return gFalse;
+ }
+ }
+#endif
+ case 0x58: // PLT - packet length, tile-part header
+ // skipped
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX PLT marker segment");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x64: // COM - comment
+ // skipped
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Error in JPX COM marker segment");
+ return gFalse;
+ }
+ }
+ break;
+ case 0x93: // SOD - start of data
+ haveSOD = gTrue;
+ break;
+ default:
+ error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
+ segType);
+ for (i = 0; i < segLen - 2; ++i) {
+ if (str->getChar() == EOF) {
+ break;
+ }
+ }
+ break;
+ }
+ } while (!haveSOD);
+
+ //----- initialize the tile, precincts, and code-blocks
+ if (tilePartIdx == 0) {
+ tile = &img.tiles[tileIdx];
+ i = tileIdx / img.nXTiles;
+ j = tileIdx % img.nXTiles;
+ if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
+ tile->x0 = img.xOffset;
+ }
+ if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) {
+ tile->y0 = img.yOffset;
+ }
+ if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) {
+ tile->x1 = img.xSize;
+ }
+ if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) {
+ tile->y1 = img.ySize;
+ }
+ tile->comp = 0;
+ tile->res = 0;
+ tile->precinct = 0;
+ tile->layer = 0;
+ tile->maxNDecompLevels = 0;
+ for (comp = 0; comp < img.nComps; ++comp) {
+ tileComp = &tile->tileComps[comp];
+ if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
+ tile->maxNDecompLevels = tileComp->nDecompLevels;
+ }
+ tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
+ tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep);
+ tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
+ tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep);
+ tileComp->cbW = 1 << tileComp->codeBlockW;
+ tileComp->cbH = 1 << tileComp->codeBlockH;
+ tileComp->data = (int *)gmalloc((tileComp->x1 - tileComp->x0) *
+ (tileComp->y1 - tileComp->y0) *
+ sizeof(int));
+ if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
+ n = tileComp->x1 - tileComp->x0;
+ } else {
+ n = tileComp->y1 - tileComp->y0;
+ }
+ tileComp->buf = (int *)gmalloc((n + 8) * sizeof(int));
+ for (r = 0; r <= tileComp->nDecompLevels; ++r) {
+ resLevel = &tileComp->resLevels[r];
+ k = r == 0 ? tileComp->nDecompLevels
+ : tileComp->nDecompLevels - r + 1;
+ resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k);
+ resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
+ resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
+ resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
+ if (r == 0) {
+ resLevel->bx0[0] = resLevel->x0;
+ resLevel->by0[0] = resLevel->y0;
+ resLevel->bx1[0] = resLevel->x1;
+ resLevel->by1[0] = resLevel->y1;
+ } else {
+ resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
+ resLevel->by0[0] = resLevel->y0;
+ resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
+ resLevel->by1[0] = resLevel->y1;
+ resLevel->bx0[1] = resLevel->x0;
+ resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
+ resLevel->bx1[1] = resLevel->x1;
+ resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
+ resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
+ resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
+ resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
+ resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
+ }
+ resLevel->precincts = (JPXPrecinct *)gmalloc(1 * sizeof(JPXPrecinct));
+ for (pre = 0; pre < 1; ++pre) {
+ precinct = &resLevel->precincts[pre];
+ precinct->x0 = resLevel->x0;
+ precinct->y0 = resLevel->y0;
+ precinct->x1 = resLevel->x1;
+ precinct->y1 = resLevel->y1;
+ nSBs = r == 0 ? 1 : 3;
+ precinct->subbands =
+ (JPXSubband *)gmalloc(nSBs * sizeof(JPXSubband));
+ for (sb = 0; sb < nSBs; ++sb) {
+ subband = &precinct->subbands[sb];
+ subband->x0 = resLevel->bx0[sb];
+ subband->y0 = resLevel->by0[sb];
+ subband->x1 = resLevel->bx1[sb];
+ subband->y1 = resLevel->by1[sb];
+ subband->nXCBs = jpxCeilDivPow2(subband->x1,
+ tileComp->codeBlockW)
+ - jpxFloorDivPow2(subband->x0,
+ tileComp->codeBlockW);
+ subband->nYCBs = jpxCeilDivPow2(subband->y1,
+ tileComp->codeBlockH)
+ - jpxFloorDivPow2(subband->y0,
+ tileComp->codeBlockH);
+ n = subband->nXCBs > subband->nYCBs ? subband->nXCBs
+ : subband->nYCBs;
+ for (subband->maxTTLevel = 0, --n;
+ n;
+ ++subband->maxTTLevel, n >>= 1) ;
+ n = 0;
+ for (level = subband->maxTTLevel; level >= 0; --level) {
+ nx = jpxCeilDivPow2(subband->nXCBs, level);
+ ny = jpxCeilDivPow2(subband->nYCBs, level);
+ n += nx * ny;
+ }
+ subband->inclusion =
+ (JPXTagTreeNode *)gmalloc(n * sizeof(JPXTagTreeNode));
+ subband->zeroBitPlane =
+ (JPXTagTreeNode *)gmalloc(n * sizeof(JPXTagTreeNode));
+ for (k = 0; k < n; ++k) {
+ subband->inclusion[k].finished = gFalse;
+ subband->inclusion[k].val = 0;
+ subband->zeroBitPlane[k].finished = gFalse;
+ subband->zeroBitPlane[k].val = 0;
+ }
+ subband->cbs = (JPXCodeBlock *)gmalloc(subband->nXCBs *
+ subband->nYCBs *
+ sizeof(JPXCodeBlock));
+ sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
+ sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
+ cb = subband->cbs;
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
+ cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW;
+ cb->x1 = cb->x0 + tileComp->cbW;
+ if (subband->x0 > cb->x0) {
+ cb->x0 = subband->x0;
+ }
+ if (subband->x1 < cb->x1) {
+ cb->x1 = subband->x1;
+ }
+ cb->y0 = (sby0 + cbY) << tileComp->codeBlockH;
+ cb->y1 = cb->y0 + tileComp->cbH;
+ if (subband->y0 > cb->y0) {
+ cb->y0 = subband->y0;
+ }
+ if (subband->y1 < cb->y1) {
+ cb->y1 = subband->y1;
+ }
+ cb->seen = gFalse;
+ cb->lBlock = 3;
+ cb->nextPass = jpxPassCleanup;
+ cb->nZeroBitPlanes = 0;
+ cb->coeffs =
+ (JPXCoeff *)gmalloc((1 << (tileComp->codeBlockW
+ + tileComp->codeBlockH))
+ * sizeof(JPXCoeff));
+ for (cbi = 0;
+ cbi < (Guint)(1 << (tileComp->codeBlockW
+ + tileComp->codeBlockH));
+ ++cbi) {
+ cb->coeffs[cbi].flags = 0;
+ cb->coeffs[cbi].len = 0;
+ cb->coeffs[cbi].mag = 0;
+ }
+ cb->stats = new JArithmeticDecoderStats(jpxNContexts);
+ cb->stats->setEntry(jpxContextSigProp, 4, 0);
+ cb->stats->setEntry(jpxContextRunLength, 3, 0);
+ cb->stats->setEntry(jpxContextUniform, 46, 0);
+ ++cb;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return readTilePartData(tileIdx, tilePartLen, tilePartToEOC);
+}
+
+GBool JPXStream::readTilePartData(Guint tileIdx,
+ Guint tilePartLen, GBool tilePartToEOC) {
+ JPXTile *tile;
+ JPXTileComp *tileComp;
+ JPXResLevel *resLevel;
+ JPXPrecinct *precinct;
+ JPXSubband *subband;
+ JPXCodeBlock *cb;
+ Guint ttVal;
+ Guint bits, cbX, cbY, nx, ny, i, j, n, sb;
+ int level;
+
+ tile = &img.tiles[tileIdx];
+
+ // read all packets from this tile-part
+ while (1) {
+ if (tilePartToEOC) {
+ //~ peek for an EOC marker
+ } else if (tilePartLen == 0) {
+ break;
+ }
+
+ tileComp = &tile->tileComps[tile->comp];
+ resLevel = &tileComp->resLevels[tile->res];
+ precinct = &resLevel->precincts[tile->precinct];
+
+ //----- packet header
+
+ // zero-length flag
+ if (!readBits(1, &bits)) {
+ goto err;
+ }
+ if (!bits) {
+ // packet is empty -- clear all code-block inclusion flags
+ for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
+ subband = &precinct->subbands[sb];
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
+ cb = &subband->cbs[cbY * subband->nXCBs + cbX];
+ cb->included = gFalse;
+ }
+ }
+ }
+ } else {
+
+ for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
+ subband = &precinct->subbands[sb];
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
+ cb = &subband->cbs[cbY * subband->nXCBs + cbX];
+
+ // skip code-blocks with no coefficients
+ if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
+ cb->included = gFalse;
+ continue;
+ }
+
+ // code-block inclusion
+ if (cb->seen) {
+ if (!readBits(1, &cb->included)) {
+ goto err;
+ }
+ } else {
+ ttVal = 0;
+ i = 0;
+ for (level = subband->maxTTLevel; level >= 0; --level) {
+ nx = jpxCeilDivPow2(subband->nXCBs, level);
+ ny = jpxCeilDivPow2(subband->nYCBs, level);
+ j = i + (cbY >> level) * nx + (cbX >> level);
+ if (!subband->inclusion[j].finished &&
+ !subband->inclusion[j].val) {
+ subband->inclusion[j].val = ttVal;
+ } else {
+ ttVal = subband->inclusion[j].val;
+ }
+ while (!subband->inclusion[j].finished &&
+ ttVal <= tile->layer) {
+ if (!readBits(1, &bits)) {
+ goto err;
+ }
+ if (bits == 1) {
+ subband->inclusion[j].finished = gTrue;
+ } else {
+ ++ttVal;
+ }
+ }
+ subband->inclusion[j].val = ttVal;
+ if (ttVal > tile->layer) {
+ break;
+ }
+ i += nx * ny;
+ }
+ cb->included = level < 0;
+ }
+
+ if (cb->included) {
+
+ // zero bit-plane count
+ if (!cb->seen) {
+ ttVal = 0;
+ i = 0;
+ for (level = subband->maxTTLevel; level >= 0; --level) {
+ nx = jpxCeilDivPow2(subband->nXCBs, level);
+ ny = jpxCeilDivPow2(subband->nYCBs, level);
+ j = i + (cbY >> level) * nx + (cbX >> level);
+ if (!subband->zeroBitPlane[j].finished &&
+ !subband->zeroBitPlane[j].val) {
+ subband->zeroBitPlane[j].val = ttVal;
+ } else {
+ ttVal = subband->zeroBitPlane[j].val;
+ }
+ while (!subband->zeroBitPlane[j].finished) {
+ if (!readBits(1, &bits)) {
+ goto err;
+ }
+ if (bits == 1) {
+ subband->zeroBitPlane[j].finished = gTrue;
+ } else {
+ ++ttVal;
+ }
+ }
+ subband->zeroBitPlane[j].val = ttVal;
+ i += nx * ny;
+ }
+ cb->nZeroBitPlanes = ttVal;
+ }
+
+ // number of coding passes
+ if (!readBits(1, &bits)) {
+ goto err;
+ }
+ if (bits == 0) {
+ cb->nCodingPasses = 1;
+ } else {
+ if (!readBits(1, &bits)) {
+ goto err;
+ }
+ if (bits == 0) {
+ cb->nCodingPasses = 2;
+ } else {
+ if (!readBits(2, &bits)) {
+ goto err;
+ }
+ if (bits < 3) {
+ cb->nCodingPasses = 3 + bits;
+ } else {
+ if (!readBits(5, &bits)) {
+ goto err;
+ }
+ if (bits < 31) {
+ cb->nCodingPasses = 6 + bits;
+ } else {
+ if (!readBits(7, &bits)) {
+ goto err;
+ }
+ cb->nCodingPasses = 37 + bits;
+ }
+ }
+ }
+ }
+
+ // update Lblock
+ while (1) {
+ if (!readBits(1, &bits)) {
+ goto err;
+ }
+ if (!bits) {
+ break;
+ }
+ ++cb->lBlock;
+ }
+
+ // length of compressed data
+ //~ deal with multiple codeword segments
+ for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
+ i;
+ ++n, i >>= 1) ;
+ if (!readBits(n, &cb->dataLen)) {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ }
+ tilePartLen -= byteCount;
+ clearBitBuf();
+
+ //----- packet data
+
+ for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
+ subband = &precinct->subbands[sb];
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
+ cb = &subband->cbs[cbY * subband->nXCBs + cbX];
+ if (cb->included) {
+ if (!readCodeBlockData(tileComp, resLevel, precinct, subband,
+ tile->res, sb, cb)) {
+ return gFalse;
+ }
+ tilePartLen -= cb->dataLen;
+ cb->seen = gTrue;
+ }
+ }
+ }
+ }
+
+ //----- next packet
+
+ switch (tile->progOrder) {
+ case 0: // layer, resolution level, component, precinct
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ }
+ }
+ }
+ break;
+ case 1: // resolution level, layer, component, precinct
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ }
+ }
+ }
+ break;
+ case 2: // resolution level, precinct, component, layer
+ //~ this isn't correct -- see B.12.1.3
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ }
+ }
+ }
+ break;
+ case 3: // precinct, component, resolution level, layer
+ //~ this isn't correct -- see B.12.1.4
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ }
+ }
+ }
+ break;
+ case 4: // component, precinct, resolution level, layer
+ //~ this isn't correct -- see B.12.1.5
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ return gTrue;
+
+ err:
+ error(getPos(), "Error in JPX stream");
+ return gFalse;
+}
+
+GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
+ JPXResLevel *resLevel,
+ JPXPrecinct *precinct,
+ JPXSubband *subband,
+ Guint res, Guint sb,
+ JPXCodeBlock *cb) {
+ JPXCoeff *coeff0, *coeff1, *coeff;
+ JArithmeticDecoder *arithDecoder;
+ Guint horiz, vert, diag, all, cx, xorBit;
+ int horizSign, vertSign;
+ Guint i, x, y0, y1, y2;
+
+ arithDecoder = new JArithmeticDecoder();
+ arithDecoder->setStream(str, cb->dataLen);
+ arithDecoder->start();
+
+ for (i = 0; i < cb->nCodingPasses; ++i) {
+ switch (cb->nextPass) {
+
+ //----- significance propagation pass
+ case jpxPassSigProp:
+ for (y0 = cb->y0, coeff0 = cb->coeffs;
+ y0 < cb->y1;
+ y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
+ for (x = cb->x0, coeff1 = coeff0;
+ x < cb->x1;
+ ++x, ++coeff1) {
+ for (y1 = 0, coeff = coeff1;
+ y1 < 4 && y0+y1 < cb->y1;
+ ++y1, coeff += tileComp->cbW) {
+ if (!(coeff->flags & jpxCoeffSignificant)) {
+ horiz = vert = diag = 0;
+ horizSign = vertSign = 2;
+ if (x > cb->x0) {
+ if (coeff[-1].flags & jpxCoeffSignificant) {
+ ++horiz;
+ horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
+ }
+ if (y0+y1 > cb->y0) {
+ diag += (coeff[-tileComp->cbW - 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ diag += (coeff[tileComp->cbW - 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ }
+ if (x < cb->x1 - 1) {
+ if (coeff[1].flags & jpxCoeffSignificant) {
+ ++horiz;
+ horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
+ }
+ if (y0+y1 > cb->y0) {
+ diag += (coeff[-tileComp->cbW + 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ diag += (coeff[tileComp->cbW + 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ }
+ if (y0+y1 > cb->y0) {
+ if (coeff[-tileComp->cbW].flags & jpxCoeffSignificant) {
+ ++vert;
+ vertSign += (coeff[-tileComp->cbW].flags & jpxCoeffSign)
+ ? -1 : 1;
+ }
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
+ ++vert;
+ vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
+ ? -1 : 1;
+ }
+ }
+ cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
+ if (cx != 0) {
+ if (arithDecoder->decodeBit(cx, cb->stats)) {
+ coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
+ coeff->mag = (coeff->mag << 1) | 1;
+ cx = signContext[horizSign][vertSign][0];
+ xorBit = signContext[horizSign][vertSign][1];
+ if (arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
+ coeff->flags |= jpxCoeffSign;
+ }
+ }
+ ++coeff->len;
+ coeff->flags |= jpxCoeffTouched;
+ }
+ }
+ }
+ }
+ }
+ ++cb->nextPass;
+ break;
+
+ //----- magnitude refinement pass
+ case jpxPassMagRef:
+ for (y0 = cb->y0, coeff0 = cb->coeffs;
+ y0 < cb->y1;
+ y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
+ for (x = cb->x0, coeff1 = coeff0;
+ x < cb->x1;
+ ++x, ++coeff1) {
+ for (y1 = 0, coeff = coeff1;
+ y1 < 4 && y0+y1 < cb->y1;
+ ++y1, coeff += tileComp->cbW) {
+ if ((coeff->flags & jpxCoeffSignificant) &&
+ !(coeff->flags & jpxCoeffTouched)) {
+ if (coeff->flags & jpxCoeffFirstMagRef) {
+ all = 0;
+ if (x > cb->x0) {
+ all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 > cb->y0) {
+ all += (coeff[-tileComp->cbW - 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ all += (coeff[tileComp->cbW - 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ }
+ if (x < cb->x1 - 1) {
+ all += (coeff[1].flags >> jpxCoeffSignificantB) & 1;
+ if (y0+y1 > cb->y0) {
+ all += (coeff[-tileComp->cbW + 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ all += (coeff[tileComp->cbW + 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ }
+ if (y0+y1 > cb->y0) {
+ all += (coeff[-tileComp->cbW].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ all += (coeff[tileComp->cbW].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ cx = all ? 15 : 14;
+ } else {
+ cx = 16;
+ }
+ coeff->mag = (coeff->mag << 1) |
+ arithDecoder->decodeBit(cx, cb->stats);
+ ++coeff->len;
+ coeff->flags |= jpxCoeffTouched;
+ coeff->flags &= ~jpxCoeffFirstMagRef;
+ }
+ }
+ }
+ }
+ ++cb->nextPass;
+ break;
+
+ //----- cleanup pass
+ case jpxPassCleanup:
+ for (y0 = cb->y0, coeff0 = cb->coeffs;
+ y0 < cb->y1;
+ y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
+ for (x = cb->x0, coeff1 = coeff0;
+ x < cb->x1;
+ ++x, ++coeff1) {
+ y1 = 0;
+ if (y0 + 3 < cb->y1 &&
+ !(coeff1->flags & jpxCoeffTouched) &&
+ !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) &&
+ !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) &&
+ !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) &&
+ (x == cb->x0 || y0 == cb->y0 ||
+ !(coeff1[-tileComp->cbW - 1].flags
+ & jpxCoeffSignificant)) &&
+ (y0 == cb->y0 ||
+ !(coeff1[-tileComp->cbW].flags & jpxCoeffSignificant)) &&
+ (x == cb->x1 - 1 || y0 == cb->y0 ||
+ !(coeff1[-tileComp->cbW + 1].flags & jpxCoeffSignificant)) &&
+ (x == cb->x0 ||
+ (!(coeff1[-1].flags & jpxCoeffSignificant) &&
+ !(coeff1[tileComp->cbW - 1].flags
+ & jpxCoeffSignificant) &&
+ !(coeff1[2 * tileComp->cbW - 1].flags
+ & jpxCoeffSignificant) &&
+ !(coeff1[3 * tileComp->cbW - 1].flags
+ & jpxCoeffSignificant))) &&
+ (x == cb->x1 - 1 ||
+ (!(coeff1[1].flags & jpxCoeffSignificant) &&
+ !(coeff1[tileComp->cbW + 1].flags
+ & jpxCoeffSignificant) &&
+ !(coeff1[2 * tileComp->cbW + 1].flags
+ & jpxCoeffSignificant) &&
+ !(coeff1[3 * tileComp->cbW + 1].flags
+ & jpxCoeffSignificant))) &&
+ (x == cb->x0 || y0+4 == cb->y1 ||
+ !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) &&
+ (y0+4 == cb->y1 ||
+ !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) &&
+ (x == cb->x1 - 1 || y0+4 == cb->y1 ||
+ !(coeff1[4 * tileComp->cbW + 1].flags
+ & jpxCoeffSignificant))) {
+ if (arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
+ y1 = arithDecoder->decodeBit(jpxContextUniform, cb->stats);
+ y1 = (y1 << 1) |
+ arithDecoder->decodeBit(jpxContextUniform, cb->stats);
+ for (y2 = 0, coeff = coeff1;
+ y2 < y1;
+ ++y2, coeff += tileComp->cbW) {
+ ++coeff->len;
+ }
+ coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
+ coeff->mag = (coeff->mag << 1) | 1;
+ ++coeff->len;
+ cx = signContext[2][2][0];
+ xorBit = signContext[2][2][1];
+ if (arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
+ coeff->flags |= jpxCoeffSign;
+ }
+ ++y1;
+ } else {
+ for (y1 = 0, coeff = coeff1;
+ y1 < 4;
+ ++y1, coeff += tileComp->cbW) {
+ ++coeff->len;
+ }
+ y1 = 4;
+ }
+ }
+ for (coeff = &coeff1[y1 << tileComp->codeBlockW];
+ y1 < 4 && y0 + y1 < cb->y1;
+ ++y1, coeff += tileComp->cbW) {
+ if (!(coeff->flags & jpxCoeffTouched)) {
+ horiz = vert = diag = 0;
+ horizSign = vertSign = 2;
+ if (x > cb->x0) {
+ if (coeff[-1].flags & jpxCoeffSignificant) {
+ ++horiz;
+ horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
+ }
+ if (y0+y1 > cb->y0) {
+ diag += (coeff[-tileComp->cbW - 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ diag += (coeff[tileComp->cbW - 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ }
+ if (x < cb->x1 - 1) {
+ if (coeff[1].flags & jpxCoeffSignificant) {
+ ++horiz;
+ horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
+ }
+ if (y0+y1 > cb->y0) {
+ diag += (coeff[-tileComp->cbW + 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ diag += (coeff[tileComp->cbW + 1].flags
+ >> jpxCoeffSignificantB) & 1;
+ }
+ }
+ if (y0+y1 > cb->y0) {
+ if (coeff[-tileComp->cbW].flags & jpxCoeffSignificant) {
+ ++vert;
+ vertSign += (coeff[-tileComp->cbW].flags & jpxCoeffSign)
+ ? -1 : 1;
+ }
+ }
+ if (y0+y1 < cb->y1 - 1) {
+ if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
+ ++vert;
+ vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
+ ? -1 : 1;
+ }
+ }
+ cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
+ if (arithDecoder->decodeBit(cx, cb->stats)) {
+ coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
+ coeff->mag = (coeff->mag << 1) | 1;
+ cx = signContext[horizSign][vertSign][0];
+ xorBit = signContext[horizSign][vertSign][1];
+ if (arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
+ coeff->flags |= jpxCoeffSign;
+ }
+ }
+ ++coeff->len;
+ } else {
+ coeff->flags &= ~jpxCoeffTouched;
+ }
+ }
+ }
+ }
+ cb->nextPass = jpxPassSigProp;
+ break;
+ }
+ }
+
+ delete arithDecoder;
+ return gTrue;
+}
+
+// Inverse quantization, and wavelet transform (IDWT). This also does
+// the initial shift to convert to fixed point format.
+void JPXStream::inverseTransform(JPXTileComp *tileComp) {
+ JPXResLevel *resLevel;
+ JPXPrecinct *precinct;
+ JPXSubband *subband;
+ JPXCodeBlock *cb;
+ JPXCoeff *coeff0, *coeff;
+ Guint qStyle, guard, eps, shift, shift2;
+ double mu;
+ int val;
+ int *dataPtr;
+ Guint nx0, ny0, nx1, ny1;
+ Guint r, cbX, cbY, x, y;
+
+ //----- (NL)LL subband (resolution level 0)
+
+ resLevel = &tileComp->resLevels[0];
+ precinct = &resLevel->precincts[0];
+ subband = &precinct->subbands[0];
+
+ // i-quant parameters
+ qStyle = tileComp->quantStyle & 0x1f;
+ guard = (tileComp->quantStyle >> 5) & 7;
+ if (qStyle == 0) {
+ eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
+ shift = guard + eps - 1;
+ mu = 0; // make gcc happy
+ } else {
+ shift = guard - 1 + tileComp->prec;
+ mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
+ }
+ if (tileComp->transform == 0) {
+ shift += fracBits;
+ }
+
+ // copy (NL)LL into the upper-left corner of the data array, doing
+ // the fixed point adjustment and dequantization along the way
+ cb = subband->cbs;
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
+ for (y = cb->y0, coeff0 = cb->coeffs;
+ y < cb->y1;
+ ++y, coeff0 += tileComp->cbW) {
+ dataPtr = &tileComp->data[(y - subband->y0)
+ * (tileComp->x1 - tileComp->x0)
+ + (cb->x0 - subband->x0)];
+ for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
+ val = (int)coeff->mag;
+ if (val != 0) {
+ shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
+ if (shift2 > 0) {
+ val = (val << shift2) + (1 << (shift2 - 1));
+ } else {
+ val >>= -shift2;
+ }
+ if (qStyle == 0) {
+ if (tileComp->transform == 0) {
+ val &= -1 << fracBits;
+ }
+ } else {
+ val = (int)((double)val * mu);
+ }
+ if (coeff->flags & jpxCoeffSign) {
+ val = -val;
+ }
+ }
+ *dataPtr++ = val;
+ }
+ }
+ ++cb;
+ }
+ }
+
+ //----- IDWT for each level
+
+ for (r = 1; r <= tileComp->nDecompLevels; ++r) {
+ resLevel = &tileComp->resLevels[r];
+
+ // (n)LL is already in the upper-left corner of the
+ // tile-component data array -- interleave with (n)HL/LH/HH
+ // and inverse transform to get (n-1)LL, which will be stored
+ // in the upper-left corner of the tile-component data array
+ if (r == tileComp->nDecompLevels) {
+ nx0 = tileComp->x0;
+ ny0 = tileComp->y0;
+ nx1 = tileComp->x1;
+ ny1 = tileComp->y1;
+ } else {
+ nx0 = tileComp->resLevels[r+1].x0;
+ ny0 = tileComp->resLevels[r+1].y0;
+ nx1 = tileComp->resLevels[r+1].x1;
+ ny1 = tileComp->resLevels[r+1].y1;
+ }
+ inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1);
+ }
+}
+
+// Do one level of the inverse transform:
+// - take (n)LL from the tile-component data array
+// - take (n)HL/LH/HH from <resLevel>
+// - leave the resulting (n-1)LL in the tile-component data array
+void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
+ Guint r, JPXResLevel *resLevel,
+ Guint nx0, Guint ny0,
+ Guint nx1, Guint ny1) {
+ JPXPrecinct *precinct;
+ JPXSubband *subband;
+ JPXCodeBlock *cb;
+ JPXCoeff *coeff0, *coeff;
+ Guint qStyle, guard, eps, shift, shift2, t;
+ double mu;
+ int val;
+ int *dataPtr;
+ Guint xo, yo;
+ Guint x, y, sb, cbX, cbY;
+ int xx, yy;
+
+ //----- interleave
+
+ // spread out LL
+ for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) {
+ for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) {
+ tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0)
+ + (2 * xx - nx0)] =
+ tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0)
+ + (xx - resLevel->x0)];
+ }
+ }
+
+ // i-quant parameters
+ qStyle = tileComp->quantStyle & 0x1f;
+ guard = (tileComp->quantStyle >> 5) & 7;
+
+ // interleave HL/LH/HH
+ precinct = &resLevel->precincts[0];
+ for (sb = 0; sb < 3; ++sb) {
+
+ // i-quant parameters
+ if (qStyle == 0) {
+ eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
+ shift = guard + eps - 1;
+ mu = 0; // make gcc happy
+ } else {
+ shift = guard + tileComp->prec;
+ if (sb == 2) {
+ ++shift;
+ }
+ t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
+ mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
+ }
+ if (tileComp->transform == 0) {
+ shift += fracBits;
+ }
+
+ // copy the subband coefficients into the data array, doing the
+ // fixed point adjustment and dequantization along the way
+ xo = (sb & 1) ? 0 : 1;
+ yo = (sb > 0) ? 1 : 0;
+ subband = &precinct->subbands[sb];
+ cb = subband->cbs;
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
+ for (y = cb->y0, coeff0 = cb->coeffs;
+ y < cb->y1;
+ ++y, coeff0 += tileComp->cbW) {
+ dataPtr = &tileComp->data[(2 * y + yo - ny0)
+ * (tileComp->x1 - tileComp->x0)
+ + (2 * cb->x0 + xo - nx0)];
+ for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
+ val = (int)coeff->mag;
+ if (val != 0) {
+ shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
+ if (shift2 > 0) {
+ val = (val << shift2) + (1 << (shift2 - 1));
+ } else {
+ val >>= -shift2;
+ }
+ if (qStyle == 0) {
+ if (tileComp->transform == 0) {
+ val &= -1 << fracBits;
+ }
+ } else {
+ val = (int)((double)val * mu);
+ }
+ if (coeff->flags & jpxCoeffSign) {
+ val = -val;
+ }
+ }
+ *dataPtr = val;
+ dataPtr += 2;
+ }
+ }
+ ++cb;
+ }
+ }
+ }
+
+ //----- horizontal (row) transforms
+ dataPtr = tileComp->data;
+ for (y = 0; y < ny1 - ny0; ++y) {
+ inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1);
+ dataPtr += tileComp->x1 - tileComp->x0;
+ }
+
+ //----- vertical (column) transforms
+ dataPtr = tileComp->data;
+ for (x = 0; x < nx1 - nx0; ++x) {
+ inverseTransform1D(tileComp, dataPtr,
+ tileComp->x1 - tileComp->x0, ny0, ny1);
+ ++dataPtr;
+ }
+}
+
+void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
+ int *data, Guint stride,
+ Guint i0, Guint i1) {
+ int *buf;
+ Guint offset, end, i;
+
+ //----- special case for length = 1
+ if (i1 - i0 == 1) {
+ if (i0 & 1) {
+ *data >>= 1;
+ }
+
+ } else {
+
+ // choose an offset: this makes even buf[] indexes correspond to
+ // odd values of i, and vice versa
+ offset = 3 + (i0 & 1);
+ end = offset + i1 - i0;
+
+ //----- gather
+ buf = tileComp->buf;
+ for (i = 0; i < i1 - i0; ++i) {
+ buf[offset + i] = data[i * stride];
+ }
+
+ //----- extend right
+ buf[end] = buf[end - 2];
+ if (i1 - i0 == 2) {
+ buf[end+1] = buf[offset + 1];
+ buf[end+2] = buf[offset];
+ buf[end+3] = buf[offset + 1];
+ } else {
+ buf[end+1] = buf[end - 3];
+ if (i1 - i0 == 3) {
+ buf[end+2] = buf[offset + 1];
+ buf[end+3] = buf[offset + 2];
+ } else {
+ buf[end+2] = buf[end - 4];
+ if (i1 - i0 == 4) {
+ buf[end+3] = buf[offset + 1];
+ } else {
+ buf[end+3] = buf[end - 5];
+ }
+ }
+ }
+
+ //----- extend left
+ buf[offset - 1] = buf[offset + 1];
+ buf[offset - 2] = buf[offset + 2];
+ buf[offset - 3] = buf[offset + 3];
+ if (offset == 4) {
+ buf[0] = buf[offset + 4];
+ }
+
+ //----- 9-7 irreversible filter
+
+ if (tileComp->transform == 0) {
+ // step 1 (even)
+ for (i = 1; i <= end + 2; i += 2) {
+ buf[i] = (int)(idwtKappa * buf[i]);
+ }
+ // step 2 (odd)
+ for (i = 0; i <= end + 3; i += 2) {
+ buf[i] = (int)(idwtIKappa * buf[i]);
+ }
+ // step 3 (even)
+ for (i = 1; i <= end + 2; i += 2) {
+ buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1]));
+ }
+ // step 4 (odd)
+ for (i = 2; i <= end + 1; i += 2) {
+ buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1]));
+ }
+ // step 5 (even)
+ for (i = 3; i <= end; i += 2) {
+ buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1]));
+ }
+ // step 6 (odd)
+ for (i = 4; i <= end - 1; i += 2) {
+ buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1]));
+ }
+
+ //----- 5-3 reversible filter
+
+ } else {
+ // step 1 (even)
+ for (i = 3; i <= end; i += 2) {
+ buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
+ }
+ // step 2 (odd)
+ for (i = 4; i < end; i += 2) {
+ buf[i] += (buf[i-1] + buf[i+1]) >> 1;
+ }
+ }
+
+ //----- scatter
+ for (i = 0; i < i1 - i0; ++i) {
+ data[i * stride] = buf[offset + i];
+ }
+ }
+}
+
+// Inverse multi-component transform and DC level shift. This also
+// converts fixed point samples back to integers.
+GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
+ JPXTileComp *tileComp;
+ int coeff, d0, d1, d2, minVal, maxVal, zeroVal;
+ int *dataPtr;
+ Guint j, comp, x, y;
+
+ //----- inverse multi-component transform
+
+ if (tile->multiComp == 1) {
+ if (img.nComps < 3 ||
+ tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
+ tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
+ tile->tileComps[1].hSep != tile->tileComps[2].hSep ||
+ tile->tileComps[1].vSep != tile->tileComps[2].vSep) {
+ return gFalse;
+ }
+
+ // inverse irreversible multiple component transform
+ if (tile->tileComps[0].transform == 0) {
+ j = 0;
+ for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
+ for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
+ d0 = tile->tileComps[0].data[j];
+ d1 = tile->tileComps[1].data[j];
+ d2 = tile->tileComps[2].data[j];
+ tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5);
+ tile->tileComps[1].data[j] =
+ (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5);
+ tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5);
+ ++j;
+ }
+ }
+
+ // inverse reversible multiple component transform
+ } else {
+ j = 0;
+ for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
+ for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
+ d0 = tile->tileComps[0].data[j];
+ d1 = tile->tileComps[1].data[j];
+ d2 = tile->tileComps[2].data[j];
+ tile->tileComps[0].data[j] = d0 - ((d2 + d1) >> 2);
+ tile->tileComps[1].data[j] = d2 - d1;
+ tile->tileComps[2].data[j] = d0 - d1;
+ ++j;
+ }
+ }
+ }
+ }
+
+ //----- DC level shift
+ for (comp = 0; comp < img.nComps; ++comp) {
+ tileComp = &tile->tileComps[comp];
+
+ // signed: clip
+ if (tileComp->sgned) {
+ minVal = -(1 << (tileComp->prec - 1));
+ maxVal = (1 << (tileComp->prec - 1)) - 1;
+ dataPtr = tileComp->data;
+ for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
+ for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
+ coeff = *dataPtr;
+ if (tileComp->transform == 0) {
+ coeff >>= fracBits;
+ }
+ if (coeff < minVal) {
+ coeff = minVal;
+ } else if (coeff > maxVal) {
+ coeff = maxVal;
+ }
+ *dataPtr++ = coeff;
+ }
+ }
+
+ // unsigned: inverse DC level shift and clip
+ } else {
+ maxVal = (1 << tileComp->prec) - 1;
+ zeroVal = 1 << (tileComp->prec - 1);
+ dataPtr = tileComp->data;
+ for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
+ for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
+ coeff = *dataPtr;
+ if (tileComp->transform == 0) {
+ coeff >>= fracBits;
+ }
+ coeff += zeroVal;
+ if (coeff < 0) {
+ coeff = 0;
+ } else if (coeff > maxVal) {
+ coeff = maxVal;
+ }
+ *dataPtr++ = coeff;
+ }
+ }
+ }
+ }
+
+ return gTrue;
+}
+
+GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) {
+ Guint len, lenH;
+
+ if (!readULong(&len) ||
+ !readULong(boxType)) {
+ return gFalse;
+ }
+ if (len == 1) {
+ if (!readULong(&lenH) || !readULong(&len)) {
+ return gFalse;
+ }
+ if (lenH) {
+ error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
+ return gFalse;
+ }
+ *boxLen = len;
+ *dataLen = len - 16;
+ } else if (len == 0) {
+ *boxLen = 0;
+ *dataLen = 0;
+ } else {
+ *boxLen = len;
+ *dataLen = len - 8;
+ }
+ return gTrue;
+}
+
+int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
+ int c;
+
+ do {
+ do {
+ if ((c = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ } while (c != 0xff);
+ do {
+ if ((c = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ } while (c == 0xff);
+ } while (c == 0x00);
+ *segType = c;
+ if ((c >= 0x30 && c <= 0x3f) ||
+ c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) {
+ *segLen = 0;
+ return gTrue;
+ }
+ return readUWord(segLen);
+}
+
+GBool JPXStream::readUByte(Guint *x) {
+ int c0;
+
+ if ((c0 = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)c0;
+ return gTrue;
+}
+
+GBool JPXStream::readByte(int *x) {
+ int c0;
+
+ if ((c0 = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = c0;
+ if (c0 & 0x80) {
+ *x |= -1 - 0xff;
+ }
+ return gTrue;
+}
+
+GBool JPXStream::readUWord(Guint *x) {
+ int c0, c1;
+
+ if ((c0 = str->getChar()) == EOF ||
+ (c1 = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)((c0 << 8) | c1);
+ return gTrue;
+}
+
+GBool JPXStream::readULong(Guint *x) {
+ int c0, c1, c2, c3;
+
+ if ((c0 = str->getChar()) == EOF ||
+ (c1 = str->getChar()) == EOF ||
+ (c2 = str->getChar()) == EOF ||
+ (c3 = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
+ return gTrue;
+}
+
+GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
+ int y, c, i;
+
+ y = 0;
+ for (i = 0; i < nBytes; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ y = (y << 8) + c;
+ }
+ if (signd) {
+ if (y & (1 << (8 * nBytes - 1))) {
+ y |= -1 << (8 * nBytes);
+ }
+ }
+ *x = y;
+ return gTrue;
+}
+
+GBool JPXStream::readBits(int nBits, Guint *x) {
+ int c;
+
+ while (bitBufLen < nBits) {
+ if ((c = str->getChar()) == EOF) {
+ return gFalse;
+ }
+ ++byteCount;
+ if (bitBufSkip) {
+ bitBuf = (bitBuf << 7) | (c & 0x7f);
+ bitBufLen += 7;
+ } else {
+ bitBuf = (bitBuf << 8) | (c & 0xff);
+ bitBufLen += 8;
+ }
+ bitBufSkip = c == 0xff;
+ }
+ *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1);
+ bitBufLen -= nBits;
+ return gTrue;
+}
+
+void JPXStream::clearBitBuf() {
+ bitBufLen = 0;
+ bitBufSkip = gFalse;
+ byteCount = 0;
+}
diff --git a/pdf2swf/xpdf/JPXStream.h b/pdf2swf/xpdf/JPXStream.h
new file mode 100644
index 00000000..eb84fe63
--- /dev/null
+++ b/pdf2swf/xpdf/JPXStream.h
@@ -0,0 +1,340 @@
+//========================================================================
+//
+// JPXStream.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef JPXSTREAM_H
+#define JPXSTREAM_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+#include "Stream.h"
+
+class JArithmeticDecoderStats;
+
+//------------------------------------------------------------------------
+
+enum JPXColorSpaceType {
+ jpxCSBiLevel = 0,
+ jpxCSYCbCr1 = 1,
+ jpxCSYCbCr2 = 3,
+ jpxCSYCBCr3 = 4,
+ jpxCSPhotoYCC = 9,
+ jpxCSCMY = 11,
+ jpxCSCMYK = 12,
+ jpxCSYCCK = 13,
+ jpxCSCIELab = 14,
+ jpxCSsRGB = 16,
+ jpxCSGrayscale = 17,
+ jpxCSBiLevel2 = 18,
+ jpxCSCIEJab = 19,
+ jpxCSCISesRGB = 20,
+ jpxCSROMMRGB = 21,
+ jpxCSsRGBYCbCr = 22,
+ jpxCSYPbPr1125 = 23,
+ jpxCSYPbPr1250 = 24
+};
+
+struct JPXColorSpec {
+ Guint meth; // method
+ int prec; // precedence
+ union {
+ struct {
+ JPXColorSpaceType type; // color space type
+ union {
+ struct {
+ Guint rl, ol, ra, oa, rb, ob, il;
+ } cieLab;
+ };
+ } enumerated;
+ };
+};
+
+//------------------------------------------------------------------------
+
+struct JPXPalette {
+ Guint nEntries; // number of entries in the palette
+ Guint nComps; // number of components in each entry
+ Guint *bpc; // bits per component, for each component
+ int *c; // color data:
+ // c[i*nComps+j] = entry i, component j
+};
+
+//------------------------------------------------------------------------
+
+struct JPXCompMap {
+ Guint nChannels; // number of channels
+ Guint *comp; // codestream components mapped to each channel
+ Guint *type; // 0 for direct use, 1 for palette mapping
+ Guint *pComp; // palette components to use
+};
+
+//------------------------------------------------------------------------
+
+struct JPXChannelDefn {
+ Guint nChannels; // number of channels
+ Guint *idx; // channel indexes
+ Guint *type; // channel types
+ Guint *assoc; // channel associations
+};
+
+//------------------------------------------------------------------------
+
+struct JPXTagTreeNode {
+ GBool finished; // true if this node is finished
+ Guint val; // current value
+};
+
+//------------------------------------------------------------------------
+
+struct JPXCoeff {
+ Gushort flags; // flag bits
+ Gushort len; // number of significant bits in mag
+ Guint mag; // magnitude value
+};
+
+// coefficient flags
+#define jpxCoeffSignificantB 0
+#define jpxCoeffTouchedB 1
+#define jpxCoeffFirstMagRefB 2
+#define jpxCoeffSignB 7
+#define jpxCoeffSignificant (1 << jpxCoeffSignificantB)
+#define jpxCoeffTouched (1 << jpxCoeffTouchedB)
+#define jpxCoeffFirstMagRef (1 << jpxCoeffFirstMagRefB)
+#define jpxCoeffSign (1 << jpxCoeffSignB)
+
+//------------------------------------------------------------------------
+
+struct JPXCodeBlock {
+ //----- size
+ Guint x0, y0, x1, y1; // bounds
+
+ //----- persistent state
+ GBool seen; // true if this code-block has already
+ // been seen
+ Guint lBlock; // base number of bits used for pkt data length
+ Guint nextPass; // next coding pass
+
+ //---- info from first packet
+ Guint nZeroBitPlanes; // number of zero bit planes
+
+ //----- info for the current packet
+ Guint included; // code-block inclusion in this packet:
+ // 0=not included, 1=included
+ Guint nCodingPasses; // number of coding passes in this pkt
+ Guint dataLen; // pkt data length
+
+ //----- coefficient data
+ JPXCoeff *coeffs; // the coefficients
+ JArithmeticDecoderStats // arithmetic decoder stats
+ *stats;
+};
+
+//------------------------------------------------------------------------
+
+struct JPXSubband {
+ //----- computed
+ Guint x0, y0, x1, y1; // bounds
+ Guint nXCBs, nYCBs; // number of code-blocks in the x and y
+ // directions
+
+ //----- tag trees
+ Guint maxTTLevel; // max tag tree level
+ JPXTagTreeNode *inclusion; // inclusion tag tree for each subband
+ JPXTagTreeNode *zeroBitPlane; // zero-bit plane tag tree for each
+ // subband
+
+ //----- children
+ JPXCodeBlock *cbs; // the code-blocks (len = nXCBs * nYCBs)
+};
+
+//------------------------------------------------------------------------
+
+struct JPXPrecinct {
+ //----- computed
+ Guint x0, y0, x1, y1; // bounds of the precinct
+
+ //----- children
+ JPXSubband *subbands; // the subbands
+};
+
+//------------------------------------------------------------------------
+
+struct JPXResLevel {
+ //----- from the COD and COC segments (main and tile)
+ Guint precinctWidth; // log2(precinct width)
+ Guint precinctHeight; // log2(precinct height)
+
+ //----- computed
+ Guint x0, y0, x1, y1; // bounds of the tile-comp (for this res level)
+ Guint bx0[3], by0[3], // subband bounds
+ bx1[3], by1[3];
+
+ //---- children
+ JPXPrecinct *precincts; // the precincts
+};
+
+//------------------------------------------------------------------------
+
+struct JPXTileComp {
+ //----- from the SIZ segment
+ GBool sgned; // 1 for signed, 0 for unsigned
+ Guint prec; // precision, in bits
+ Guint hSep; // horizontal separation of samples
+ Guint vSep; // vertical separation of samples
+
+ //----- from the COD and COC segments (main and tile)
+ Guint style; // coding style parameter (Scod / Scoc)
+ Guint nDecompLevels; // number of decomposition levels
+ Guint codeBlockW; // log2(code-block width)
+ Guint codeBlockH; // log2(code-block height)
+ Guint codeBlockStyle; // code-block style
+ Guint transform; // wavelet transformation
+
+ //----- from the QCD and QCC segments (main and tile)
+ Guint quantStyle; // quantization style
+ Guint *quantSteps; // quantization step size for each subband
+ Guint nQuantSteps; // number of entries in quantSteps
+
+ //----- computed
+ Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords
+ Guint cbW; // code-block width
+ Guint cbH; // code-block height
+
+ //----- image data
+ int *data; // the decoded image data
+ int *buf; // intermediate buffer for the inverse
+ // transform
+
+ //----- children
+ JPXResLevel *resLevels; // the resolution levels
+ // (len = nDecompLevels + 1)
+};
+
+//------------------------------------------------------------------------
+
+struct JPXTile {
+ //----- from the COD segments (main and tile)
+ Guint progOrder; // progression order
+ Guint nLayers; // number of layers
+ Guint multiComp; // multiple component transformation
+
+ //----- computed
+ Guint x0, y0, x1, y1; // bounds of the tile, in ref coords
+ Guint maxNDecompLevels; // max number of decomposition levels used
+ // in any component in this tile
+
+ //----- progression order loop counters
+ Guint comp; // component
+ Guint res; // resolution level
+ Guint precinct; // precinct
+ Guint layer; // layer
+
+ //----- children
+ JPXTileComp *tileComps; // the tile-components (len = JPXImage.nComps)
+};
+
+//------------------------------------------------------------------------
+
+struct JPXImage {
+ //----- from the SIZ segment
+ Guint xSize, ySize; // size of reference grid
+ Guint xOffset, yOffset; // image offset
+ Guint xTileSize, yTileSize; // size of tiles
+ Guint xTileOffset, // offset of first tile
+ yTileOffset;
+ Guint nComps; // number of components
+
+ //----- computed
+ Guint nXTiles; // number of tiles in x direction
+ Guint nYTiles; // number of tiles in y direction
+
+ //----- children
+ JPXTile *tiles; // the tiles (len = nXTiles * nYTiles)
+};
+
+//------------------------------------------------------------------------
+
+class JPXStream: public FilterStream {
+public:
+
+ JPXStream(Stream *strA);
+ virtual ~JPXStream();
+ virtual StreamKind getKind() { return strJPX; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ void fillReadBuf();
+ GBool readBoxes();
+ GBool readColorSpecBox(Guint dataLen);
+ GBool readCodestream(Guint len);
+ GBool readTilePart();
+ GBool readTilePartData(Guint tileIdx,
+ Guint tilePartLen, GBool tilePartToEOC);
+ GBool readCodeBlockData(JPXTileComp *tileComp,
+ JPXResLevel *resLevel,
+ JPXPrecinct *precinct,
+ JPXSubband *subband,
+ Guint res, Guint sb,
+ JPXCodeBlock *cb);
+ void inverseTransform(JPXTileComp *tileComp);
+ void inverseTransformLevel(JPXTileComp *tileComp,
+ Guint r, JPXResLevel *resLevel,
+ Guint nx0, Guint ny0,
+ Guint nx1, Guint ny1);
+ void inverseTransform1D(JPXTileComp *tileComp,
+ int *data, Guint stride,
+ Guint i0, Guint i1);
+ GBool inverseMultiCompAndDC(JPXTile *tile);
+ GBool readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen);
+ int readMarkerHdr(int *segType, Guint *segLen);
+ GBool readUByte(Guint *x);
+ GBool readByte(int *x);
+ GBool readUWord(Guint *x);
+ GBool readULong(Guint *x);
+ GBool readNBytes(int nBytes, GBool signd, int *x);
+ GBool readBits(int nBits, Guint *x);
+ void clearBitBuf();
+
+ Guint nComps; // number of components
+ Guint *bpc; // bits per component, for each component
+ Guint width, height; // image size
+ GBool haveImgHdr; // set if a JP2/JPX image header has been
+ // found
+ JPXColorSpec cs; // color specification
+ GBool haveCS; // set if a color spec has been found
+ JPXPalette palette; // the palette
+ GBool havePalette; // set if a palette has been found
+ JPXCompMap compMap; // the component mapping
+ GBool haveCompMap; // set if a component mapping has been found
+ JPXChannelDefn channelDefn; // channel definition
+ GBool haveChannelDefn; // set if a channel defn has been found
+
+ JPXImage img; // JPEG2000 decoder data
+ Guint bitBuf; // buffer for bit reads
+ int bitBufLen; // number of bits in bitBuf
+ GBool bitBufSkip; // true if next bit should be skipped
+ // (for bit stuffing)
+ Guint byteCount; // number of bytes read since last call
+ // to clearBitBuf
+
+ Guint curX, curY, curComp; // current position for lookChar/getChar
+ Guint readBuf; // read buffer
+ Guint readBufLen; // number of valid bits in readBuf
+};
+
+#endif
diff --git a/pdf2swf/xpdf/Lexer.cc b/pdf2swf/xpdf/Lexer.cc
index d0374691..1fa166f1 100644
--- a/pdf2swf/xpdf/Lexer.cc
+++ b/pdf2swf/xpdf/Lexer.cc
@@ -2,15 +2,16 @@
//
// Lexer.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
diff --git a/pdf2swf/xpdf/Lexer.h b/pdf2swf/xpdf/Lexer.h
index 8a01ab25..398d27c3 100644
--- a/pdf2swf/xpdf/Lexer.h
+++ b/pdf2swf/xpdf/Lexer.h
@@ -2,14 +2,16 @@
//
// Lexer.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef LEXER_H
#define LEXER_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Link.cc b/pdf2swf/xpdf/Link.cc
index af64c8be..2d146b57 100644
--- a/pdf2swf/xpdf/Link.cc
+++ b/pdf2swf/xpdf/Link.cc
@@ -2,15 +2,16 @@
//
// Link.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
@@ -22,8 +23,117 @@
#include "Link.h"
//------------------------------------------------------------------------
+// LinkAction
+//------------------------------------------------------------------------
+
+LinkAction *LinkAction::parseDest(Object *obj) {
+ LinkAction *action;
+
+ action = new LinkGoTo(obj);
+ if (!action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
+ LinkAction *action;
+ Object obj2, obj3, obj4;
+
+ if (!obj->isDict()) {
+ error(-1, "Bad annotation action");
+ return NULL;
+ }
+
+ obj->dictLookup("S", &obj2);
+
+ // GoTo action
+ if (obj2.isName("GoTo")) {
+ obj->dictLookup("D", &obj3);
+ action = new LinkGoTo(&obj3);
+ obj3.free();
+
+ // GoToR action
+ } else if (obj2.isName("GoToR")) {
+ obj->dictLookup("F", &obj3);
+ obj->dictLookup("D", &obj4);
+ action = new LinkGoToR(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // Launch action
+ } else if (obj2.isName("Launch")) {
+ action = new LinkLaunch(obj);
+
+ // URI action
+ } else if (obj2.isName("URI")) {
+ obj->dictLookup("URI", &obj3);
+ action = new LinkURI(&obj3, baseURI);
+ obj3.free();
+
+ // Named action
+ } else if (obj2.isName("Named")) {
+ obj->dictLookup("N", &obj3);
+ action = new LinkNamed(&obj3);
+ obj3.free();
+
+ // Movie action
+ } else if (obj2.isName("Movie")) {
+ obj->dictLookupNF("Annot", &obj3);
+ obj->dictLookup("T", &obj4);
+ action = new LinkMovie(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // unknown action
+ } else if (obj2.isName()) {
+ action = new LinkUnknown(obj2.getName());
+
+ // action is missing or wrong type
+ } else {
+ error(-1, "Bad annotation action");
+ action = NULL;
+ }
+
+ obj2.free();
+
+ if (action && !action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
+ GString *name;
+ Object obj1;
+
+ name = NULL;
+
+ // string
+ if (fileSpecObj->isString()) {
+ name = fileSpecObj->getString()->copy();
+
+ // dictionary
+ } else if (fileSpecObj->isDict()) {
+ if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
+ obj1.free();
+ fileSpecObj->dictLookup("F", &obj1);
+ }
+ if (obj1.isString())
+ name = obj1.getString()->copy();
+ else
+ error(-1, "Illegal file spec in link");
+ obj1.free();
+
+ // error
+ } else {
+ error(-1, "Illegal file spec in link");
+ }
-static GString *getFileSpecName(Object *fileSpecObj);
+ return name;
+}
//------------------------------------------------------------------------
// LinkDest
@@ -37,6 +147,10 @@ LinkDest::LinkDest(Array *a) {
ok = gFalse;
// get page
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array is too short");
+ return;
+ }
a->getNF(0, &obj1);
if (obj1.isInt()) {
pageNum = obj1.getInt() + 1;
@@ -57,46 +171,66 @@ LinkDest::LinkDest(Array *a) {
// XYZ link
if (obj1.isName("XYZ")) {
kind = destXYZ;
- a->get(2, &obj2);
- if (obj2.isNull()) {
+ if (a->getLength() < 3) {
changeLeft = gFalse;
- } else if (obj2.isNum()) {
- changeLeft = gTrue;
- left = obj2.getNum();
} else {
- error(-1, "Bad annotation destination position");
- goto err1;
+ a->get(2, &obj2);
+ if (obj2.isNull()) {
+ changeLeft = gFalse;
+ } else if (obj2.isNum()) {
+ changeLeft = gTrue;
+ left = obj2.getNum();
+ } else {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ obj2.free();
}
- obj2.free();
- a->get(3, &obj2);
- if (obj2.isNull()) {
+ if (a->getLength() < 4) {
changeTop = gFalse;
- } else if (obj2.isNum()) {
- changeTop = gTrue;
- top = obj2.getNum();
} else {
- error(-1, "Bad annotation destination position");
- goto err1;
+ a->get(3, &obj2);
+ if (obj2.isNull()) {
+ changeTop = gFalse;
+ } else if (obj2.isNum()) {
+ changeTop = gTrue;
+ top = obj2.getNum();
+ } else {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ obj2.free();
}
- obj2.free();
- a->get(4, &obj2);
- if (obj2.isNull()) {
+ if (a->getLength() < 5) {
changeZoom = gFalse;
- } else if (obj2.isNum()) {
- changeZoom = gTrue;
- zoom = obj2.getNum();
} else {
- error(-1, "Bad annotation destination position");
- goto err1;
+ a->get(4, &obj2);
+ if (obj2.isNull()) {
+ changeZoom = gFalse;
+ } else if (obj2.isNum()) {
+ changeZoom = gTrue;
+ zoom = obj2.getNum();
+ } else {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ obj2.free();
}
- obj2.free();
// Fit link
} else if (obj1.isName("Fit")) {
+ 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 is too short");
+ goto err2;
+ }
kind = destFitH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -107,6 +241,10 @@ LinkDest::LinkDest(Array *a) {
// FitV link
} else if (obj1.isName("FitV")) {
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
kind = destFitV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -117,6 +255,10 @@ LinkDest::LinkDest(Array *a) {
// FitR link
} else if (obj1.isName("FitR")) {
+ if (a->getLength() < 6) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
kind = destFitR;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -145,10 +287,18 @@ LinkDest::LinkDest(Array *a) {
// FitB link
} else if (obj1.isName("FitB")) {
+ 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 is too short");
+ goto err2;
+ }
kind = destFitBH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -159,6 +309,10 @@ LinkDest::LinkDest(Array *a) {
// FitBV link
} else if (obj1.isName("FitBV")) {
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
kind = destFitBV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -292,18 +446,33 @@ LinkLaunch::LinkLaunch(Object *actionObj) {
fileName = getFileSpecName(&obj1);
} else {
obj1.free();
+#ifdef WIN32
+ if (actionObj->dictLookup("Win", &obj1)->isDict()) {
+ obj1.dictLookup("F", &obj2);
+ fileName = getFileSpecName(&obj2);
+ obj2.free();
+ if (obj1.dictLookup("P", &obj2)->isString()) {
+ params = obj2.getString()->copy();
+ }
+ obj2.free();
+ } else {
+ error(-1, "Bad launch-type link action");
+ }
+#else
//~ This hasn't been defined by Adobe yet, so assume it looks
//~ just like the Win dictionary until they say otherwise.
if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
obj1.dictLookup("F", &obj2);
fileName = getFileSpecName(&obj2);
obj2.free();
- if (obj1.dictLookup("P", &obj2)->isString())
+ if (obj1.dictLookup("P", &obj2)->isString()) {
params = obj2.getString()->copy();
+ }
obj2.free();
} else {
error(-1, "Bad launch-type link action");
}
+#endif
}
obj1.free();
}
@@ -378,6 +547,28 @@ LinkNamed::~LinkNamed() {
}
//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
+ annotRef.num = -1;
+ title = NULL;
+ if (annotObj->isRef()) {
+ annotRef = annotObj->getRef();
+ } else if (titleObj->isString()) {
+ title = titleObj->getString()->copy();
+ } else {
+ error(-1, "Movie action is missing both the Annot and T keys");
+ }
+}
+
+LinkMovie::~LinkMovie() {
+ if (title) {
+ delete title;
+ }
+}
+
+//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
@@ -390,13 +581,42 @@ LinkUnknown::~LinkUnknown() {
}
//------------------------------------------------------------------------
+// LinkBorderStyle
+//------------------------------------------------------------------------
+
+LinkBorderStyle::LinkBorderStyle(LinkBorderType typeA, double widthA,
+ double *dashA, int dashLengthA,
+ double rA, double gA, double bA) {
+ type = typeA;
+ width = widthA;
+ dash = dashA;
+ dashLength = dashLengthA;
+ r = rA;
+ g = gA;
+ b = bA;
+}
+
+LinkBorderStyle::~LinkBorderStyle() {
+ if (dash) {
+ gfree(dash);
+ }
+}
+
+//------------------------------------------------------------------------
// Link
//------------------------------------------------------------------------
Link::Link(Dict *dict, GString *baseURI) {
- Object obj1, obj2, obj3, obj4;
+ Object obj1, obj2, obj3;
+ LinkBorderType borderType;
+ double borderWidth;
+ double *borderDash;
+ int borderDashLength;
+ double borderR, borderG, borderB;
double t;
+ int i;
+ borderStyle = NULL;
action = NULL;
ok = gFalse;
@@ -441,82 +661,110 @@ Link::Link(Dict *dict, GString *baseURI) {
y2 = t;
}
- // get border
- borderW = 1;
- if (!dict->lookup("Border", &obj1)->isNull()) {
- if (obj1.isArray() && obj1.arrayGetLength() >= 3) {
- if (obj1.arrayGet(2, &obj2)->isNum()) {
- borderW = obj2.getNum();
- } else {
- error(-1, "Bad annotation border");
+ // get the border style info
+ borderType = linkBorderSolid;
+ borderWidth = 1;
+ borderDash = NULL;
+ borderDashLength = 0;
+ borderR = 0;
+ borderG = 0;
+ borderB = 1;
+ if (dict->lookup("BS", &obj1)->isDict()) {
+ if (obj1.dictLookup("S", &obj2)->isName()) {
+ if (obj2.isName("S")) {
+ borderType = linkBorderSolid;
+ } else if (obj2.isName("D")) {
+ borderType = linkBorderDashed;
+ } else if (obj2.isName("B")) {
+ borderType = linkBorderEmbossed;
+ } else if (obj2.isName("I")) {
+ borderType = linkBorderEngraved;
+ } else if (obj2.isName("U")) {
+ borderType = linkBorderUnderlined;
+ }
+ }
+ obj2.free();
+ if (obj1.dictLookup("W", &obj2)->isNum()) {
+ borderWidth = obj2.getNum();
+ }
+ obj2.free();
+ if (obj1.dictLookup("D", &obj2)->isArray()) {
+ borderDashLength = obj2.arrayGetLength();
+ borderDash = (double *)gmalloc(borderDashLength * sizeof(double));
+ for (i = 0; i < borderDashLength; ++i) {
+ if (obj2.arrayGet(i, &obj3)->isNum()) {
+ borderDash[i] = obj3.getNum();
+ } else {
+ borderDash[i] = 1;
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+ } else {
+ obj1.free();
+ if (dict->lookup("Border", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() >= 3) {
+ if (obj1.arrayGet(2, &obj2)->isNum()) {
+ borderWidth = obj2.getNum();
+ }
+ obj2.free();
+ if (obj1.arrayGetLength() >= 4) {
+ if (obj1.arrayGet(3, &obj2)->isArray()) {
+ borderType = linkBorderDashed;
+ borderDashLength = obj2.arrayGetLength();
+ borderDash = (double *)gmalloc(borderDashLength * sizeof(double));
+ for (i = 0; i < borderDashLength; ++i) {
+ if (obj2.arrayGet(i, &obj3)->isNum()) {
+ borderDash[i] = obj3.getNum();
+ } else {
+ borderDash[i] = 1;
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+ }
}
- obj2.free();
}
}
obj1.free();
+ if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) {
+ if (obj1.arrayGet(0, &obj2)->isNum()) {
+ borderR = obj2.getNum();
+ }
+ obj1.free();
+ if (obj1.arrayGet(1, &obj2)->isNum()) {
+ borderG = obj2.getNum();
+ }
+ obj1.free();
+ if (obj1.arrayGet(2, &obj2)->isNum()) {
+ borderB = obj2.getNum();
+ }
+ obj1.free();
+ }
+ obj1.free();
+ borderStyle = new LinkBorderStyle(borderType, borderWidth,
+ borderDash, borderDashLength,
+ borderR, borderG, borderB);
// look for destination
if (!dict->lookup("Dest", &obj1)->isNull()) {
- action = new LinkGoTo(&obj1);
+ action = LinkAction::parseDest(&obj1);
// look for action
} else {
obj1.free();
if (dict->lookup("A", &obj1)->isDict()) {
- obj1.dictLookup("S", &obj2);
-
- // GoTo action
- if (obj2.isName("GoTo")) {
- obj1.dictLookup("D", &obj3);
- action = new LinkGoTo(&obj3);
- obj3.free();
-
- // GoToR action
- } else if (obj2.isName("GoToR")) {
- obj1.dictLookup("F", &obj3);
- obj1.dictLookup("D", &obj4);
- action = new LinkGoToR(&obj3, &obj4);
- obj3.free();
- obj4.free();
-
- // Launch action
- } else if (obj2.isName("Launch")) {
- action = new LinkLaunch(&obj1);
-
- // URI action
- } else if (obj2.isName("URI")) {
- obj1.dictLookup("URI", &obj3);
- action = new LinkURI(&obj3, baseURI);
- obj3.free();
-
- // Named action
- } else if (obj2.isName("Named")) {
- obj1.dictLookup("N", &obj3);
- action = new LinkNamed(&obj3);
- obj3.free();
-
- // unknown action
- } else if (obj2.isName()) {
- action = new LinkUnknown(obj2.getName());
-
- // action is missing or wrong type
- } else {
- error(-1, "Bad annotation action");
- action = NULL;
- }
-
- obj2.free();
-
- } else {
- error(-1, "Missing annotation destination/action");
- action = NULL;
+ action = LinkAction::parseAction(&obj1, baseURI);
}
}
obj1.free();
// check for bad action
- if (action && action->isOk())
+ if (action) {
ok = gTrue;
+ }
return;
@@ -527,8 +775,12 @@ Link::Link(Dict *dict, GString *baseURI) {
}
Link::~Link() {
- if (action)
+ if (borderStyle) {
+ delete borderStyle;
+ }
+ if (action) {
delete action;
+ }
}
//------------------------------------------------------------------------
@@ -595,36 +847,3 @@ GBool Links::onLink(double x, double y) {
}
return gFalse;
}
-
-//------------------------------------------------------------------------
-
-// Extract a file name from a file specification (string or dictionary).
-static GString *getFileSpecName(Object *fileSpecObj) {
- GString *name;
- Object obj1;
-
- name = NULL;
-
- // string
- if (fileSpecObj->isString()) {
- name = fileSpecObj->getString()->copy();
-
- // dictionary
- } else if (fileSpecObj->isDict()) {
- if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
- obj1.free();
- fileSpecObj->dictLookup("F", &obj1);
- }
- if (obj1.isString())
- name = obj1.getString()->copy();
- else
- error(-1, "Illegal file spec in link");
- obj1.free();
-
- // error
- } else {
- error(-1, "Illegal file spec in link");
- }
-
- return name;
-}
diff --git a/pdf2swf/xpdf/Link.h b/pdf2swf/xpdf/Link.h
index 4c644b86..9f044204 100644
--- a/pdf2swf/xpdf/Link.h
+++ b/pdf2swf/xpdf/Link.h
@@ -2,14 +2,16 @@
//
// Link.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef LINK_H
#define LINK_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -29,6 +31,7 @@ enum LinkActionKind {
actionLaunch, // launch app (or open document)
actionURI, // URI
actionNamed, // named action
+ actionMovie, // movie action
actionUnknown // anything else
};
@@ -43,6 +46,16 @@ public:
// Check link action type.
virtual LinkActionKind getKind() = 0;
+
+ // Parse a destination (old-style action) name, string, or array.
+ static LinkAction *parseDest(Object *obj);
+
+ // Parse an action dictionary.
+ static LinkAction *parseAction(Object *obj, GString *baseURI = NULL);
+
+ // Extract a file name from a file specification (string or
+ // dictionary).
+ static GString *getFileSpecName(Object *fileSpecObj);
};
//------------------------------------------------------------------------
@@ -240,6 +253,30 @@ private:
};
//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+class LinkMovie: public LinkAction {
+public:
+
+ LinkMovie(Object *annotObj, Object *titleObj);
+
+ virtual ~LinkMovie();
+
+ virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; }
+
+ virtual LinkActionKind getKind() { return actionMovie; }
+ GBool hasAnnotRef() { return annotRef.num >= 0; }
+ Ref *getAnnotRef() { return &annotRef; }
+ GString *getTitle() { return title; }
+
+private:
+
+ Ref annotRef;
+ GString *title;
+};
+
+//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
@@ -265,6 +302,42 @@ private:
};
//------------------------------------------------------------------------
+// LinkBorderStyle
+//------------------------------------------------------------------------
+
+enum LinkBorderType {
+ linkBorderSolid,
+ linkBorderDashed,
+ linkBorderEmbossed,
+ linkBorderEngraved,
+ linkBorderUnderlined
+};
+
+class LinkBorderStyle {
+public:
+
+ LinkBorderStyle(LinkBorderType typeA, double widthA,
+ double *dashA, int dashLengthA,
+ double rA, double gA, double bA);
+ ~LinkBorderStyle();
+
+ LinkBorderType getType() { return type; }
+ double getWidth() { return width; }
+ void getDash(double **dashA, int *dashLengthA)
+ { *dashA = dash; *dashLengthA = dashLength; }
+ void getColor(double *rA, double *gA, double *bA)
+ { *rA = r; *gA = g; *bA = b; }
+
+private:
+
+ LinkBorderType type;
+ double width;
+ double *dash;
+ int dashLength;
+ double r, g, b;
+};
+
+//------------------------------------------------------------------------
// Link
//------------------------------------------------------------------------
@@ -287,16 +360,18 @@ public:
// Get action.
LinkAction *getAction() { return action; }
- // Get border corners and width.
- void getBorder(double *xa1, double *ya1, double *xa2, double *ya2,
- double *wa)
- { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; *wa = borderW; }
+ // Get the link rectangle.
+ void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
+ { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
+
+ // Get the border style info.
+ LinkBorderStyle *getBorderStyle() { return borderStyle; }
private:
double x1, y1; // lower left corner
double x2, y2; // upper right corner
- double borderW; // border width
+ LinkBorderStyle *borderStyle; // border style
LinkAction *action; // action
GBool ok; // is link valid?
};
diff --git a/pdf2swf/xpdf/NameToCharCode.cc b/pdf2swf/xpdf/NameToCharCode.cc
index b9cde77d..8f22a907 100644
--- a/pdf2swf/xpdf/NameToCharCode.cc
+++ b/pdf2swf/xpdf/NameToCharCode.cc
@@ -2,15 +2,16 @@
//
// NameToCharCode.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <string.h>
#include "gmem.h"
#include "NameToCharCode.h"
diff --git a/pdf2swf/xpdf/NameToCharCode.h b/pdf2swf/xpdf/NameToCharCode.h
index 22e41b61..65453c3a 100644
--- a/pdf2swf/xpdf/NameToCharCode.h
+++ b/pdf2swf/xpdf/NameToCharCode.h
@@ -2,14 +2,16 @@
//
// NameToCharCode.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef NAMETOCHARCODE_H
#define NAMETOCHARCODE_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/NameToUnicodeTable.h b/pdf2swf/xpdf/NameToUnicodeTable.h
index 432fafb3..4f28ffff 100644
--- a/pdf2swf/xpdf/NameToUnicodeTable.h
+++ b/pdf2swf/xpdf/NameToUnicodeTable.h
@@ -2,7 +2,7 @@
//
// NameToUnicodeTable.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
@@ -10,6 +10,37 @@ static struct {
Unicode u;
char *name;
} nameToUnicodeTab[] = {
+ {0x0021, "!"},
+ {0x0023, "#"},
+ {0x0024, "$"},
+ {0x0025, "%"},
+ {0x0026, "&"},
+ {0x0027, "'"},
+ {0x0028, "("},
+ {0x0029, ")"},
+ {0x002a, "*"},
+ {0x002b, "+"},
+ {0x002c, ","},
+ {0x002d, "-"},
+ {0x002e, "."},
+ {0x002f, "/"},
+ {0x0030, "0"},
+ {0x0031, "1"},
+ {0x0032, "2"},
+ {0x0033, "3"},
+ {0x0034, "4"},
+ {0x0035, "5"},
+ {0x0036, "6"},
+ {0x0037, "7"},
+ {0x0038, "8"},
+ {0x0039, "9"},
+ {0x003a, ":"},
+ {0x003b, ";"},
+ {0x003c, "<"},
+ {0x003d, "="},
+ {0x003e, ">"},
+ {0x003f, "?"},
+ {0x0040, "@"},
{0x0041, "A"},
{0x00c6, "AE"},
{0x01fc, "AEacute"},
@@ -304,6 +335,12 @@ static struct {
{0x017b, "Zdotaccent"},
{0x0396, "Zeta"},
{0x005a, "Zsmall"},
+ {0x0022, "\""},
+ {0x005c, "\\"},
+ {0x005d, "]"},
+ {0x005e, "^"},
+ {0x005f, "_"},
+ {0x0060, "`"},
{0x0061, "a"},
{0x00e1, "aacute"},
{0x0103, "abreve"},
@@ -647,8 +684,8 @@ static struct {
{0xf6e2, "commasuperior"},
{0x2245, "congruent"},
{0x00a9, "copyright"},
- {0xf8e9, "copyrightsans"},
- {0xf6d9, "copyrightserif"},
+ {0x00a9, "copyrightsans"},
+ {0x00a9, "copyrightserif"},
{0x00a4, "currency"},
{0xf6d1, "cyrBreve"},
{0xf6d2, "cyrFlex"},
@@ -715,6 +752,7 @@ static struct {
{0x203c, "exclamdbl"},
{0x00a1, "exclamdown"},
{0x00a1, "exclamdownsmall"},
+ {0x0021, "exclamleft"},
{0x0021, "exclamsmall"},
{0x2203, "existential"},
{0x0066, "f"},
@@ -934,8 +972,8 @@ static struct {
{0x2286, "reflexsubset"},
{0x2287, "reflexsuperset"},
{0x00ae, "registered"},
- {0xf8e8, "registersans"},
- {0xf6da, "registerserif"},
+ {0x00ae, "registersans"},
+ {0x00ae, "registerserif"},
{0x2310, "revlogicalnot"},
{0x03c1, "rho"},
{0x02da, "ring"},
@@ -993,8 +1031,8 @@ static struct {
{0x0303, "tildecomb"},
{0x0384, "tonos"},
{0x2122, "trademark"},
- {0xf8ea, "trademarksans"},
- {0xf6db, "trademarkserif"},
+ {0x2122, "trademarksans"},
+ {0x2122, "trademarkserif"},
{0x25bc, "triagdn"},
{0x25c4, "triaglf"},
{0x25ba, "triagrt"},
@@ -1051,5 +1089,9 @@ static struct {
{0x0030, "zerooldstyle"},
{0x2070, "zerosuperior"},
{0x03b6, "zeta"},
+ {0x007b, "{"},
+ {0x007c, "|"},
+ {0x007d, "}"},
+ {0x007e, "~"},
{ 0, NULL }
};
diff --git a/pdf2swf/xpdf/Object.cc b/pdf2swf/xpdf/Object.cc
index 6d92c6a3..ddd6da69 100644
--- a/pdf2swf/xpdf/Object.cc
+++ b/pdf2swf/xpdf/Object.cc
@@ -2,15 +2,16 @@
//
// Object.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
@@ -57,6 +58,13 @@ Object *Object::initDict(XRef *xref) {
return this;
}
+Object *Object::initDict(Dict *dictA) {
+ initObj(objDict);
+ dict = dictA;
+ dict->incRef();
+ return this;
+}
+
Object *Object::initStream(Stream *streamA) {
initObj(objStream);
stream = streamA;
diff --git a/pdf2swf/xpdf/Object.h b/pdf2swf/xpdf/Object.h
index 65d0be0d..8b1807c5 100644
--- a/pdf2swf/xpdf/Object.h
+++ b/pdf2swf/xpdf/Object.h
@@ -2,14 +2,16 @@
//
// Object.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef OBJECT_H
#define OBJECT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -93,6 +95,7 @@ public:
{ initObj(objNull); return this; }
Object *initArray(XRef *xref);
Object *initDict(XRef *xref);
+ Object *initDict(Dict *dictA);
Object *initStream(Stream *streamA);
Object *initRef(int numA, int genA)
{ initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
@@ -152,6 +155,7 @@ public:
Ref getRef() { return ref; }
int getRefNum() { return ref.num; }
int getRefGen() { return ref.gen; }
+ char *getCmd() { return cmd; }
// Array accessors.
int arrayGetLength();
diff --git a/pdf2swf/xpdf/Outline.cc b/pdf2swf/xpdf/Outline.cc
new file mode 100644
index 00000000..04891f3c
--- /dev/null
+++ b/pdf2swf/xpdf/Outline.cc
@@ -0,0 +1,151 @@
+//========================================================================
+//
+// Outline.cc
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "GString.h"
+#include "GList.h"
+#include "Link.h"
+#include "PDFDocEncoding.h"
+#include "Outline.h"
+
+//------------------------------------------------------------------------
+
+Outline::Outline(Object *outlineObj, XRef *xref) {
+ Object first, last;
+
+ items = NULL;
+ if (!outlineObj->isDict()) {
+ return;
+ }
+ items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first),
+ outlineObj->dictLookupNF("Last", &last),
+ xref);
+ first.free();
+ last.free();
+}
+
+Outline::~Outline() {
+ if (items) {
+ deleteGList(items, OutlineItem);
+ }
+}
+
+//------------------------------------------------------------------------
+
+OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
+ Object obj1;
+ GString *s;
+ int i;
+
+ xref = xrefA;
+ title = NULL;
+ action = NULL;
+ kids = NULL;
+
+ if (dict->lookup("Title", &obj1)->isString()) {
+ s = obj1.getString();
+ if ((s->getChar(0) & 0xff) == 0xfe &&
+ (s->getChar(1) & 0xff) == 0xff) {
+ titleLen = (s->getLength() - 2) / 2;
+ title = (Unicode *)gmalloc(titleLen * sizeof(Unicode));
+ for (i = 0; i < titleLen; ++i) {
+ title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
+ (s->getChar(3 + 2*i) & 0xff);
+ }
+ } else {
+ titleLen = s->getLength();
+ title = (Unicode *)gmalloc(titleLen * sizeof(Unicode));
+ for (i = 0; i < titleLen; ++i) {
+ title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
+ }
+ }
+ } else {
+ titleLen = 0;
+ }
+ obj1.free();
+
+ if (!dict->lookup("Dest", &obj1)->isNull()) {
+ action = LinkAction::parseDest(&obj1);
+ } else {
+ obj1.free();
+ if (dict->lookup("A", &obj1)) {
+ action = LinkAction::parseAction(&obj1);
+ }
+ }
+ obj1.free();
+
+ dict->lookupNF("First", &firstRef);
+ dict->lookupNF("Last", &lastRef);
+ dict->lookupNF("Next", &nextRef);
+
+ startsOpen = gFalse;
+ if (dict->lookup("Count", &obj1)->isInt()) {
+ if (obj1.getInt() > 0) {
+ startsOpen = gTrue;
+ }
+ }
+ obj1.free();
+}
+
+OutlineItem::~OutlineItem() {
+ close();
+ if (title) {
+ gfree(title);
+ }
+ if (action) {
+ delete action;
+ }
+ firstRef.free();
+ lastRef.free();
+ nextRef.free();
+}
+
+GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
+ XRef *xrefA) {
+ GList *items;
+ OutlineItem *item;
+ Object obj;
+ Object *p;
+
+ items = new GList();
+ p = firstItemRef;
+ while (p->isRef()) {
+ if (!p->fetch(xrefA, &obj)->isDict()) {
+ obj.free();
+ break;
+ }
+ item = new OutlineItem(obj.getDict(), xrefA);
+ obj.free();
+ items->append(item);
+ if (p->getRef().num == lastItemRef->getRef().num &&
+ p->getRef().gen == lastItemRef->getRef().gen) {
+ break;
+ }
+ p = &item->nextRef;
+ }
+ return items;
+}
+
+void OutlineItem::open() {
+ if (!kids) {
+ kids = readItemList(&firstRef, &lastRef, xref);
+ }
+}
+
+void OutlineItem::close() {
+ if (kids) {
+ deleteGList(kids, OutlineItem);
+ kids = NULL;
+ }
+}
diff --git a/pdf2swf/xpdf/Outline.h b/pdf2swf/xpdf/Outline.h
new file mode 100644
index 00000000..f38f8d16
--- /dev/null
+++ b/pdf2swf/xpdf/Outline.h
@@ -0,0 +1,76 @@
+//========================================================================
+//
+// Outline.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef OUTLINE_H
+#define OUTLINE_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+#include "CharTypes.h"
+
+class GString;
+class GList;
+class XRef;
+class LinkAction;
+
+//------------------------------------------------------------------------
+
+class Outline {
+public:
+
+ Outline(Object *outlineObj, XRef *xref);
+ ~Outline();
+
+ GList *getItems() { return items; }
+
+private:
+
+ GList *items; // NULL if document has no outline
+ // [OutlineItem]
+};
+
+//------------------------------------------------------------------------
+
+class OutlineItem {
+public:
+
+ OutlineItem(Dict *dict, XRef *xrefA);
+ ~OutlineItem();
+
+ static GList *readItemList(Object *firstItemRef, Object *lastItemRef,
+ XRef *xrefA);
+
+ void open();
+ void close();
+
+ Unicode *getTitle() { return title; }
+ int getTitleLength() { return titleLen; }
+ LinkAction *getAction() { return action; }
+ GBool isOpen() { return startsOpen; }
+ GBool hasKids() { return firstRef.isRef(); }
+ GList *getKids() { return kids; }
+
+private:
+
+ XRef *xref;
+ Unicode *title;
+ int titleLen;
+ LinkAction *action;
+ Object firstRef;
+ Object lastRef;
+ Object nextRef;
+ GBool startsOpen;
+ GList *kids; // NULL unless this item is open [OutlineItem]
+};
+
+#endif
diff --git a/pdf2swf/xpdf/OutputDev.cc b/pdf2swf/xpdf/OutputDev.cc
index 6d465423..e83882df 100644
--- a/pdf2swf/xpdf/OutputDev.cc
+++ b/pdf2swf/xpdf/OutputDev.cc
@@ -2,15 +2,16 @@
//
// OutputDev.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Stream.h"
@@ -37,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];
}
@@ -59,7 +60,8 @@ void OutputDev::updateAll(GfxState *state) {
updateFont(state);
}
-GBool OutputDev::beginType3Char(GfxState *state,
+GBool OutputDev::beginType3Char(GfxState *state, double x, double y,
+ double dx, double dy,
CharCode code, Unicode *u, int uLen) {
return gFalse;
}
diff --git a/pdf2swf/xpdf/OutputDev.h b/pdf2swf/xpdf/OutputDev.h
index 4a05f1ac..fb7d8abe 100644
--- a/pdf2swf/xpdf/OutputDev.h
+++ b/pdf2swf/xpdf/OutputDev.h
@@ -2,14 +2,16 @@
//
// OutputDev.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef OUTPUTDEV_H
#define OUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -59,7 +61,7 @@ public:
virtual void setDefaultCTM(double *ctm);
// Start a page.
- virtual void startPage(int pageNum, GfxState *state, double x1,double y1,double x2,double y2) {}
+ virtual void startPage(int pageNum, GfxState *state) {}
// End a page.
virtual void endPage() {}
@@ -70,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
@@ -123,9 +125,11 @@ public:
double originX, double originY,
CharCode code, Unicode *u, int uLen) {}
virtual void drawString(GfxState *state, GString *s) {}
- virtual GBool beginType3Char(GfxState *state,
+ virtual GBool beginType3Char(GfxState *state, double x, double y,
+ double dx, double dy,
CharCode code, Unicode *u, int uLen);
virtual void endType3Char(GfxState *state) {}
+ virtual void endTextObject(GfxState *state) {}
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
diff --git a/pdf2swf/xpdf/PDFDoc.cc b/pdf2swf/xpdf/PDFDoc.cc
index 29abba05..b5981d9b 100644
--- a/pdf2swf/xpdf/PDFDoc.cc
+++ b/pdf2swf/xpdf/PDFDoc.cc
@@ -2,21 +2,23 @@
//
// PDFDoc.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "GString.h"
#include "config.h"
+#include "GlobalParams.h"
#include "Page.h"
#include "Catalog.h"
#include "Stream.h"
@@ -27,6 +29,9 @@
#include "ErrorCodes.h"
#include "Lexer.h"
#include "Parser.h"
+#ifndef DISABLE_OUTLINE
+#include "Outline.h"
+#endif
#include "PDFDoc.h"
//------------------------------------------------------------------------
@@ -39,9 +44,9 @@
//------------------------------------------------------------------------
PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
- GString *userPassword, GBool printCommandsA) {
+ GString *userPassword) {
Object obj;
- GString *fileName2;
+ GString *fileName1, *fileName2;
ok = gFalse;
errCode = errNone;
@@ -51,19 +56,24 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
xref = NULL;
catalog = NULL;
links = NULL;
- printCommands = printCommandsA;
+#ifndef DISABLE_OUTLINE
+ outline = NULL;
+#endif
- // try to open file
fileName = fileNameA;
+ fileName1 = fileName;
+
+
+ // try to open file
fileName2 = NULL;
#ifdef VMS
- if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
- error(-1, "Couldn't open file '%s'", fileName->getCString());
+ if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
+ error(-1, "Couldn't open file '%s'", fileName1->getCString());
errCode = errOpenFile;
return;
}
#else
- if (!(file = fopen(fileName->getCString(), "rb"))) {
+ if (!(file = fopen(fileName1->getCString(), "rb"))) {
fileName2 = fileName->copy();
fileName2->lowerCase();
if (!(file = fopen(fileName2->getCString(), "rb"))) {
@@ -87,7 +97,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
}
PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
- GString *userPassword, GBool printCommandsA) {
+ GString *userPassword) {
ok = gFalse;
errCode = errNone;
fileName = NULL;
@@ -96,11 +106,15 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
xref = NULL;
catalog = NULL;
links = NULL;
- printCommands = printCommandsA;
+#ifndef DISABLE_OUTLINE
+ outline = NULL;
+#endif
ok = setup(ownerPassword, userPassword);
}
GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
+ str->reset();
+
// check header
checkHeader();
@@ -113,18 +127,28 @@ GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
}
// read catalog
- catalog = new Catalog(xref, printCommands);
+ catalog = new Catalog(xref);
if (!catalog->isOk()) {
error(-1, "Couldn't read page catalog");
errCode = errBadCatalog;
return gFalse;
}
+#ifndef DISABLE_OUTLINE
+ // read outline
+ outline = new Outline(catalog->getOutline(), xref);
+#endif
+
// done
return gTrue;
}
PDFDoc::~PDFDoc() {
+#ifndef DISABLE_OUTLINE
+ if (outline) {
+ delete outline;
+ }
+#endif
if (catalog) {
delete catalog;
}
@@ -176,11 +200,13 @@ void PDFDoc::checkHeader() {
}
}
-void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
- int rotate, GBool doLinks) {
+void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
+ int rotate, GBool crop, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
Page *p;
- if (printCommands) {
+ if (globalParams->getPrintCommands()) {
printf("***** page %d *****\n", page);
}
p = catalog->getPage(page);
@@ -189,21 +215,41 @@ void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
delete links;
}
getLinks(p);
- p->display(out, zoom, rotate, links, catalog);
+ p->display(out, hDPI, vDPI, rotate, crop, links, catalog,
+ abortCheckCbk, abortCheckCbkData);
} else {
- p->display(out, zoom, rotate, NULL, catalog);
+ p->display(out, hDPI, vDPI, rotate, crop, NULL, catalog,
+ abortCheckCbk, abortCheckCbkData);
}
}
void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
- int zoom, int rotate, GBool doLinks) {
+ double hDPI, double vDPI, int rotate,
+ GBool crop, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
int page;
for (page = firstPage; page <= lastPage; ++page) {
- displayPage(out, page, zoom, rotate, doLinks);
+ displayPage(out, page, hDPI, vDPI, rotate, crop, doLinks,
+ abortCheckCbk, abortCheckCbkData);
}
}
+void PDFDoc::displayPageSlice(OutputDev *out, int page,
+ double hDPI, double vDPI,
+ int rotate, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ Page *p;
+
+ p = catalog->getPage(page);
+ p->displaySlice(out, hDPI, vDPI, rotate, crop,
+ sliceX, sliceY, sliceW, sliceH,
+ NULL, catalog, abortCheckCbk, abortCheckCbkData);
+}
+
GBool PDFDoc::isLinearized() {
Parser *parser;
Object obj1, obj2, obj3, obj4, obj5;
diff --git a/pdf2swf/xpdf/PDFDoc.h b/pdf2swf/xpdf/PDFDoc.h
index c12531e9..bdcbd65d 100644
--- a/pdf2swf/xpdf/PDFDoc.h
+++ b/pdf2swf/xpdf/PDFDoc.h
@@ -2,14 +2,16 @@
//
// PDFDoc.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef PDFDOC_H
#define PDFDOC_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -25,6 +27,7 @@ class OutputDev;
class Links;
class LinkAction;
class LinkDest;
+class Outline;
//------------------------------------------------------------------------
// PDFDoc
@@ -34,9 +37,9 @@ class PDFDoc {
public:
PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, GBool printCommandsA = gFalse);
+ GString *userPassword = NULL);
PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, GBool printCommandsA = gFalse);
+ GString *userPassword = NULL);
~PDFDoc();
// Was PDF document successfully opened?
@@ -76,12 +79,25 @@ public:
Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
// Display a page.
- void displayPage(OutputDev *out, int page, double zoom,
- int rotate, GBool doLinks);
+ void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
+ int rotate, GBool crop, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
- int zoom, int rotate, GBool doLinks);
+ double hDPI, double vDPI, int rotate,
+ GBool crop, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display part of a page.
+ void displayPageSlice(OutputDev *out, int page,
+ double hDPI, double vDPI,
+ int rotate, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
// Find a page, given its object ID. Returns page number, or 0 if
// not found.
@@ -89,7 +105,8 @@ public:
// If point <x>,<y> is in a link, return the associated action;
// else return NULL.
- LinkAction *findLink(double x, double y) { return links->find(x, y); }
+ LinkAction *findLink(double x, double y)
+ { return links ? links->find(x, y) : (LinkAction *)NULL; }
// Return true if <x>,<y> is in a link.
GBool onLink(double x, double y) { return links->onLink(x, y); }
@@ -99,6 +116,11 @@ public:
LinkDest *findDest(GString *name)
{ return catalog->findDest(name); }
+#ifndef DISABLE_OUTLINE
+ // Return the outline object.
+ Outline *getOutline() { return outline; }
+#endif
+
// Is the file encrypted?
GBool isEncrypted() { return xref->isEncrypted(); }
@@ -117,6 +139,7 @@ public:
// Return the document's Info dictionary (if any).
Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); }
+ Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); }
// Return the PDF version specified by the file.
double getPDFVersion() { return pdfVersion; }
@@ -124,6 +147,7 @@ public:
// Save this file with another name.
GBool saveAs(GString *name);
+
private:
GBool setup(GString *ownerPassword, GString *userPassword);
@@ -137,7 +161,10 @@ private:
XRef *xref;
Catalog *catalog;
Links *links;
- GBool printCommands;
+#ifndef DISABLE_OUTLINE
+ Outline *outline;
+#endif
+
GBool ok;
int errCode;
diff --git a/pdf2swf/xpdf/PDFDocEncoding.cc b/pdf2swf/xpdf/PDFDocEncoding.cc
new file mode 100644
index 00000000..89dc3828
--- /dev/null
+++ b/pdf2swf/xpdf/PDFDocEncoding.cc
@@ -0,0 +1,44 @@
+//========================================================================
+//
+// PDFDocEncoding.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include "PDFDocEncoding.h"
+
+Unicode pdfDocEncoding[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10
+ 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
+ 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, // 80
+ 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
+ 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, // 90
+ 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000,
+ 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+};
diff --git a/pdf2swf/xpdf/PDFDocEncoding.h b/pdf2swf/xpdf/PDFDocEncoding.h
new file mode 100644
index 00000000..3259d3e1
--- /dev/null
+++ b/pdf2swf/xpdf/PDFDocEncoding.h
@@ -0,0 +1,16 @@
+//========================================================================
+//
+// PDFDocEncoding.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PDFDOCENCODING_H
+#define PDFDOCENCODING_H
+
+#include "CharTypes.h"
+
+extern Unicode pdfDocEncoding[256];
+
+#endif
diff --git a/pdf2swf/xpdf/PSTokenizer.cc b/pdf2swf/xpdf/PSTokenizer.cc
index 8d654bd2..a65c3241 100644
--- a/pdf2swf/xpdf/PSTokenizer.cc
+++ b/pdf2swf/xpdf/PSTokenizer.cc
@@ -2,11 +2,13 @@
//
// PSTokenizer.cc
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
diff --git a/pdf2swf/xpdf/PSTokenizer.h b/pdf2swf/xpdf/PSTokenizer.h
index 1053c675..4d5ee97f 100644
--- a/pdf2swf/xpdf/PSTokenizer.h
+++ b/pdf2swf/xpdf/PSTokenizer.h
@@ -2,14 +2,16 @@
//
// PSTokenizer.h
//
-// Copyright 2002 Glyph & Cog, LLC
+// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef PSTOKENIZER_H
#define PSTOKENIZER_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Page.cc b/pdf2swf/xpdf/Page.cc
index c6018577..ab8504d9 100644
--- a/pdf2swf/xpdf/Page.cc
+++ b/pdf2swf/xpdf/Page.cc
@@ -2,16 +2,18 @@
//
// Page.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
+#include "GlobalParams.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
@@ -57,8 +59,12 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
readBox(dict, "MediaBox", &mediaBox);
// crop box
- cropBox = mediaBox;
- haveCropBox = readBox(dict, "CropBox", &cropBox);
+ if (readBox(dict, "CropBox", &cropBox)) {
+ haveCropBox = gTrue;
+ }
+ if (!haveCropBox) {
+ cropBox = mediaBox;
+ }
// if the MediaBox is excessively larger than the CropBox,
// just use the CropBox
@@ -170,13 +176,10 @@ GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
// Page
//------------------------------------------------------------------------
-Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
- GBool printCommandsA) {
-
+Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
ok = gTrue;
xref = xrefA;
num = numA;
- printCommands = printCommandsA;
// get attributes
attrs = attrsA;
@@ -215,22 +218,91 @@ Page::~Page() {
contents.free();
}
-void Page::display(OutputDev *out, double dpi, int rotate,
- Links *links, Catalog *catalog) {
+void Page::display(OutputDev *out, double hDPI, double vDPI,
+ int rotate, GBool crop,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ displaySlice(out, hDPI, vDPI, rotate, crop, -1, -1, -1, -1, links, catalog,
+ abortCheckCbk, abortCheckCbkData);
+}
+
+void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
+ int rotate, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
#ifndef PDF_PARSER_ONLY
- PDFRectangle *box, *cropBox;
+ PDFRectangle *mediaBox, *cropBox;
+ PDFRectangle box;
Gfx *gfx;
Object obj;
Link *link;
- int i;
Annots *annotList;
+ double kx, ky;
+ int i;
- box = getBox();
+ rotate += getRotate();
+ if (rotate >= 360) {
+ rotate -= 360;
+ } else if (rotate < 0) {
+ rotate += 360;
+ }
+
+ mediaBox = getBox();
+ if (sliceW >= 0 && sliceH >= 0) {
+ kx = 72.0 / hDPI;
+ ky = 72.0 / vDPI;
+ if (rotate == 90) {
+ if (out->upsideDown()) {
+ box.x1 = mediaBox->x1 + ky * sliceY;
+ box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
+ } else {
+ box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
+ box.x2 = mediaBox->x2 - ky * sliceY;
+ }
+ box.y1 = mediaBox->y1 + kx * sliceX;
+ box.y2 = mediaBox->y1 + kx * (sliceX + sliceW);
+ } else if (rotate == 180) {
+ box.x1 = mediaBox->x2 - kx * (sliceX + sliceW);
+ box.x2 = mediaBox->x2 - kx * sliceX;
+ if (out->upsideDown()) {
+ box.y1 = mediaBox->y1 + ky * sliceY;
+ box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
+ } else {
+ box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
+ box.y2 = mediaBox->y2 - ky * sliceY;
+ }
+ } else if (rotate == 270) {
+ if (out->upsideDown()) {
+ box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
+ box.x2 = mediaBox->x2 - ky * sliceY;
+ } else {
+ box.x1 = mediaBox->x1 + ky * sliceY;
+ box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
+ }
+ box.y1 = mediaBox->y2 - kx * (sliceX + sliceW);
+ box.y2 = mediaBox->y2 - kx * sliceX;
+ } else {
+ box.x1 = mediaBox->x1 + kx * sliceX;
+ box.x2 = mediaBox->x1 + kx * (sliceX + sliceW);
+ if (out->upsideDown()) {
+ box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
+ box.y2 = mediaBox->y2 - ky * sliceY;
+ } else {
+ box.y1 = mediaBox->y1 + ky * sliceY;
+ box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
+ }
+ }
+ } else {
+ box = *mediaBox;
+ }
cropBox = getCropBox();
- if (printCommands) {
+ if (globalParams->getPrintCommands()) {
printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
- box->x1, box->y1, box->x2, box->y2);
+ box.x1, box.y1, box.x2, box.y2);
if (isCropped()) {
printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
@@ -238,35 +310,33 @@ void Page::display(OutputDev *out, double dpi, int rotate,
printf("***** Rotate = %d\n", attrs->getRotate());
}
- rotate += getRotate();
- if (rotate >= 360) {
- rotate -= 360;
- } else if (rotate < 0) {
- rotate += 360;
- }
gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
- dpi, box, isCropped(), cropBox, rotate, printCommands);
+ hDPI, vDPI, &box, crop && isCropped(), cropBox, rotate,
+ abortCheckCbk, abortCheckCbkData);
contents.fetch(xref, &obj);
if (!obj.isNull()) {
+ gfx->saveState();
gfx->display(&obj);
+ gfx->restoreState();
}
obj.free();
// draw links
if (links) {
+ gfx->saveState();
for (i = 0; i < links->getNumLinks(); ++i) {
link = links->getLink(i);
out->drawLink(link, catalog);
}
+ gfx->restoreState();
out->dump();
}
// draw non-link annotations
- //~ need to reset CTM ???
annotList = new Annots(xref, annots.fetch(xref, &obj));
obj.free();
if (annotList->getNumAnnots() > 0) {
- if (printCommands) {
+ if (globalParams->getPrintCommands()) {
printf("***** Annotations\n");
}
for (i = 0; i < annotList->getNumAnnots(); ++i) {
diff --git a/pdf2swf/xpdf/Page.h b/pdf2swf/xpdf/Page.h
index 7207b206..2376cb49 100644
--- a/pdf2swf/xpdf/Page.h
+++ b/pdf2swf/xpdf/Page.h
@@ -2,14 +2,16 @@
//
// Page.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef PAGE_H
#define PAGE_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -23,8 +25,14 @@ class Catalog;
//------------------------------------------------------------------------
-struct PDFRectangle {
+class PDFRectangle {
+public:
double x1, y1, x2, y2;
+
+ PDFRectangle() { x1 = y1 = x2 = y2 = 0; }
+ PDFRectangle(double x1A, double y1A, double x2A, double y2A)
+ { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
+ GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
};
//------------------------------------------------------------------------
@@ -97,8 +105,7 @@ class Page {
public:
// Constructor.
- Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
- GBool printCommandsA);
+ Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA);
// Destructor.
~Page();
@@ -134,8 +141,19 @@ public:
Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
// Display a page.
- void display(OutputDev *out, double dpi, int rotate,
- Links *links, Catalog *catalog);
+ void display(OutputDev *out, double hDPI, double vDPI,
+ int rotate, GBool crop,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display part of a page.
+ void displaySlice(OutputDev *out, double hDPI, double vDPI,
+ int rotate, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
private:
@@ -144,7 +162,6 @@ private:
PageAttrs *attrs; // page attributes
Object annots; // annotations array
Object contents; // page contents
- GBool printCommands; // print the drawing commands (for debugging)
GBool ok; // true if page is valid
};
diff --git a/pdf2swf/xpdf/Parser.cc b/pdf2swf/xpdf/Parser.cc
index 4df53c98..0aa66d32 100644
--- a/pdf2swf/xpdf/Parser.cc
+++ b/pdf2swf/xpdf/Parser.cc
@@ -2,15 +2,16 @@
//
// Parser.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
@@ -88,8 +89,10 @@ Object *Parser::getObj(Object *obj) {
} else {
key = copyString(buf1.getName());
shift();
- if (buf1.isEOF() || buf1.isError())
+ if (buf1.isEOF() || buf1.isError()) {
+ gfree(key);
break;
+ }
#ifndef NO_DECRYPTION
obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
#else
@@ -173,10 +176,16 @@ Stream *Parser::makeStream(Object *dict) {
}
// check for length in damaged file
- if (xref->getStreamEnd(pos, &endPos)) {
+ if (xref && xref->getStreamEnd(pos, &endPos)) {
length = endPos - pos;
}
+ // in badly damaged PDF files, we can run off the end of the input
+ // stream immediately after the "stream" token
+ if (!lexer->getStream()) {
+ return NULL;
+ }
+
// make base stream
str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue,
length, dict);
@@ -190,17 +199,25 @@ Stream *Parser::makeStream(Object *dict) {
// refill token buffers and check for 'endstream'
shift(); // kill '>>'
shift(); // kill 'stream'
- if (buf1.isCmd("endstream"))
+ if (buf1.isCmd("endstream")) {
shift();
- else
+ } else {
error(getPos(), "Missing 'endstream'");
+ str->ignoreLength();
+ }
return str;
}
void Parser::shift() {
if (inlineImg > 0) {
- ++inlineImg;
+ if (inlineImg < 2) {
+ ++inlineImg;
+ } else {
+ // in a damaged content stream, if 'ID' shows up in the middle
+ // of a dictionary, we need to reset
+ inlineImg = 0;
+ }
} else if (buf2.isCmd("ID")) {
lexer->skipChar(); // skip char after 'ID' command
inlineImg = 1;
diff --git a/pdf2swf/xpdf/Parser.h b/pdf2swf/xpdf/Parser.h
index c11475bf..3bc3ab27 100644
--- a/pdf2swf/xpdf/Parser.h
+++ b/pdf2swf/xpdf/Parser.h
@@ -2,14 +2,16 @@
//
// Parser.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef PARSER_H
#define PARSER_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
diff --git a/pdf2swf/xpdf/Stream-CCITT.h b/pdf2swf/xpdf/Stream-CCITT.h
index f5a77b0b..c4458fe7 100644
--- a/pdf2swf/xpdf/Stream-CCITT.h
+++ b/pdf2swf/xpdf/Stream-CCITT.h
@@ -4,7 +4,7 @@
//
// Tables for CCITT Fax decoding.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
diff --git a/pdf2swf/xpdf/Stream.cc b/pdf2swf/xpdf/Stream.cc
index c47c5af0..49bbb461 100644
--- a/pdf2swf/xpdf/Stream.cc
+++ b/pdf2swf/xpdf/Stream.cc
@@ -2,22 +2,21 @@
//
// Stream.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#ifndef WIN32
#include <unistd.h>
-#else
-extern "C" int unlink(char *filename);
#endif
#include <string.h>
#include <ctype.h>
@@ -30,6 +29,8 @@ extern "C" int unlink(char *filename);
#include "Decrypt.h"
#endif
#include "Stream.h"
+#include "JBIG2Stream.h"
+#include "JPXStream.h"
#include "Stream-CCITT.h"
#ifdef __DJGPP__
@@ -37,9 +38,6 @@ static GBool setDJSYSFLAGS = gFalse;
#endif
#ifdef VMS
-#if (__VMS_VER < 70000000)
-extern "C" int unlink(char *filename);
-#endif
#ifdef __GNUC__
#define SEEK_SET 0
#define SEEK_CUR 1
@@ -47,10 +45,6 @@ extern "C" int unlink(char *filename);
#endif
#endif
-#ifdef MACOS
-#include "StuffItEngineLib.h"
-#endif
-
//------------------------------------------------------------------------
// Stream (base class)
//------------------------------------------------------------------------
@@ -91,7 +85,7 @@ char *Stream::getLine(char *buf, int size) {
return buf;
}
-GString *Stream::getPSFilter(char *indent) {
+GString *Stream::getPSFilter(int psLevel, char *indent) {
return new GString();
}
@@ -147,7 +141,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
int encoding;
GBool endOfLine, byteAlign, endOfBlock, black;
int columns, rows;
- Object obj;
+ Object globals, obj;
if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
str = new ASCIIHexStream(str);
@@ -257,6 +251,14 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
obj.free();
}
str = new FlateStream(str, pred, columns, colors, bits);
+ } else if (!strcmp(name, "JBIG2Decode")) {
+ if (params->isDict()) {
+ params->dictLookup("JBIG2Globals", &globals);
+ }
+ str = new JBIG2Stream(str, &globals);
+ globals.free();
+ } else if (!strcmp(name, "JPXDecode")) {
+ str = new JPXStream(str);
} else {
error(getPos(), "Unknown filter '%s'", name);
str = new EOFStream(str);
@@ -340,51 +342,54 @@ void ImageStream::reset() {
}
GBool ImageStream::getPixel(Guchar *pix) {
+ int i;
+
+ if (imgIdx >= nVals) {
+ getLine();
+ imgIdx = 0;
+ }
+ for (i = 0; i < nComps; ++i) {
+ pix[i] = imgLine[imgIdx++];
+ }
+ return gTrue;
+}
+
+Guchar *ImageStream::getLine() {
Gulong buf, bitMask;
int bits;
int c;
int i;
- if (imgIdx >= nVals) {
-
- // read one line of image pixels
- if (nBits == 1) {
- for (i = 0; i < nVals; i += 8) {
- c = str->getChar();
- imgLine[i+0] = (Guchar)((c >> 7) & 1);
- imgLine[i+1] = (Guchar)((c >> 6) & 1);
- imgLine[i+2] = (Guchar)((c >> 5) & 1);
- imgLine[i+3] = (Guchar)((c >> 4) & 1);
- imgLine[i+4] = (Guchar)((c >> 3) & 1);
- imgLine[i+5] = (Guchar)((c >> 2) & 1);
- imgLine[i+6] = (Guchar)((c >> 1) & 1);
- imgLine[i+7] = (Guchar)(c & 1);
- }
- } else if (nBits == 8) {
- for (i = 0; i < nVals; ++i) {
- imgLine[i] = str->getChar();
- }
- } else {
- bitMask = (1 << nBits) - 1;
- buf = 0;
- bits = 0;
- for (i = 0; i < nVals; ++i) {
- if (bits < nBits) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bits += 8;
- }
- imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
- bits -= nBits;
+ if (nBits == 1) {
+ for (i = 0; i < nVals; i += 8) {
+ c = str->getChar();
+ imgLine[i+0] = (Guchar)((c >> 7) & 1);
+ imgLine[i+1] = (Guchar)((c >> 6) & 1);
+ imgLine[i+2] = (Guchar)((c >> 5) & 1);
+ imgLine[i+3] = (Guchar)((c >> 4) & 1);
+ imgLine[i+4] = (Guchar)((c >> 3) & 1);
+ imgLine[i+5] = (Guchar)((c >> 2) & 1);
+ imgLine[i+6] = (Guchar)((c >> 1) & 1);
+ imgLine[i+7] = (Guchar)(c & 1);
+ }
+ } else if (nBits == 8) {
+ for (i = 0; i < nVals; ++i) {
+ imgLine[i] = str->getChar();
+ }
+ } else {
+ bitMask = (1 << nBits) - 1;
+ buf = 0;
+ bits = 0;
+ for (i = 0; i < nVals; ++i) {
+ if (bits < nBits) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bits += 8;
}
+ imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
+ bits -= nBits;
}
-
- // reset to start of line
- imgIdx = 0;
}
-
- for (i = 0; i < nComps; ++i)
- pix[i] = imgLine[imgIdx++];
- return gTrue;
+ return imgLine;
}
void ImageStream::skipLine() {
@@ -448,7 +453,7 @@ GBool StreamPredictor::getNextLine() {
int i, j, k;
// get PNG optimum predictor number
- if (predictor == 15) {
+ if (predictor >= 10) {
if ((curPred = str->getRawChar()) == EOF) {
return gFalse;
}
@@ -465,7 +470,7 @@ GBool StreamPredictor::getNextLine() {
upLeftBuf[1] = upLeftBuf[0];
upLeftBuf[0] = predLine[i];
if ((c = str->getRawChar()) == EOF) {
- break;
+ return gFalse;
}
switch (curPred) {
case 11: // PNG sub
@@ -504,7 +509,6 @@ GBool StreamPredictor::getNextLine() {
}
// apply TIFF (component) predictor
- //~ this is completely untested
if (predictor == 2) {
if (nBits == 1) {
inBuf = predLine[pixBytes - 1];
@@ -579,7 +583,10 @@ Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
}
void FileStream::reset() {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ savePos = (Guint)ftello(f);
+ fseeko(f, start, SEEK_SET);
+#elif HAVE_FSEEK64
savePos = (Guint)ftell64(f);
fseek64(f, start, SEEK_SET);
#else
@@ -597,7 +604,9 @@ void FileStream::reset() {
void FileStream::close() {
if (saved) {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, savePos, SEEK_SET);
+#elif HAVE_FSEEK64
fseek64(f, savePos, SEEK_SET);
#else
fseek(f, savePos, SEEK_SET);
@@ -641,14 +650,19 @@ void FileStream::setPos(Guint pos, int dir) {
Guint size;
if (dir >= 0) {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, pos, SEEK_SET);
+#elif HAVE_FSEEK64
fseek64(f, pos, SEEK_SET);
#else
fseek(f, pos, SEEK_SET);
#endif
bufPos = pos;
} else {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, 0, SEEK_END);
+ size = (Guint)ftello(f);
+#elif HAVE_FSEEK64
fseek64(f, 0, SEEK_END);
size = (Guint)ftell64(f);
#else
@@ -661,7 +675,10 @@ void FileStream::setPos(Guint pos, int dir) {
//~ work around a bug in cygwin's implementation of fseek
rewind(f);
#endif
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftello(f);
+#elif HAVE_FSEEK64
fseek64(f, -(int)pos, SEEK_END);
bufPos = (Guint)ftell64(f);
#else
@@ -682,13 +699,14 @@ void FileStream::moveStart(int delta) {
// MemStream
//------------------------------------------------------------------------
-MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
+MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
BaseStream(dictA) {
buf = bufA;
- needFree = gFalse;
+ start = startA;
length = lengthA;
- bufEnd = buf + length;
- bufPtr = buf;
+ bufEnd = buf + start + length;
+ bufPtr = buf + start;
+ needFree = gFalse;
}
MemStream::~MemStream() {
@@ -697,20 +715,22 @@ MemStream::~MemStream() {
}
}
-Stream *MemStream::makeSubStream(Guint start, GBool limited,
+Stream *MemStream::makeSubStream(Guint startA, GBool limited,
Guint lengthA, Object *dictA) {
+ MemStream *subStr;
Guint newLength;
- if (!limited || start + lengthA > length) {
- newLength = length - start;
+ if (!limited || startA + lengthA > start + length) {
+ newLength = start + length - startA;
} else {
newLength = lengthA;
}
- return new MemStream(buf + start, newLength, dictA);
+ subStr = new MemStream(buf, startA, newLength, dictA);
+ return subStr;
}
void MemStream::reset() {
- bufPtr = buf;
+ bufPtr = buf + start;
#ifndef NO_DECRYPTION
if (decrypt) {
decrypt->reset();
@@ -722,24 +742,24 @@ void MemStream::close() {
}
void MemStream::setPos(Guint pos, int dir) {
+ Guint i;
+
if (dir >= 0) {
- if (pos > length) {
- bufPtr = bufEnd;
- } else {
- bufPtr = buf + pos;
- }
+ i = pos;
} else {
- if (pos > length) {
- bufPtr = buf;
- } else {
- bufPtr = bufEnd - pos;
- }
+ i = start + length - pos;
+ }
+ if (i < start) {
+ i = start;
+ } else if (i > start + length) {
+ i = start + length;
}
+ bufPtr = buf + i;
}
void MemStream::moveStart(int delta) {
- buf += delta;
- bufPtr = buf;
+ start += delta;
+ bufPtr = buf + start;
}
#ifndef NO_DECRYPTION
@@ -750,12 +770,13 @@ void MemStream::doDecryption(Guchar *fileKey, int keyLength,
this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
if (decrypt) {
- newBuf = (char *)gmalloc(bufEnd - buf);
- for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
+ newBuf = (char *)gmalloc(length);
+ for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
*q = (char)decrypt->decryptByte((Guchar)*p);
}
- bufEnd = newBuf + (bufEnd - buf);
- bufPtr = newBuf + (bufPtr - buf);
+ bufEnd = newBuf + length;
+ bufPtr = newBuf + (bufPtr - (buf + start));
+ start = 0;
buf = newBuf;
needFree = gTrue;
}
@@ -766,20 +787,38 @@ void MemStream::doDecryption(Guchar *fileKey, int keyLength,
// EmbedStream
//------------------------------------------------------------------------
-EmbedStream::EmbedStream(Stream *strA, Object *dictA):
+EmbedStream::EmbedStream(Stream *strA, Object *dictA,
+ GBool limitedA, Guint lengthA):
BaseStream(dictA) {
str = strA;
+ limited = limitedA;
+ length = lengthA;
}
EmbedStream::~EmbedStream() {
}
-Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
- Guint length, Object *dictA) {
+Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
+ Guint lengthA, Object *dictA) {
error(-1, "Internal: called makeSubStream() on EmbedStream");
return NULL;
}
+int EmbedStream::getChar() {
+ if (limited && !length) {
+ return EOF;
+ }
+ --length;
+ return str->getChar();
+}
+
+int EmbedStream::lookChar() {
+ if (limited && !length) {
+ return EOF;
+ }
+ return str->lookChar();
+}
+
void EmbedStream::setPos(Guint pos, int dir) {
error(-1, "Internal: called setPos() on EmbedStream");
}
@@ -866,10 +905,13 @@ int ASCIIHexStream::lookChar() {
return buf;
}
-GString *ASCIIHexStream::getPSFilter(char *indent) {
+GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
GString *s;
- if (!(s = str->getPSFilter(indent))) {
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("/ASCIIHexDecode filter\n");
@@ -944,10 +986,13 @@ int ASCII85Stream::lookChar() {
return b[index];
}
-GString *ASCII85Stream::getPSFilter(char *indent) {
+GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
GString *s;
- if (!(s = str->getPSFilter(indent))) {
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("/ASCII85Decode filter\n");
@@ -971,21 +1016,12 @@ LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
pred = NULL;
}
early = earlyA;
- zPipe = NULL;
- bufPtr = bufEnd = buf;
+ eof = gFalse;
+ inputBits = 0;
+ clearTable();
}
LZWStream::~LZWStream() {
- if (zPipe) {
-#ifdef HAVE_POPEN
- pclose(zPipe);
-#else
- fclose(zPipe);
-#endif
- zPipe = NULL;
- unlink(zName->getCString());
- delete zName;
- }
if (pred) {
delete pred;
}
@@ -996,275 +1032,149 @@ int LZWStream::getChar() {
if (pred) {
return pred->getChar();
}
- return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex++];
}
int LZWStream::lookChar() {
if (pred) {
return pred->lookChar();
}
- return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex];
}
int LZWStream::getRawChar() {
- return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex++];
}
void LZWStream::reset() {
- FILE *f;
- GString *zCmd;
-
- //----- close old LZW stream
- if (zPipe) {
-#ifdef HAVE_POPEN
- pclose(zPipe);
-#else
- fclose(zPipe);
-#endif
- zPipe = NULL;
- unlink(zName->getCString());
- delete zName;
- }
+ str->reset();
+ eof = gFalse;
+ inputBits = 0;
+ clearTable();
+}
- //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
- // to run gzip
-#if __DJGPP__
- if (!setDJSYSFLAGS) {
- setenv("DJSYSFLAGS", "0x0002", 0);
- setDJSYSFLAGS = gTrue;
- }
-#endif
+GBool LZWStream::processNextCode() {
+ int code;
+ int nextLength;
+ int i, j;
- //----- create the .Z file
- if (!openTempFile(&zName, &f, "wb", ".Z")) {
- error(getPos(), "Couldn't create temporary file for LZW stream");
- return;
+ // check for EOF
+ if (eof) {
+ return gFalse;
}
- dumpFile(f);
- fclose(f);
- //----- execute uncompress / gzip
-#ifdef WIN32
- zCmd = new GString("c:\\swftools\\gzip.exe");
-#else
- zCmd = new GString(uncompressCmd);
-#endif
- zCmd->append(' ');
- zCmd->append(zName);
-#if defined(MACOS)
- long magicCookie;
- // first we open the engine up
- OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
- // if we found it - let's use it!
- if (!err && magicCookie) {
- // make sure we have the correct version of the Engine
- if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
- FSSpec myFSS;
- Str255 pName;
- strcpy((char *)pName, zName->getCString());
- c2pstr((char *)pName);
- FSMakeFSSpec(0, 0, pName, &myFSS);
- short ftype = DetermineFileType(magicCookie, &myFSS);
- OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
- NULL, NULL, kCreateFolderNever,
- kDeleteOriginal, kTextConvertSmart);
- }
- }
-#elif defined(HAVE_POPEN)
- if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
- error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
- unlink(zName->getCString());
- delete zName;
- return;
- }
-#else // HAVE_POPEN
- if (!executeCommand(zCmd->getCString())) {
- error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
- unlink(zName->getCString());
- delete zName;
- return;
+ // check for eod and clear-table codes
+ start:
+ code = getCode();
+ if (code == EOF || code == 257) {
+ eof = gTrue;
+ return gFalse;
}
- zName->del(zName->getLength() - 2, 2);
- if (!(zPipe = fopen(zName->getCString(), "rb"))) {
- error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
- unlink(zName->getCString());
- delete zName;
- return;
+ if (code == 256) {
+ clearTable();
+ goto start;
+ }
+ if (nextCode >= 4097) {
+ error(getPos(), "Bad LZW stream - expected clear-table code");
+ clearTable();
+ }
+
+ // process the next code
+ nextLength = seqLength + 1;
+ if (code < 256) {
+ seqBuf[0] = code;
+ seqLength = 1;
+ } else if (code < nextCode) {
+ seqLength = table[code].length;
+ for (i = seqLength - 1, j = code; i > 0; --i) {
+ seqBuf[i] = table[j].tail;
+ j = table[j].head;
+ }
+ seqBuf[0] = j;
+ } else if (code == nextCode) {
+ seqBuf[seqLength] = newChar;
+ ++seqLength;
+ } else {
+ error(getPos(), "Bad LZW stream - unexpected code");
+ eof = gTrue;
+ return gFalse;
}
-#endif // HAVE_POPEN
-
- //----- clean up
- delete zCmd;
+ newChar = seqBuf[0];
+ if (first) {
+ first = gFalse;
+ } else {
+ table[nextCode].length = nextLength;
+ table[nextCode].head = prevCode;
+ table[nextCode].tail = newChar;
+ ++nextCode;
+ if (nextCode + early == 512)
+ nextBits = 10;
+ else if (nextCode + early == 1024)
+ nextBits = 11;
+ else if (nextCode + early == 2048)
+ nextBits = 12;
+ }
+ prevCode = code;
+
+ // reset buffer
+ seqIndex = 0;
- //----- initialize buffer
- bufPtr = bufEnd = buf;
+ return gTrue;
}
-void LZWStream::dumpFile(FILE *f) {
- int outCodeBits; // size of output code
- int outBits; // max output code
- int outBuf[8]; // output buffer
- int outData; // temporary output buffer
- int inCode, outCode; // input and output codes
- int nextCode; // next code index
- GBool eof; // set when EOF is reached
- GBool clear; // set if table needs to be cleared
- GBool first; // indicates first code word after clear
- int i, j;
-
- str->reset();
-
- // magic number
- fputc(0x1f, f);
- fputc(0x9d, f);
-
- // max code length, block mode flag
- fputc(0x8c, f);
-
- // init input side
- inCodeBits = 9;
- inputBuf = 0;
- inputBits = 0;
- eof = gFalse;
-
- // init output side
- outCodeBits = 9;
-
- // clear table
- first = gTrue;
+void LZWStream::clearTable() {
nextCode = 258;
-
- clear = gFalse;
- do {
- for (i = 0; i < 8; ++i) {
- // check for table overflow
- if (nextCode + early > 0x1001) {
- inCode = 256;
-
- // read input code
- } else {
- do {
- inCode = getCode();
- if (inCode == EOF) {
- eof = gTrue;
- inCode = 0;
- }
- } while (first && inCode == 256);
- }
-
- // compute output code
- if (inCode < 256) {
- outCode = inCode;
- } else if (inCode == 256) {
- outCode = 256;
- clear = gTrue;
- } else if (inCode == 257) {
- outCode = 0;
- eof = gTrue;
- } else {
- outCode = inCode - 1;
- }
- outBuf[i] = outCode;
-
- // next code index
- if (first)
- first = gFalse;
- else
- ++nextCode;
-
- // check input code size
- if (nextCode + early == 0x200)
- inCodeBits = 10;
- else if (nextCode + early == 0x400) {
- inCodeBits = 11;
- } else if (nextCode + early == 0x800) {
- inCodeBits = 12;
- }
-
- // check for eof/clear
- if (eof)
- break;
- if (clear) {
- i = 8;
- break;
- }
- }
-
- // write output block
- outData = 0;
- outBits = 0;
- j = 0;
- while (j < i || outBits > 0) {
- if (outBits < 8 && j < i) {
- outData = outData | (outBuf[j++] << outBits);
- outBits += outCodeBits;
- }
- fputc(outData & 0xff, f);
- outData >>= 8;
- outBits -= 8;
- }
-
- // check output code size
- if (nextCode - 1 == 512 ||
- nextCode - 1 == 1024 ||
- nextCode - 1 == 2048 ||
- nextCode - 1 == 4096) {
- outCodeBits = inCodeBits;
- }
-
- // clear table if necessary
- if (clear) {
- inCodeBits = 9;
- outCodeBits = 9;
- first = gTrue;
- nextCode = 258;
- clear = gFalse;
- }
- } while (!eof);
+ nextBits = 9;
+ seqIndex = seqLength = 0;
+ first = gTrue;
}
int LZWStream::getCode() {
int c;
int code;
- while (inputBits < inCodeBits) {
+ while (inputBits < nextBits) {
if ((c = str->getChar()) == EOF)
return EOF;
inputBuf = (inputBuf << 8) | (c & 0xff);
inputBits += 8;
}
- code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
- inputBits -= inCodeBits;
+ code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
+ inputBits -= nextBits;
return code;
}
-GBool LZWStream::fillBuf() {
- int n;
-
- if (!zPipe)
- return gFalse;
- if ((n = fread(buf, 1, 256, zPipe)) < 256) {
-#ifdef HAVE_POPEN
- pclose(zPipe);
-#else
- fclose(zPipe);
-#endif
- zPipe = NULL;
- unlink(zName->getCString());
- delete zName;
- }
- bufPtr = buf;
- bufEnd = buf + n;
- return n > 0;
-}
-
-GString *LZWStream::getPSFilter(char *indent) {
+GString *LZWStream::getPSFilter(int psLevel, char *indent) {
GString *s;
- if (pred) {
+ if (psLevel < 2 || pred) {
return NULL;
}
- if (!(s = str->getPSFilter(indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("/LZWDecode filter\n");
@@ -1295,10 +1205,13 @@ void RunLengthStream::reset() {
eof = gFalse;
}
-GString *RunLengthStream::getPSFilter(char *indent) {
+GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
GString *s;
- if (!(s = str->getPSFilter(indent))) {
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("/RunLengthDecode filter\n");
@@ -1371,7 +1284,7 @@ CCITTFaxStream::~CCITTFaxStream() {
}
void CCITTFaxStream::reset() {
- int n;
+ short code1;
str->reset();
eof = gFalse;
@@ -1383,16 +1296,13 @@ void CCITTFaxStream::reset() {
a0 = 1;
buf = EOF;
- // get initial end-of-line marker and 2D encoding tag
- if (endOfBlock) {
- if (lookBits(12) == 0x001) {
- eatBits(12);
- }
- } else {
- for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
- if (n == 11 && lookBits(12) == 0x001) {
- eatBits(12);
- }
+ // skip any initial zero bits and end-of-line marker, and get the 2D
+ // encoding tag
+ while ((code1 = lookBits(12)) == 0) {
+ eatBits(1);
+ }
+ if (code1 == 0x001) {
+ eatBits(12);
}
if (encoding > 0) {
nextLine2D = !lookBits(1);
@@ -1403,10 +1313,7 @@ void CCITTFaxStream::reset() {
int CCITTFaxStream::lookChar() {
short code1, code2, code3;
int a0New;
-#if 0
- GBool err;
-#endif
- GBool gotEOL;
+ GBool err, gotEOL;
int ret;
int bits, i;
@@ -1416,9 +1323,7 @@ int CCITTFaxStream::lookChar() {
}
// read the next row
-#if 0
err = gFalse;
-#endif
if (codingLine[a0] >= columns) {
// 2-D encoding
@@ -1455,12 +1360,14 @@ int CCITTFaxStream::lookChar() {
code2 += code3 = getWhiteCode();
} while (code3 >= 64);
}
- codingLine[a0 + 1] = a0New + code1;
- ++a0;
- a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
- ++a0;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
- b1 += 2;
+ if (code1 > 0 || code2 > 0) {
+ codingLine[a0 + 1] = a0New + code1;
+ ++a0;
+ a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
+ ++a0;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ }
break;
case twoDimVert0:
a0New = codingLine[++a0] = refLine[b1];
@@ -1518,13 +1425,8 @@ int CCITTFaxStream::lookChar() {
return EOF;
default:
error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
-#if 0
err = gTrue;
break;
-#else
- eof = gTrue;
- return EOF;
-#endif
}
} while (codingLine[a0] < columns);
@@ -1553,9 +1455,12 @@ int CCITTFaxStream::lookChar() {
if (codingLine[a0] != columns) {
error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
-#if 0
+ // force the row to be the correct length
+ while (codingLine[a0] > columns) {
+ --a0;
+ }
+ codingLine[++a0] = columns;
err = gTrue;
-#endif
}
// byte-align the row
@@ -1611,30 +1516,25 @@ int CCITTFaxStream::lookChar() {
}
eof = gTrue;
}
- }
-#if 0
- // This looks for an end-of-line marker after an error, however
- // some (most?) CCITT streams in PDF files don't use end-of-line
- // markers, and the just-plow-on technique works better in those
- // cases.
- else if (err) {
+ // look for an end-of-line marker after an error -- we only do
+ // this if we know the stream contains end-of-line markers because
+ // the "just plow on" technique tends to work better otherwise
+ } else if (err && endOfLine) {
do {
if (code1 == EOF) {
eof = gTrue;
return EOF;
}
eatBits(1);
- code1 = look13Bits();
+ code1 = lookBits(13);
} while ((code1 >> 1) != 0x001);
eatBits(12);
- codingLine[++a0] = columns;
if (encoding > 0) {
eatBits(1);
nextLine2D = !(code1 & 1);
}
}
-#endif
a0 = 0;
outputBits = codingLine[1] - codingLine[0];
@@ -1845,11 +1745,14 @@ short CCITTFaxStream::lookBits(int n) {
return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
}
-GString *CCITTFaxStream::getPSFilter(char *indent) {
+GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
GString *s;
char s1[50];
- if (!(s = str->getPSFilter(indent))) {
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("<< ");
@@ -1888,7 +1791,6 @@ GBool CCITTFaxStream::isBinary(GBool last) {
//------------------------------------------------------------------------
// IDCT constants (20.12 fixed point format)
-#ifndef FP_IDCT
#define dctCos1 4017 // cos(pi/16)
#define dctSin1 799 // sin(pi/16)
#define dctCos3 3406 // cos(3*pi/16)
@@ -1897,19 +1799,6 @@ GBool CCITTFaxStream::isBinary(GBool last) {
#define dctSin6 3784 // sin(6*pi/16)
#define dctSqrt2 5793 // sqrt(2)
#define dctSqrt1d2 2896 // sqrt(2) / 2
-#endif
-
-// IDCT constants
-#ifdef FP_IDCT
-#define dctCos1 0.98078528 // cos(pi/16)
-#define dctSin1 0.19509032 // sin(pi/16)
-#define dctCos3 0.83146961 // cos(3*pi/16)
-#define dctSin3 0.55557023 // sin(3*pi/16)
-#define dctCos6 0.38268343 // cos(6*pi/16)
-#define dctSin6 0.92387953 // sin(6*pi/16)
-#define dctSqrt2 1.41421356 // sqrt(2)
-#define dctSqrt1d2 0.70710678 // sqrt(2) / 2
-#endif
// color conversion parameters (16.16 fixed point format)
#define dctCrToR 91881 // 1.4020
@@ -1945,14 +1834,18 @@ DCTStream::DCTStream(Stream *strA):
FilterStream(strA) {
int i, j;
+ progressive = interleaved = gFalse;
width = height = 0;
mcuWidth = mcuHeight = 0;
numComps = 0;
comp = 0;
x = y = dy = 0;
- for (i = 0; i < 4; ++i)
- for (j = 0; j < 32; ++j)
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 32; ++j) {
rowBuf[i][j] = NULL;
+ }
+ frameBuf[i] = NULL;
+ }
if (!dctClipInit) {
for (i = -256; i < 0; ++i)
@@ -1969,53 +1862,178 @@ DCTStream::~DCTStream() {
int i, j;
delete str;
- for (i = 0; i < numComps; ++i)
- for (j = 0; j < mcuHeight; ++j)
- gfree(rowBuf[i][j]);
+ if (progressive || !interleaved) {
+ for (i = 0; i < numComps; ++i) {
+ gfree(frameBuf[i]);
+ }
+ } else {
+ for (i = 0; i < numComps; ++i) {
+ for (j = 0; j < mcuHeight; ++j) {
+ gfree(rowBuf[i][j]);
+ }
+ }
+ }
}
void DCTStream::reset() {
+ int minHSample, minVSample;
+ int i, j;
+
str->reset();
+
+ progressive = interleaved = gFalse;
+ width = height = 0;
+ numComps = 0;
+ numQuantTables = 0;
+ numDCHuffTables = 0;
+ numACHuffTables = 0;
+ colorXform = 0;
+ gotJFIFMarker = gFalse;
+ gotAdobeMarker = gFalse;
+ restartInterval = 0;
+
if (!readHeader()) {
y = height;
return;
}
- restartMarker = 0xd0;
- restart();
+
+ // compute MCU size
+ mcuWidth = minHSample = compInfo[0].hSample;
+ mcuHeight = minVSample = compInfo[0].vSample;
+ for (i = 1; i < numComps; ++i) {
+ if (compInfo[i].hSample < minHSample)
+ minHSample = compInfo[i].hSample;
+ if (compInfo[i].vSample < minVSample)
+ minVSample = compInfo[i].vSample;
+ if (compInfo[i].hSample > mcuWidth)
+ mcuWidth = compInfo[i].hSample;
+ if (compInfo[i].vSample > mcuHeight)
+ mcuHeight = compInfo[i].vSample;
+ }
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].hSample /= minHSample;
+ compInfo[i].vSample /= minVSample;
+ }
+ mcuWidth = (mcuWidth / minHSample) * 8;
+ mcuHeight = (mcuHeight / minVSample) * 8;
+
+ // figure out color transform
+ if (!gotAdobeMarker && numComps == 3) {
+ if (gotJFIFMarker) {
+ colorXform = 1;
+ } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
+ compInfo[2].id == 66) { // ASCII "RGB"
+ colorXform = 0;
+ } else {
+ colorXform = 1;
+ }
+ }
+
+ if (progressive || !interleaved) {
+
+ // allocate a buffer for the whole image
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
+ bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
+ for (i = 0; i < numComps; ++i) {
+ frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
+ memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
+ }
+
+ // read the image data
+ do {
+ restartMarker = 0xd0;
+ restart();
+ readScan();
+ } while (readHeader());
+
+ // decode
+ decodeImage();
+
+ // initialize counters
+ comp = 0;
+ x = 0;
+ y = 0;
+
+ } else {
+
+ // allocate a buffer for one row of MCUs
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
+ for (i = 0; i < numComps; ++i) {
+ for (j = 0; j < mcuHeight; ++j) {
+ rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
+ }
+ }
+
+ // initialize counters
+ comp = 0;
+ x = 0;
+ y = 0;
+ dy = mcuHeight;
+
+ restartMarker = 0xd0;
+ restart();
+ }
}
int DCTStream::getChar() {
int c;
- c = lookChar();
- if (c == EOF)
+ if (y >= height) {
return EOF;
- if (++comp == numComps) {
- comp = 0;
- if (++x == width) {
+ }
+ if (progressive || !interleaved) {
+ c = frameBuf[comp][y * bufWidth + x];
+ if (++comp == numComps) {
+ comp = 0;
+ if (++x == width) {
+ x = 0;
+ ++y;
+ }
+ }
+ } else {
+ if (dy >= mcuHeight) {
+ if (!readMCURow()) {
+ y = height;
+ return EOF;
+ }
+ comp = 0;
x = 0;
- ++y;
- ++dy;
+ dy = 0;
+ }
+ c = rowBuf[comp][dy][x];
+ if (++comp == numComps) {
+ comp = 0;
+ if (++x == width) {
+ x = 0;
+ ++y;
+ ++dy;
+ if (y == height) {
+ readTrailer();
+ }
+ }
}
}
- if (y == height)
- readTrailer();
return c;
}
int DCTStream::lookChar() {
- if (y >= height)
+ if (y >= height) {
return EOF;
- if (dy >= mcuHeight) {
- if (!readMCURow()) {
- y = height;
- return EOF;
+ }
+ if (progressive || !interleaved) {
+ return frameBuf[comp][y * bufWidth + x];
+ } else {
+ if (dy >= mcuHeight) {
+ if (!readMCURow()) {
+ y = height;
+ return EOF;
+ }
+ comp = 0;
+ x = 0;
+ dy = 0;
}
- comp = 0;
- x = 0;
- dy = 0;
+ return rowBuf[comp][dy][x];
}
- return rowBuf[comp][dy][x];
}
void DCTStream::restart() {
@@ -2023,12 +2041,16 @@ void DCTStream::restart() {
inputBits = 0;
restartCtr = restartInterval;
- for (i = 0; i < numComps; ++i)
+ for (i = 0; i < numComps; ++i) {
compInfo[i].prevDC = 0;
+ }
+ eobRun = 0;
}
+// Read one row of MCUs from a sequential JPEG stream.
GBool DCTStream::readMCURow() {
- Guchar data[64];
+ int data1[64];
+ Guchar data2[64];
Guchar *p1, *p2;
int pY, pCb, pCr, pR, pG, pB;
int h, v, horiz, vert, hSub, vSub;
@@ -2059,36 +2081,38 @@ GBool DCTStream::readMCURow() {
vSub = vert / 8;
for (y2 = 0; y2 < mcuHeight; y2 += vert) {
for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
- if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
- &acHuffTables[compInfo[cc].acHuffTable],
- quantTables[compInfo[cc].quantTable],
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
&compInfo[cc].prevDC,
- data))
+ data1)) {
return gFalse;
+ }
+ transformDataUnit(quantTables[compInfo[cc].quantTable],
+ data1, data2);
if (hSub == 1 && vSub == 1) {
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
p1 = &rowBuf[cc][y2+y3][x1+x2];
- p1[0] = data[i];
- p1[1] = data[i+1];
- p1[2] = data[i+2];
- p1[3] = data[i+3];
- p1[4] = data[i+4];
- p1[5] = data[i+5];
- p1[6] = data[i+6];
- p1[7] = data[i+7];
+ p1[0] = data2[i];
+ p1[1] = data2[i+1];
+ p1[2] = data2[i+2];
+ p1[3] = data2[i+3];
+ p1[4] = data2[i+4];
+ p1[5] = data2[i+5];
+ p1[6] = data2[i+6];
+ p1[7] = data2[i+7];
}
} else if (hSub == 2 && vSub == 2) {
for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
p1 = &rowBuf[cc][y2+y3][x1+x2];
p2 = &rowBuf[cc][y2+y3+1][x1+x2];
- p1[0] = p1[1] = p2[0] = p2[1] = data[i];
- p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
- p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
- p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
- p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
- p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
- p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
- p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
+ p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
+ p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
+ p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
+ p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
+ p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
+ p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
+ p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
+ p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
}
} else {
i = 0;
@@ -2096,7 +2120,7 @@ GBool DCTStream::readMCURow() {
for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
for (y5 = 0; y5 < vSub; ++y5)
for (x5 = 0; x5 < hSub; ++x5)
- rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
+ rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
++i;
}
}
@@ -2144,71 +2168,469 @@ GBool DCTStream::readMCURow() {
return gTrue;
}
-// This IDCT algorithm is taken from:
-// 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.
-// The stage numbers mentioned in the comments refer to Figure 1 in this
-// paper.
-#ifndef FP_IDCT
+// Read one scan from a progressive or non-interleaved JPEG stream.
+void DCTStream::readScan() {
+ int data[64];
+ int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
+ int h, v, horiz, vert, vSub;
+ int *p1;
+ int c;
+
+ if (scanInfo.numComps == 1) {
+ for (cc = 0; cc < numComps; ++cc) {
+ if (scanInfo.comp[cc]) {
+ break;
+ }
+ }
+ dx1 = mcuWidth / compInfo[cc].hSample;
+ dy1 = mcuHeight / compInfo[cc].vSample;
+ } else {
+ dx1 = mcuWidth;
+ dy1 = mcuHeight;
+ }
+
+ for (y1 = 0; y1 < height; y1 += dy1) {
+ for (x1 = 0; x1 < width; x1 += dx1) {
+
+ // deal with restart marker
+ if (restartInterval > 0 && restartCtr == 0) {
+ c = readMarker();
+ if (c != restartMarker) {
+ error(getPos(), "Bad DCT data: incorrect restart marker");
+ return;
+ }
+ if (++restartMarker == 0xd8) {
+ restartMarker = 0xd0;
+ }
+ restart();
+ }
+
+ // read one MCU
+ for (cc = 0; cc < numComps; ++cc) {
+ if (!scanInfo.comp[cc]) {
+ continue;
+ }
+
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < dy1; y2 += vert) {
+ for (x2 = 0; x2 < dx1; x2 += horiz) {
+
+ // pull out the current values
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ data[i] = p1[0];
+ data[i+1] = p1[1];
+ data[i+2] = p1[2];
+ data[i+3] = p1[3];
+ data[i+4] = p1[4];
+ data[i+5] = p1[5];
+ data[i+6] = p1[6];
+ data[i+7] = p1[7];
+ p1 += bufWidth * vSub;
+ }
+
+ // read one data unit
+ if (progressive) {
+ if (!readProgressiveDataUnit(
+ &dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data)) {
+ return;
+ }
+ } else {
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data)) {
+ return;
+ }
+ }
+
+ // add the data unit into frameBuf
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1[0] = data[i];
+ p1[1] = data[i+1];
+ p1[2] = data[i+2];
+ p1[3] = data[i+3];
+ p1[4] = data[i+4];
+ p1[5] = data[i+5];
+ p1[6] = data[i+6];
+ p1[7] = data[i+7];
+ p1 += bufWidth * vSub;
+ }
+ }
+ }
+ }
+ --restartCtr;
+ }
+ }
+}
+
+// Read one data unit from a sequential JPEG stream.
GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
DCTHuffTable *acHuffTable,
- Guchar quantTable[64], int *prevDC,
- Guchar data[64]) {
- int tmp1[64];
- int v0, v1, v2, v3, v4, v5, v6, v7, t;
+ int *prevDC, int data[64]) {
int run, size, amp;
int c;
int i, j;
- // Huffman decode and dequantize
- size = readHuffSym(dcHuffTable);
- if (size == 9999)
+ if ((size = readHuffSym(dcHuffTable)) == 9999) {
return gFalse;
+ }
if (size > 0) {
- amp = readAmp(size);
- if (amp == 9999)
+ if ((amp = readAmp(size)) == 9999) {
return gFalse;
+ }
} else {
amp = 0;
}
- tmp1[0] = (*prevDC += amp) * quantTable[0];
- for (i = 1; i < 64; ++i)
- tmp1[i] = 0;
+ data[0] = *prevDC += amp;
+ for (i = 1; i < 64; ++i) {
+ data[i] = 0;
+ }
i = 1;
while (i < 64) {
run = 0;
- while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
+ while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
run += 0x10;
- if (c == 9999)
+ }
+ if (c == 9999) {
return gFalse;
+ }
if (c == 0x00) {
break;
} else {
run += (c >> 4) & 0x0f;
size = c & 0x0f;
amp = readAmp(size);
- if (amp == 9999)
+ if (amp == 9999) {
return gFalse;
+ }
i += run;
+ if (i < 64) {
+ j = dctZigZag[i++];
+ data[j] = amp;
+ }
+ }
+ }
+ return gTrue;
+}
+
+// Read one data unit from a sequential JPEG stream.
+GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]) {
+ int run, size, amp, bit, c;
+ int i, j, k;
+
+ // get the DC coefficient
+ i = scanInfo.firstCoeff;
+ if (i == 0) {
+ if (scanInfo.ah == 0) {
+ if ((size = readHuffSym(dcHuffTable)) == 9999) {
+ return gFalse;
+ }
+ if (size > 0) {
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ } else {
+ amp = 0;
+ }
+ data[0] += (*prevDC += amp) << scanInfo.al;
+ } else {
+ if ((bit = readBit()) == 9999) {
+ return gFalse;
+ }
+ data[0] += bit << scanInfo.al;
+ }
+ ++i;
+ }
+ if (scanInfo.lastCoeff == 0) {
+ return gTrue;
+ }
+
+ // check for an EOB run
+ if (eobRun > 0) {
+ while (i <= scanInfo.lastCoeff) {
j = dctZigZag[i++];
- tmp1[j] = amp * quantTable[j];
+ if (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+ --eobRun;
+ return gTrue;
+ }
+
+ // read the AC coefficients
+ while (i <= scanInfo.lastCoeff) {
+ if ((c = readHuffSym(acHuffTable)) == 9999) {
+ return gFalse;
+ }
+
+ // ZRL
+ if (c == 0xf0) {
+ k = 0;
+ while (k < 16) {
+ j = dctZigZag[i++];
+ if (data[j] == 0) {
+ ++k;
+ } else {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+
+ // EOB run
+ } else if ((c & 0x0f) == 0x00) {
+ j = c >> 4;
+ eobRun = 0;
+ for (k = 0; k < j; ++k) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ eobRun = (eobRun << 1) | bit;
+ }
+ eobRun += 1 << j;
+ while (i <= scanInfo.lastCoeff) {
+ j = dctZigZag[i++];
+ if (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+ --eobRun;
+ break;
+
+ // zero run and one AC coefficient
+ } else {
+ run = (c >> 4) & 0x0f;
+ size = c & 0x0f;
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ k = 0;
+ do {
+ j = dctZigZag[i++];
+ while (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ j = dctZigZag[i++];
+ }
+ ++k;
+ } while (k <= run);
+ data[j] = amp << scanInfo.al;
}
}
+ return gTrue;
+}
+
+// Decode a progressive JPEG image.
+void DCTStream::decodeImage() {
+ int dataIn[64];
+ Guchar dataOut[64];
+ Guchar *quantTable;
+ int pY, pCb, pCr, pR, pG, pB;
+ int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
+ int h, v, horiz, vert, hSub, vSub;
+ int *p0, *p1, *p2;
+
+ for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
+ for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
+ for (cc = 0; cc < numComps; ++cc) {
+ quantTable = quantTables[compInfo[cc].quantTable];
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ hSub = horiz / 8;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < mcuHeight; y2 += vert) {
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
+
+ // pull out the coded data unit
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ dataIn[i] = p1[0];
+ dataIn[i+1] = p1[1];
+ dataIn[i+2] = p1[2];
+ dataIn[i+3] = p1[3];
+ dataIn[i+4] = p1[4];
+ dataIn[i+5] = p1[5];
+ dataIn[i+6] = p1[6];
+ dataIn[i+7] = p1[7];
+ p1 += bufWidth * vSub;
+ }
+
+ // transform
+ transformDataUnit(quantTable, dataIn, dataOut);
+
+ // store back into frameBuf, doing replication for
+ // subsampled components
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ if (hSub == 1 && vSub == 1) {
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1[0] = dataOut[i] & 0xff;
+ p1[1] = dataOut[i+1] & 0xff;
+ p1[2] = dataOut[i+2] & 0xff;
+ p1[3] = dataOut[i+3] & 0xff;
+ p1[4] = dataOut[i+4] & 0xff;
+ p1[5] = dataOut[i+5] & 0xff;
+ p1[6] = dataOut[i+6] & 0xff;
+ p1[7] = dataOut[i+7] & 0xff;
+ p1 += bufWidth;
+ }
+ } else if (hSub == 2 && vSub == 2) {
+ p2 = p1 + bufWidth;
+ for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
+ p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
+ p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
+ p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
+ p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
+ p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
+ p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
+ p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
+ p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
+ p1 += bufWidth * 2;
+ p2 += bufWidth * 2;
+ }
+ } else {
+ i = 0;
+ for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
+ for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
+ p2 = p1 + x4;
+ for (y5 = 0; y5 < vSub; ++y5) {
+ for (x5 = 0; x5 < hSub; ++x5) {
+ p2[x5] = dataOut[i] & 0xff;
+ }
+ p2 += bufWidth;
+ }
+ ++i;
+ }
+ p1 += bufWidth * vSub;
+ }
+ }
+ }
+ }
+ }
+
+ // color space conversion
+ if (colorXform) {
+ // convert YCbCr to RGB
+ if (numComps == 3) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = *p0;
+ pCb = *p1 - 128;
+ pCr = *p2 - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ *p0++ = dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
+ 32768) >> 16;
+ *p1++ = dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ *p2++ = dctClip[dctClipOffset + pB];
+ }
+ }
+ // convert YCbCrK to CMYK (K is passed through unchanged)
+ } else if (numComps == 4) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = *p0;
+ pCb = *p1 - 128;
+ pCr = *p2 - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ *p0++ = 255 - dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
+ 32768) >> 16;
+ *p1++ = 255 - dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ *p2++ = 255 - dctClip[dctClipOffset + pB];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Transform one data unit -- this performs the dequantization and
+// IDCT steps. This IDCT algorithm is taken from:
+// 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.
+// The stage numbers mentioned in the comments refer to Figure 1 in this
+// paper.
+void DCTStream::transformDataUnit(Guchar *quantTable,
+ int dataIn[64], Guchar dataOut[64]) {
+ int v0, v1, v2, v3, v4, v5, v6, v7, t;
+ int *p;
+ int i;
+
+ // dequant
+ for (i = 0; i < 64; ++i) {
+ dataIn[i] *= quantTable[i];
+ }
+
// inverse DCT on rows
for (i = 0; i < 64; i += 8) {
+ p = dataIn + i;
+
+ // check for all-zero AC coefficients
+ if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
+ p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
+ t = (dctSqrt2 * p[0] + 512) >> 10;
+ p[0] = t;
+ p[1] = t;
+ p[2] = t;
+ p[3] = t;
+ p[4] = t;
+ p[5] = t;
+ p[6] = t;
+ p[7] = t;
+ continue;
+ }
// stage 4
- v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
- v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
- v2 = tmp1[i+2];
- v3 = tmp1[i+6];
- v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
- v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
- v5 = tmp1[i+3] << 4;
- v6 = tmp1[i+5] << 4;
+ v0 = (dctSqrt2 * p[0] + 128) >> 8;
+ v1 = (dctSqrt2 * p[4] + 128) >> 8;
+ v2 = p[2];
+ v3 = p[6];
+ v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
+ v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
+ v5 = p[3] << 4;
+ v6 = p[5] << 4;
// stage 3
t = (v0 - v1+ 1) >> 1;
@@ -2239,28 +2661,44 @@ GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
v6 = t;
// stage 1
- tmp1[i+0] = v0 + v7;
- tmp1[i+7] = v0 - v7;
- tmp1[i+1] = v1 + v6;
- tmp1[i+6] = v1 - v6;
- tmp1[i+2] = v2 + v5;
- tmp1[i+5] = v2 - v5;
- tmp1[i+3] = v3 + v4;
- tmp1[i+4] = v3 - v4;
+ p[0] = v0 + v7;
+ p[7] = v0 - v7;
+ p[1] = v1 + v6;
+ p[6] = v1 - v6;
+ p[2] = v2 + v5;
+ p[5] = v2 - v5;
+ p[3] = v3 + v4;
+ p[4] = v3 - v4;
}
// inverse DCT on columns
for (i = 0; i < 8; ++i) {
+ p = dataIn + i;
+
+ // check for all-zero AC coefficients
+ if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
+ p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
+ t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
+ p[0*8] = t;
+ p[1*8] = t;
+ p[2*8] = t;
+ p[3*8] = t;
+ p[4*8] = t;
+ p[5*8] = t;
+ p[6*8] = t;
+ p[7*8] = t;
+ continue;
+ }
// stage 4
- v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
- v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
- v2 = tmp1[2*8+i];
- v3 = tmp1[6*8+i];
- v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
- v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
- v5 = tmp1[3*8+i];
- v6 = tmp1[5*8+i];
+ v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
+ v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
+ v2 = p[2*8];
+ v3 = p[6*8];
+ v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
+ v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
+ v5 = p[3*8];
+ v6 = p[5*8];
// stage 3
t = (v0 - v1 + 1) >> 1;
@@ -2291,181 +2729,21 @@ GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
v6 = t;
// stage 1
- tmp1[0*8+i] = v0 + v7;
- tmp1[7*8+i] = v0 - v7;
- tmp1[1*8+i] = v1 + v6;
- tmp1[6*8+i] = v1 - v6;
- tmp1[2*8+i] = v2 + v5;
- tmp1[5*8+i] = v2 - v5;
- tmp1[3*8+i] = v3 + v4;
- tmp1[4*8+i] = v3 - v4;
+ p[0*8] = v0 + v7;
+ p[7*8] = v0 - v7;
+ p[1*8] = v1 + v6;
+ p[6*8] = v1 - v6;
+ p[2*8] = v2 + v5;
+ p[5*8] = v2 - v5;
+ p[3*8] = v3 + v4;
+ p[4*8] = v3 - v4;
}
// convert to 8-bit integers
- for (i = 0; i < 64; ++i)
- data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
-
- return gTrue;
-}
-#endif
-
-#ifdef FP_IDCT
-GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- Guchar quantTable[64], int *prevDC,
- Guchar data[64]) {
- double tmp1[64];
- double v0, v1, v2, v3, v4, v5, v6, v7, t;
- int run, size, amp;
- int c;
- int i, j;
-
- // Huffman decode and dequantize
- size = readHuffSym(dcHuffTable);
- if (size == 9999)
- return gFalse;
- if (size > 0) {
- amp = readAmp(size);
- if (amp == 9999)
- return gFalse;
- } else {
- amp = 0;
+ for (i = 0; i < 64; ++i) {
+ dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
}
- tmp1[0] = (*prevDC += amp) * quantTable[0];
- for (i = 1; i < 64; ++i)
- tmp1[i] = 0;
- i = 1;
- while (i < 64) {
- run = 0;
- while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
- run += 0x10;
- if (c == 9999)
- return gFalse;
- if (c == 0x00) {
- break;
- } else {
- run += (c >> 4) & 0x0f;
- size = c & 0x0f;
- amp = readAmp(size);
- if (amp == 9999)
- return gFalse;
- i += run;
- j = dctZigZag[i++];
- tmp1[j] = amp * quantTable[j];
- }
- }
-
- // inverse DCT on rows
- for (i = 0; i < 64; i += 8) {
-
- // stage 4
- v0 = dctSqrt2 * tmp1[i+0];
- v1 = dctSqrt2 * tmp1[i+4];
- v2 = tmp1[i+2];
- v3 = tmp1[i+6];
- v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
- v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
- v5 = tmp1[i+3];
- v6 = tmp1[i+5];
-
- // stage 3
- t = 0.5 * (v0 - v1);
- v0 = 0.5 * (v0 + v1);
- v1 = t;
- t = v2 * dctSin6 + v3 * dctCos6;
- v2 = v2 * dctCos6 - v3 * dctSin6;
- v3 = t;
- t = 0.5 * (v4 - v6);
- v4 = 0.5 * (v4 + v6);
- v6 = t;
- t = 0.5 * (v7 + v5);
- v5 = 0.5 * (v7 - v5);
- v7 = t;
-
- // stage 2
- t = 0.5 * (v0 - v3);
- v0 = 0.5 * (v0 + v3);
- v3 = t;
- t = 0.5 * (v1 - v2);
- v1 = 0.5 * (v1 + v2);
- v2 = t;
- t = v4 * dctSin3 + v7 * dctCos3;
- v4 = v4 * dctCos3 - v7 * dctSin3;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1;
- v5 = v5 * dctCos1 - v6 * dctSin1;
- v6 = t;
-
- // stage 1
- tmp1[i+0] = v0 + v7;
- tmp1[i+7] = v0 - v7;
- tmp1[i+1] = v1 + v6;
- tmp1[i+6] = v1 - v6;
- tmp1[i+2] = v2 + v5;
- tmp1[i+5] = v2 - v5;
- tmp1[i+3] = v3 + v4;
- tmp1[i+4] = v3 - v4;
- }
-
- // inverse DCT on columns
- for (i = 0; i < 8; ++i) {
-
- // stage 4
- v0 = dctSqrt2 * tmp1[0*8+i];
- v1 = dctSqrt2 * tmp1[4*8+i];
- v2 = tmp1[2*8+i];
- v3 = tmp1[6*8+i];
- v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
- v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
- v5 = tmp1[3*8+i];
- v6 = tmp1[5*8+i];
-
- // stage 3
- t = 0.5 * (v0 - v1);
- v0 = 0.5 * (v0 + v1);
- v1 = t;
- t = v2 * dctSin6 + v3 * dctCos6;
- v2 = v2 * dctCos6 - v3 * dctSin6;
- v3 = t;
- t = 0.5 * (v4 - v6);
- v4 = 0.5 * (v4 + v6);
- v6 = t;
- t = 0.5 * (v7 + v5);
- v5 = 0.5 * (v7 - v5);
- v7 = t;
-
- // stage 2
- t = 0.5 * (v0 - v3);
- v0 = 0.5 * (v0 + v3);
- v3 = t;
- t = 0.5 * (v1 - v2);
- v1 = 0.5 * (v1 + v2);
- v2 = t;
- t = v4 * dctSin3 + v7 * dctCos3;
- v4 = v4 * dctCos3 - v7 * dctSin3;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1;
- v5 = v5 * dctCos1 - v6 * dctSin1;
- v6 = t;
-
- // stage 1
- tmp1[0*8+i] = v0 + v7;
- tmp1[7*8+i] = v0 - v7;
- tmp1[1*8+i] = v1 + v6;
- tmp1[6*8+i] = v1 - v6;
- tmp1[2*8+i] = v2 + v5;
- tmp1[5*8+i] = v2 - v5;
- tmp1[3*8+i] = v3 + v4;
- tmp1[4*8+i] = v3 - v4;
- }
-
- // convert to 8-bit integers
- for (i = 0; i < 64; ++i)
- data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
-
- return gTrue;
}
-#endif
int DCTStream::readHuffSym(DCTHuffTable *table) {
Gushort code;
@@ -2533,20 +2811,9 @@ int DCTStream::readBit() {
GBool DCTStream::readHeader() {
GBool doScan;
- int minHSample, minVSample;
- int bufWidth;
int n;
int c = 0;
- int i, j;
-
- width = height = 0;
- numComps = 0;
- numQuantTables = 0;
- numDCHuffTables = 0;
- numACHuffTables = 0;
- colorXform = 0;
- gotAdobeMarker = gFalse;
- restartInterval = 0;
+ int i;
// read headers
doScan = gFalse;
@@ -2554,31 +2821,49 @@ GBool DCTStream::readHeader() {
c = readMarker();
switch (c) {
case 0xc0: // SOF0
- if (!readFrameInfo())
+ if (!readBaselineSOF()) {
return gFalse;
+ }
+ break;
+ case 0xc2: // SOF2
+ if (!readProgressiveSOF()) {
+ return gFalse;
+ }
break;
case 0xc4: // DHT
- if (!readHuffmanTables())
+ if (!readHuffmanTables()) {
return gFalse;
+ }
break;
case 0xd8: // SOI
break;
+ case 0xd9: // EOI
+ return gFalse;
case 0xda: // SOS
- if (!readScanInfo())
+ if (!readScanInfo()) {
return gFalse;
+ }
doScan = gTrue;
break;
case 0xdb: // DQT
- if (!readQuantTables())
+ if (!readQuantTables()) {
return gFalse;
+ }
break;
case 0xdd: // DRI
- if (!readRestartInterval())
+ if (!readRestartInterval()) {
+ return gFalse;
+ }
+ break;
+ case 0xe0: // APP0
+ if (!readJFIFMarker()) {
return gFalse;
+ }
break;
case 0xee: // APP14
- if (!readAdobeMarker())
+ if (!readAdobeMarker()) {
return gFalse;
+ }
break;
case EOF:
error(getPos(), "Bad DCT header");
@@ -2587,8 +2872,9 @@ GBool DCTStream::readHeader() {
// skip APPn / COM / etc.
if (c >= 0xe0) {
n = read16() - 2;
- for (i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i) {
str->getChar();
+ }
} else {
error(getPos(), "Unknown DCT marker <%02x>", c);
return gFalse;
@@ -2597,107 +2883,105 @@ GBool DCTStream::readHeader() {
}
}
- // compute MCU size
- mcuWidth = minHSample = compInfo[0].hSample;
- mcuHeight = minVSample = compInfo[0].vSample;
- for (i = 1; i < numComps; ++i) {
- if (compInfo[i].hSample < minHSample)
- minHSample = compInfo[i].hSample;
- if (compInfo[i].vSample < minVSample)
- minVSample = compInfo[i].vSample;
- if (compInfo[i].hSample > mcuWidth)
- mcuWidth = compInfo[i].hSample;
- if (compInfo[i].vSample > mcuHeight)
- mcuHeight = compInfo[i].vSample;
- }
- for (i = 0; i < numComps; ++i) {
- compInfo[i].hSample /= minHSample;
- compInfo[i].vSample /= minVSample;
- }
- mcuWidth = (mcuWidth / minHSample) * 8;
- mcuHeight = (mcuHeight / minVSample) * 8;
+ return gTrue;
+}
- // allocate buffers
- bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
- for (i = 0; i < numComps; ++i)
- for (j = 0; j < mcuHeight; ++j)
- rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
+GBool DCTStream::readBaselineSOF() {
+ int length;
+ int prec;
+ int i;
+ int c;
- // figure out color transform
- if (!gotAdobeMarker && numComps == 3) {
- if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
- colorXform = 1;
- }
+ length = read16();
+ prec = str->getChar();
+ height = read16();
+ width = read16();
+ numComps = str->getChar();
+ if (prec != 8) {
+ error(getPos(), "Bad DCT precision %d", prec);
+ return gFalse;
}
-
- // initialize counters
- comp = 0;
- x = 0;
- y = 0;
- dy = mcuHeight;
-
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].id = str->getChar();
+ c = str->getChar();
+ compInfo[i].hSample = (c >> 4) & 0x0f;
+ compInfo[i].vSample = c & 0x0f;
+ compInfo[i].quantTable = str->getChar();
+ }
+ progressive = gFalse;
return gTrue;
}
-GBool DCTStream::readFrameInfo() {
+GBool DCTStream::readProgressiveSOF() {
int length;
int prec;
int i;
int c;
- length = read16() - 2;
+ length = read16();
prec = str->getChar();
height = read16();
width = read16();
numComps = str->getChar();
- length -= 6;
if (prec != 8) {
error(getPos(), "Bad DCT precision %d", prec);
return gFalse;
}
for (i = 0; i < numComps; ++i) {
compInfo[i].id = str->getChar();
- compInfo[i].inScan = gFalse;
c = str->getChar();
compInfo[i].hSample = (c >> 4) & 0x0f;
compInfo[i].vSample = c & 0x0f;
compInfo[i].quantTable = str->getChar();
- compInfo[i].dcHuffTable = 0;
- compInfo[i].acHuffTable = 0;
}
+ progressive = gTrue;
return gTrue;
}
GBool DCTStream::readScanInfo() {
int length;
- int scanComps, id, c;
+ int id, c;
int i, j;
length = read16() - 2;
- scanComps = str->getChar();
+ scanInfo.numComps = str->getChar();
--length;
- if (length != 2 * scanComps + 3) {
+ if (length != 2 * scanInfo.numComps + 3) {
error(getPos(), "Bad DCT scan info block");
return gFalse;
}
- for (i = 0; i < scanComps; ++i) {
+ interleaved = scanInfo.numComps == numComps;
+ for (j = 0; j < numComps; ++j) {
+ scanInfo.comp[j] = gFalse;
+ }
+ for (i = 0; i < scanInfo.numComps; ++i) {
id = str->getChar();
- for (j = 0; j < numComps; ++j) {
- if (id == compInfo[j].id)
- break;
- }
- if (j == numComps) {
- error(getPos(), "Bad DCT component ID in scan info block");
- return gFalse;
+ // some (broken) DCT streams reuse ID numbers, but at least they
+ // keep the components in order, so we check compInfo[i] first to
+ // work around the problem
+ if (id == compInfo[i].id) {
+ j = i;
+ } else {
+ for (j = 0; j < numComps; ++j) {
+ if (id == compInfo[j].id) {
+ break;
+ }
+ }
+ if (j == numComps) {
+ error(getPos(), "Bad DCT component ID in scan info block");
+ return gFalse;
+ }
}
- compInfo[j].inScan = gTrue;
+ scanInfo.comp[j] = gTrue;
c = str->getChar();
- compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
- compInfo[j].acHuffTable = c & 0x0f;
+ scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
+ scanInfo.acHuffTable[j] = c & 0x0f;
}
- str->getChar();
- str->getChar();
- str->getChar();
+ scanInfo.firstCoeff = str->getChar();
+ scanInfo.lastCoeff = str->getChar();
+ c = str->getChar();
+ scanInfo.ah = (c >> 4) & 0x0f;
+ scanInfo.al = c & 0x0f;
return gTrue;
}
@@ -2779,23 +3063,61 @@ GBool DCTStream::readRestartInterval() {
return gTrue;
}
+GBool DCTStream::readJFIFMarker() {
+ int length, i;
+ char buf[5];
+ int c;
+
+ length = read16();
+ length -= 2;
+ if (length >= 5) {
+ for (i = 0; i < 5; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ error(getPos(), "Bad DCT APP0 marker");
+ return gFalse;
+ }
+ buf[i] = c;
+ }
+ length -= 5;
+ if (!memcmp(buf, "JFIF\0", 5)) {
+ gotJFIFMarker = gTrue;
+ }
+ }
+ while (length > 0) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Bad DCT APP0 marker");
+ return gFalse;
+ }
+ --length;
+ }
+ return gTrue;
+}
+
GBool DCTStream::readAdobeMarker() {
int length, i;
char buf[12];
int c;
length = read16();
- if (length != 14)
+ if (length < 14) {
goto err;
+ }
for (i = 0; i < 12; ++i) {
- if ((c = str->getChar()) == EOF)
+ if ((c = str->getChar()) == EOF) {
goto err;
+ }
buf[i] = c;
}
- if (strncmp(buf, "Adobe", 5))
+ if (strncmp(buf, "Adobe", 5)) {
goto err;
+ }
colorXform = buf[11];
gotAdobeMarker = gTrue;
+ for (i = 14; i < length; ++i) {
+ if (str->getChar() == EOF) {
+ goto err;
+ }
+ }
return gTrue;
err:
@@ -2838,10 +3160,13 @@ int DCTStream::read16() {
return (c1 << 8) + c2;
}
-GString *DCTStream::getPSFilter(char *indent) {
+GString *DCTStream::getPSFilter(int psLevel, char *indent) {
GString *s;
- if (!(s = str->getPSFilter(indent))) {
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("<< >> /DCTDecode filter\n");
@@ -2933,9 +3258,13 @@ FlateStream::FlateStream(Stream *strA, int predictor, int columns,
} else {
pred = NULL;
}
+ litCodeTab.codes = NULL;
+ distCodeTab.codes = NULL;
}
FlateStream::~FlateStream() {
+ gfree(litCodeTab.codes);
+ gfree(distCodeTab.codes);
if (pred) {
delete pred;
}
@@ -3024,8 +3353,17 @@ int FlateStream::getRawChar() {
return c;
}
-GString *FlateStream::getPSFilter(char *indent) {
- return NULL;
+GString *FlateStream::getPSFilter(int psLevel, char *indent) {
+ GString *s;
+
+ if (psLevel < 3 || pred) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("<< >> /FlateDecode filter\n");
+ return s;
}
GBool FlateStream::isBinary(GBool last) {
@@ -3102,6 +3440,12 @@ GBool FlateStream::startBlock() {
int c;
int check;
+ // free the code tables from the previous block
+ gfree(litCodeTab.codes);
+ litCodeTab.codes = NULL;
+ gfree(distCodeTab.codes);
+ distCodeTab.codes = NULL;
+
// read block header
blockHdr = getCodeWord(3);
if (blockHdr & 1)
@@ -3136,8 +3480,9 @@ GBool FlateStream::startBlock() {
// compressed block with dynamic codes
} else if (blockHdr == 2) {
compressedBlock = gTrue;
- if (!readDynamicCodes())
+ if (!readDynamicCodes()) {
goto err;
+ }
// unknown block type
} else {
@@ -3156,186 +3501,196 @@ err:
void FlateStream::loadFixedCodes() {
int i;
- // set up code arrays
- litCodeTab.codes = allCodes;
- distCodeTab.codes = allCodes + flateMaxLitCodes;
-
- // initialize literal code table
- for (i = 0; i <= 143; ++i)
- litCodeTab.codes[i].len = 8;
- for (i = 144; i <= 255; ++i)
- litCodeTab.codes[i].len = 9;
- for (i = 256; i <= 279; ++i)
- litCodeTab.codes[i].len = 7;
- for (i = 280; i <= 287; ++i)
- litCodeTab.codes[i].len = 8;
- compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
-
- // initialize distance code table
- for (i = 0; i <= 5; ++i) {
- distCodeTab.start[i] = 0;
+ // build the literal code table
+ for (i = 0; i <= 143; ++i) {
+ codeLengths[i] = 8;
+ }
+ for (i = 144; i <= 255; ++i) {
+ codeLengths[i] = 9;
+ }
+ for (i = 256; i <= 279; ++i) {
+ codeLengths[i] = 7;
}
- for (i = 6; i <= flateMaxHuffman+1; ++i) {
- distCodeTab.start[i] = flateMaxDistCodes;
+ for (i = 280; i <= 287; ++i) {
+ codeLengths[i] = 8;
}
+ compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
+
+ // build the distance code table
for (i = 0; i < flateMaxDistCodes; ++i) {
- distCodeTab.codes[i].len = 5;
- distCodeTab.codes[i].code = i;
- distCodeTab.codes[i].val = i;
+ codeLengths[i] = 5;
}
+ compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
}
GBool FlateStream::readDynamicCodes() {
int numCodeLenCodes;
int numLitCodes;
int numDistCodes;
- FlateCode codeLenCodes[flateMaxCodeLenCodes];
+ int codeLenCodeLengths[flateMaxCodeLenCodes];
FlateHuffmanTab codeLenCodeTab;
int len, repeat, code;
int i;
+ codeLenCodeTab.codes = NULL;
+
// read lengths
- if ((numLitCodes = getCodeWord(5)) == EOF)
+ if ((numLitCodes = getCodeWord(5)) == EOF) {
goto err;
+ }
numLitCodes += 257;
- if ((numDistCodes = getCodeWord(5)) == EOF)
+ if ((numDistCodes = getCodeWord(5)) == EOF) {
goto err;
+ }
numDistCodes += 1;
- if ((numCodeLenCodes = getCodeWord(4)) == EOF)
+ if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
goto err;
+ }
numCodeLenCodes += 4;
if (numLitCodes > flateMaxLitCodes ||
numDistCodes > flateMaxDistCodes ||
- numCodeLenCodes > flateMaxCodeLenCodes)
+ numCodeLenCodes > flateMaxCodeLenCodes) {
goto err;
+ }
- // read code length code table
- codeLenCodeTab.codes = codeLenCodes;
- for (i = 0; i < flateMaxCodeLenCodes; ++i)
- codeLenCodes[i].len = 0;
+ // build the code length code table
+ for (i = 0; i < flateMaxCodeLenCodes; ++i) {
+ codeLenCodeLengths[i] = 0;
+ }
for (i = 0; i < numCodeLenCodes; ++i) {
- if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
+ if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
goto err;
+ }
}
- compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
+ compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
- // set up code arrays
- litCodeTab.codes = allCodes;
- distCodeTab.codes = allCodes + numLitCodes;
-
- // read literal and distance code tables
+ // build the literal and distance code tables
len = 0;
repeat = 0;
i = 0;
while (i < numLitCodes + numDistCodes) {
- if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
+ if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
goto err;
+ }
if (code == 16) {
- if ((repeat = getCodeWord(2)) == EOF)
+ if ((repeat = getCodeWord(2)) == EOF) {
+ goto err;
+ }
+ repeat += 3;
+ if (i + repeat > numLitCodes + numDistCodes) {
goto err;
- for (repeat += 3; repeat > 0; --repeat)
- allCodes[i++].len = len;
+ }
+ for (; repeat > 0; --repeat) {
+ codeLengths[i++] = len;
+ }
} else if (code == 17) {
- if ((repeat = getCodeWord(3)) == EOF)
+ if ((repeat = getCodeWord(3)) == EOF) {
goto err;
+ }
+ repeat += 3;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
len = 0;
- for (repeat += 3; repeat > 0; --repeat)
- allCodes[i++].len = 0;
+ for (; repeat > 0; --repeat) {
+ codeLengths[i++] = 0;
+ }
} else if (code == 18) {
- if ((repeat = getCodeWord(7)) == EOF)
+ if ((repeat = getCodeWord(7)) == EOF) {
goto err;
+ }
+ repeat += 11;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
len = 0;
- for (repeat += 11; repeat > 0; --repeat)
- allCodes[i++].len = 0;
+ for (; repeat > 0; --repeat) {
+ codeLengths[i++] = 0;
+ }
} else {
- allCodes[i++].len = len = code;
+ codeLengths[i++] = len = code;
}
}
- compHuffmanCodes(&litCodeTab, numLitCodes);
- compHuffmanCodes(&distCodeTab, numDistCodes);
+ compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
+ compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
+ gfree(codeLenCodeTab.codes);
return gTrue;
err:
error(getPos(), "Bad dynamic code table in flate stream");
+ gfree(codeLenCodeTab.codes);
return gFalse;
}
-// On entry, the <tab->codes> array contains the lengths of each code,
-// stored in code value order. This function computes the code words.
-// The result is sorted in order of (1) code length and (2) code word.
-// The length values are no longer valid. The <tab->start> array is
-// filled with the indexes of the first code of each length.
-void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
- int numLengths[flateMaxHuffman+1];
- int nextCode[flateMaxHuffman+1];
- int nextIndex[flateMaxHuffman+2];
- int code;
- int i, j;
+// Convert an array <lengths> of <n> lengths, in value order, into a
+// Huffman code lookup table.
+void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
+ int tabSize, len, code, code2, skip, val, i, t;
- // count number of codes for each code length
- for (i = 0; i <= flateMaxHuffman; ++i)
- numLengths[i] = 0;
- for (i = 0; i < n; ++i)
- ++numLengths[tab->codes[i].len];
+ // find max code length
+ tab->maxLen = 0;
+ for (val = 0; val < n; ++val) {
+ if (lengths[val] > tab->maxLen) {
+ tab->maxLen = lengths[val];
+ }
+ }
- // compute first index for each length
- tab->start[0] = nextIndex[0] = 0;
- for (i = 1; i <= flateMaxHuffman + 1; ++i)
- tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
+ // allocate the table
+ tabSize = 1 << tab->maxLen;
+ tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
- // compute first code for each length
- code = 0;
- numLengths[0] = 0;
- for (i = 1; i <= flateMaxHuffman; ++i) {
- code = (code + numLengths[i-1]) << 1;
- nextCode[i] = code;
+ // clear the table
+ for (i = 0; i < tabSize; ++i) {
+ tab->codes[i].len = 0;
+ tab->codes[i].val = 0;
}
- // compute the codes -- this permutes the codes array from value
- // order to length/code order
- for (i = 0; i < n; ++i) {
- j = nextIndex[tab->codes[i].len]++;
- if (tab->codes[i].len == 0)
- tab->codes[j].code = 0;
- else
- tab->codes[j].code = nextCode[tab->codes[i].len]++;
- tab->codes[j].val = i;
+ // build the table
+ for (len = 1, code = 0, skip = 2;
+ len <= tab->maxLen;
+ ++len, code <<= 1, skip <<= 1) {
+ for (val = 0; val < n; ++val) {
+ if (lengths[val] == len) {
+
+ // bit-reverse the code
+ code2 = 0;
+ t = code;
+ for (i = 0; i < len; ++i) {
+ code2 = (code2 << 1) | (t & 1);
+ t >>= 1;
+ }
+
+ // fill in the table entries
+ for (i = code2; i < tabSize; i += skip) {
+ tab->codes[i].len = (Gushort)len;
+ tab->codes[i].val = (Gushort)val;
+ }
+
+ ++code;
+ }
+ }
}
}
int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
- int len;
- int code;
+ FlateCode *code;
int c;
- int i, j;
-
- code = 0;
- for (len = 1; len <= flateMaxHuffman; ++len) {
-
- // add a bit to the code
- if (codeSize == 0) {
- if ((c = str->getChar()) == EOF)
- return EOF;
- codeBuf = c & 0xff;
- codeSize = 8;
- }
- code = (code << 1) | (codeBuf & 1);
- codeBuf >>= 1;
- --codeSize;
- // look for code
- i = tab->start[len];
- j = tab->start[len + 1];
- if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
- i += code - tab->codes[i].code;
- return tab->codes[i].val;
+ while (codeSize < tab->maxLen) {
+ if ((c = str->getChar()) == EOF) {
+ break;
}
+ codeBuf |= (c & 0xff) << codeSize;
+ codeSize += 8;
}
-
- // not found
- error(getPos(), "Bad code (%04x) in flate stream", code);
- return EOF;
+ code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
+ if (codeSize == 0 || codeSize < code->len || code->len == 0) {
+ return EOF;
+ }
+ codeBuf >>= code->len;
+ codeSize -= code->len;
+ return (int)code->val;
}
int FlateStream::getCodeWord(int bits) {
@@ -3385,9 +3740,6 @@ void FixedLengthEncoder::reset() {
count = 0;
}
-void FixedLengthEncoder::close() {
-}
-
int FixedLengthEncoder::getChar() {
if (length >= 0 && count >= length)
return EOF;
@@ -3401,6 +3753,10 @@ int FixedLengthEncoder::lookChar() {
return str->getChar();
}
+GBool FixedLengthEncoder::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
//------------------------------------------------------------------------
// ASCIIHexEncoder
//------------------------------------------------------------------------
@@ -3425,9 +3781,6 @@ void ASCIIHexEncoder::reset() {
eof = gFalse;
}
-void ASCIIHexEncoder::close() {
-}
-
GBool ASCIIHexEncoder::fillBuf() {
static char *hex = "0123456789abcdef";
int c;
@@ -3474,9 +3827,6 @@ void ASCII85Encoder::reset() {
eof = gFalse;
}
-void ASCII85Encoder::close() {
-}
-
GBool ASCII85Encoder::fillBuf() {
Gulong t;
char buf1[5];
@@ -3544,9 +3894,6 @@ void RunLengthEncoder::reset() {
eof = gFalse;
}
-void RunLengthEncoder::close() {
-}
-
//
// When fillBuf finishes, buf[] looks like this:
// +-----+--------------+-----------------+--
diff --git a/pdf2swf/xpdf/Stream.h b/pdf2swf/xpdf/Stream.h
index 3319dccd..0b70afa4 100644
--- a/pdf2swf/xpdf/Stream.h
+++ b/pdf2swf/xpdf/Stream.h
@@ -2,14 +2,16 @@
//
// Stream.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef STREAM_H
#define STREAM_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -33,6 +35,8 @@ enum StreamKind {
strCCITTFax,
strDCT,
strFlate,
+ strJBIG2,
+ strJPX,
strWeird // internal-use stream types
};
@@ -84,12 +88,12 @@ public:
virtual void setPos(Guint pos, int dir = 0) = 0;
// Get PostScript command for the filter(s).
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
// Does this stream type potentially contain non-printable chars?
virtual GBool isBinary(GBool last = gTrue) = 0;
- // Get the BaseStream or EmbedStream of this stream.
+ // Get the BaseStream of this stream.
virtual BaseStream *getBaseStream() = 0;
// Get the dictionary associated with this stream.
@@ -102,6 +106,11 @@ public:
// Returns the new stream.
Stream *addFilters(Object *dict);
+ // Tell this stream to ignore any length limitation -- this only
+ // applies to BaseStream subclasses, and is used as a hack to work
+ // around broken PDF files with incorrect stream lengths.
+ virtual void ignoreLength() {}
+
private:
Stream *makeFilter(char *name, Stream *str, Object *params);
@@ -123,6 +132,7 @@ public:
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint length, Object *dict) = 0;
virtual void setPos(Guint pos, int dir = 0) = 0;
+ virtual GBool isBinary(GBool last = gTrue) { return last; }
virtual BaseStream *getBaseStream() { return this; }
virtual Dict *getDict() { return dict.getDict(); }
@@ -163,6 +173,7 @@ public:
virtual void setPos(Guint pos, int dir = 0);
virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
virtual Dict *getDict() { return str->getDict(); }
+ virtual void ignoreLength() { str->ignoreLength(); }
protected:
@@ -190,6 +201,10 @@ public:
// at least nComps elements. Returns false at end of file.
GBool getPixel(Guchar *pix);
+ // Returns a pointer to the next line of pixels. Returns NULL at
+ // end of file.
+ Guchar *getLine();
+
// Skip an entire line from the image.
void skipLine();
@@ -260,7 +275,7 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual int getPos() { return bufPos + (bufPtr - buf); }
virtual void setPos(Guint pos, int dir = 0);
- virtual GBool isBinary(GBool last = gTrue) { return last; }
+ virtual void ignoreLength() { limited = gFalse; }
virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
@@ -287,7 +302,7 @@ private:
class MemStream: public BaseStream {
public:
- MemStream(char *bufA, Guint lengthA, Object *dictA);
+ MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
virtual ~MemStream();
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint lengthA, Object *dictA);
@@ -298,10 +313,9 @@ public:
{ return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
virtual int lookChar()
{ return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
- virtual int getPos() { return bufPtr - buf; }
+ virtual int getPos() { return (int)(bufPtr - buf); }
virtual void setPos(Guint pos, int dir = 0);
- virtual GBool isBinary(GBool last = gTrue) { return last; }
- virtual Guint getStart() { return 0; }
+ virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
#ifndef NO_DECRYPTION
virtual void doDecryption(Guchar *fileKey, int keyLength,
@@ -311,10 +325,11 @@ public:
private:
char *buf;
+ Guint start;
Guint length;
- GBool needFree;
char *bufEnd;
char *bufPtr;
+ GBool needFree;
};
//------------------------------------------------------------------------
@@ -330,23 +345,24 @@ private:
class EmbedStream: public BaseStream {
public:
- EmbedStream(Stream *strA, Object *dictA);
+ EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
virtual ~EmbedStream();
- virtual Stream *makeSubStream(Guint start, GBool limited,
- Guint length, Object *dictA);
+ virtual Stream *makeSubStream(Guint start, GBool limitedA,
+ Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return str->getKind(); }
virtual void reset() {}
- virtual int getChar() { return str->getChar(); }
- virtual int lookChar() { return str->lookChar(); }
+ virtual int getChar();
+ virtual int lookChar();
virtual int getPos() { return str->getPos(); }
virtual void setPos(Guint pos, int dir = 0);
- virtual GBool isBinary(GBool last = gTrue) { return last; }
virtual Guint getStart();
virtual void moveStart(int delta);
private:
Stream *str;
+ GBool limited;
+ Guint length;
};
//------------------------------------------------------------------------
@@ -363,7 +379,7 @@ public:
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -386,7 +402,7 @@ public:
virtual int getChar()
{ int ch = lookChar(); ++index; return ch; }
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -412,25 +428,33 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
StreamPredictor *pred; // predictor
int early; // early parameter
- FILE *zPipe; // uncompress pipe
- GString *zName; // .Z file name
+ GBool eof; // true if at eof
int inputBuf; // input buffer
int inputBits; // number of bits in input buffer
- int inCodeBits; // size of input code
- char buf[256]; // buffer
- char *bufPtr; // next char to read
- char *bufEnd; // end of buffer
-
- void dumpFile(FILE *f);
+ struct { // decoding table
+ int length;
+ int head;
+ Guchar tail;
+ } table[4097];
+ int nextCode; // next code to be used
+ int nextBits; // number of bits in next code word
+ int prevCode; // previous code used in stream
+ int newChar; // next char to be added to table
+ Guchar seqBuf[4097]; // buffer for current sequence
+ int seqLength; // length of current sequence
+ int seqIndex; // index into current sequence
+ GBool first; // first code after a table clear
+
+ GBool processNextCode();
+ void clearTable();
int getCode();
- GBool fillBuf();
};
//------------------------------------------------------------------------
@@ -448,7 +472,7 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -479,7 +503,7 @@ public:
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -517,13 +541,21 @@ private:
// DCT component info
struct DCTCompInfo {
int id; // component ID
- GBool inScan; // is this component in the current scan?
int hSample, vSample; // horiz/vert sampling resolutions
int quantTable; // quantization table number
- int dcHuffTable, acHuffTable; // Huffman table numbers
int prevDC; // DC coefficient accumulator
};
+struct DCTScanInfo {
+ GBool comp[4]; // comp[i] is set if component i is
+ // included in this scan
+ int numComps; // number of components in the scan
+ int dcHuffTable[4]; // DC Huffman table numbers
+ int acHuffTable[4]; // AC Huffman table numbers
+ int firstCoeff, lastCoeff; // first and last DCT coefficient
+ int ah, al; // successive approximation parameters
+};
+
// DCT Huffman decoding table
struct DCTHuffTable {
Guchar firstSym[17]; // first symbol for this bit length
@@ -541,17 +573,22 @@ public:
virtual void reset();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
Stream *getRawStream() { return str; }
private:
+ GBool progressive; // set if in progressive mode
+ GBool interleaved; // set if in interleaved mode
int width, height; // image size
int mcuWidth, mcuHeight; // size of min coding unit, in data units
+ int bufWidth, bufHeight; // frameBuf size
DCTCompInfo compInfo[4]; // info for each component
+ DCTScanInfo scanInfo; // info for the current scan
int numComps; // number of components in image
int colorXform; // need YCbCr-to-RGB transform?
+ GBool gotJFIFMarker; // set if APP0 JFIF marker was present
GBool gotAdobeMarker; // set if APP14 Adobe marker was present
int restartInterval; // restart interval, in MCUs
Guchar quantTables[4][64]; // quantization tables
@@ -560,26 +597,38 @@ private:
DCTHuffTable acHuffTables[4]; // AC Huffman tables
int numDCHuffTables; // number of DC Huffman tables
int numACHuffTables; // number of AC Huffman tables
- Guchar *rowBuf[4][32]; // buffer for one MCU
+ Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
+ int *frameBuf[4]; // buffer for frame (progressive mode)
int comp, x, y, dy; // current position within image/MCU
int restartCtr; // MCUs left until restart
int restartMarker; // next restart marker
+ int eobRun; // number of EOBs left in the current run
int inputBuf; // input buffer for variable length codes
int inputBits; // number of valid bits in input buffer
void restart();
GBool readMCURow();
- GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable,
- Guchar quantTable[64], int *prevDC, Guchar data[64]);
+ void readScan();
+ GBool readDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]);
+ GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]);
+ void decodeImage();
+ void transformDataUnit(Guchar *quantTable,
+ int dataIn[64], Guchar dataOut[64]);
int readHuffSym(DCTHuffTable *table);
int readAmp(int size);
int readBit();
GBool readHeader();
- GBool readFrameInfo();
+ GBool readBaselineSOF();
+ GBool readProgressiveSOF();
GBool readScanInfo();
GBool readQuantTables();
GBool readHuffmanTables();
GBool readRestartInterval();
+ GBool readJFIFMarker();
GBool readAdobeMarker();
GBool readTrailer();
int readMarker();
@@ -599,15 +648,13 @@ private:
// Huffman code table entry
struct FlateCode {
- int len; // code length in bits
- int code; // code word
- int val; // value represented by this code
+ Gushort len; // code length, in bits
+ Gushort val; // value represented by this code
};
-// Huffman code table
struct FlateHuffmanTab {
- int start[flateMaxHuffman+2]; // indexes of first code of each length
- FlateCode *codes; // codes, sorted by length and code word
+ FlateCode *codes;
+ int maxLen;
};
// Decoding info for length and distance code words
@@ -627,7 +674,7 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -638,8 +685,8 @@ private:
int remain; // number valid bytes in output buffer
int codeBuf; // input buffer
int codeSize; // number of bits in input buffer
- FlateCode // literal and distance codes
- allCodes[flateMaxLitCodes + flateMaxDistCodes];
+ int // literal and distance code lengths
+ codeLengths[flateMaxLitCodes + flateMaxDistCodes];
FlateHuffmanTab litCodeTab; // literal code table
FlateHuffmanTab distCodeTab; // distance code table
GBool compressedBlock; // set if reading a compressed block
@@ -658,7 +705,7 @@ private:
GBool startBlock();
void loadFixedCodes();
GBool readDynamicCodes();
- void compHuffmanCodes(FlateHuffmanTab *tab, int n);
+ void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
int getHuffmanCodeWord(FlateHuffmanTab *tab);
int getCodeWord(int bits);
};
@@ -676,7 +723,7 @@ public:
virtual void reset() {}
virtual int getChar() { return EOF; }
virtual int lookChar() { return EOF; }
- virtual GString *getPSFilter(char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
};
@@ -691,11 +738,10 @@ public:
~FixedLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
- virtual void close();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue);
virtual GBool isEncoder() { return gTrue; }
private:
@@ -715,12 +761,11 @@ public:
virtual ~ASCIIHexEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
- virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
@@ -746,12 +791,11 @@ public:
virtual ~ASCII85Encoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
- virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
@@ -777,13 +821,12 @@ public:
virtual ~RunLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
- virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
private:
diff --git a/pdf2swf/xpdf/UTF8.h b/pdf2swf/xpdf/UTF8.h
index d707e2fc..8536dbf9 100644
--- a/pdf2swf/xpdf/UTF8.h
+++ b/pdf2swf/xpdf/UTF8.h
@@ -2,7 +2,7 @@
//
// UTF8.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
diff --git a/pdf2swf/xpdf/UnicodeMap.cc b/pdf2swf/xpdf/UnicodeMap.cc
index 75f23d2b..300d802a 100644
--- a/pdf2swf/xpdf/UnicodeMap.cc
+++ b/pdf2swf/xpdf/UnicodeMap.cc
@@ -2,15 +2,16 @@
//
// UnicodeMap.cc
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <string.h>
#include "gmem.h"
@@ -101,37 +102,52 @@ UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
++line;
}
+ fclose(f);
+
return map;
}
UnicodeMap::UnicodeMap(GString *encodingNameA) {
encodingName = encodingNameA;
+ unicodeOut = gFalse;
kind = unicodeMapUser;
ranges = NULL;
len = 0;
eMaps = NULL;
eMapsLen = 0;
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
-UnicodeMap::UnicodeMap(char *encodingNameA,
+UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
UnicodeMapRange *rangesA, int lenA) {
encodingName = new GString(encodingNameA);
+ unicodeOut = unicodeOutA;
kind = unicodeMapResident;
ranges = rangesA;
len = lenA;
eMaps = NULL;
eMapsLen = 0;
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
-UnicodeMap::UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA) {
+UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
+ UnicodeMapFunc funcA) {
encodingName = new GString(encodingNameA);
+ unicodeOut = unicodeOutA;
kind = unicodeMapFunc;
func = funcA;
eMaps = NULL;
eMapsLen = 0;
refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
}
UnicodeMap::~UnicodeMap() {
@@ -142,14 +158,32 @@ UnicodeMap::~UnicodeMap() {
if (eMaps) {
gfree(eMaps);
}
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
}
void UnicodeMap::incRefCnt() {
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
++refCnt;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
}
void UnicodeMap::decRefCnt() {
- if (--refCnt == 0) {
+ GBool done;
+
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ done = --refCnt == 0;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+ if (done) {
delete this;
}
}
@@ -168,29 +202,28 @@ int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
a = 0;
b = len;
- if (u < ranges[a].start) {
- return 0;
- }
- // invariant: ranges[a].start <= u < ranges[b].start
- while (b - a > 1) {
- m = (a + b) / 2;
- if (u >= ranges[m].start) {
- a = m;
- } else if (u < ranges[m].start) {
- b = m;
- }
- }
- if (u <= ranges[a].end) {
- n = ranges[a].nBytes;
- if (n > bufSize) {
- return 0;
+ if (u >= ranges[a].start) {
+ // invariant: ranges[a].start <= u < ranges[b].start
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (u >= ranges[m].start) {
+ a = m;
+ } else if (u < ranges[m].start) {
+ b = m;
+ }
}
- code = ranges[a].code + (u - ranges[a].start);
- for (i = n - 1; i >= 0; --i) {
- buf[i] = (char)(code & 0xff);
- code >>= 8;
+ if (u <= ranges[a].end) {
+ n = ranges[a].nBytes;
+ if (n > bufSize) {
+ return 0;
+ }
+ code = ranges[a].code + (u - ranges[a].start);
+ for (i = n - 1; i >= 0; --i) {
+ buf[i] = (char)(code & 0xff);
+ code >>= 8;
+ }
+ return n;
}
- return n;
}
for (i = 0; i < eMapsLen; ++i) {
diff --git a/pdf2swf/xpdf/UnicodeMap.h b/pdf2swf/xpdf/UnicodeMap.h
index 274c4472..6fd4ed24 100644
--- a/pdf2swf/xpdf/UnicodeMap.h
+++ b/pdf2swf/xpdf/UnicodeMap.h
@@ -4,20 +4,26 @@
//
// Mapping from Unicode to an encoding.
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef UNICODEMAP_H
#define UNICODEMAP_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "gtypes.h"
#include "CharTypes.h"
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
class GString;
//------------------------------------------------------------------------
@@ -47,12 +53,13 @@ public:
static UnicodeMap *parse(GString *encodingNameA);
// Create a resident UnicodeMap.
- UnicodeMap(char *encodingNameA,
+ UnicodeMap(char *encodingNameA, GBool unicodeOutA,
UnicodeMapRange *rangesA, int lenA);
// Create a resident UnicodeMap that uses a function instead of a
// list of ranges.
- UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA);
+ UnicodeMap(char *encodingNameA, GBool unicodeOutA,
+ UnicodeMapFunc funcA);
~UnicodeMap();
@@ -61,6 +68,8 @@ public:
GString *getEncodingName() { return encodingName; }
+ GBool isUnicode() { return unicodeOut; }
+
// Return true if this UnicodeMap matches the specified
// <encodingNameA>.
GBool match(GString *encodingNameA);
@@ -77,6 +86,7 @@ private:
GString *encodingName;
UnicodeMapKind kind;
+ GBool unicodeOut;
union {
UnicodeMapRange *ranges; // (user, resident)
UnicodeMapFunc func; // (func)
@@ -85,6 +95,9 @@ private:
UnicodeMapExt *eMaps; // (user)
int eMapsLen; // (user)
int refCnt;
+#ifdef MULTITHREADED
+ GMutex mutex;
+#endif
};
//------------------------------------------------------------------------
diff --git a/pdf2swf/xpdf/UnicodeMapTables.h b/pdf2swf/xpdf/UnicodeMapTables.h
index 51dee98d..9c510346 100644
--- a/pdf2swf/xpdf/UnicodeMapTables.h
+++ b/pdf2swf/xpdf/UnicodeMapTables.h
@@ -2,7 +2,7 @@
//
// UnicodeMapTables.h
//
-// Copyright 2001-2002 Glyph & Cog, LLC
+// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
diff --git a/pdf2swf/xpdf/XRef.cc b/pdf2swf/xpdf/XRef.cc
index 0e1bbc9c..e0d82d23 100644
--- a/pdf2swf/xpdf/XRef.cc
+++ b/pdf2swf/xpdf/XRef.cc
@@ -2,15 +2,16 @@
//
// XRef.cc
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -46,12 +47,148 @@
#endif
//------------------------------------------------------------------------
+// ObjectStream
+//------------------------------------------------------------------------
+
+class ObjectStream {
+public:
+
+ // Create an object stream, using object number <objStrNum>,
+ // generation 0.
+ ObjectStream(XRef *xref, int objStrNumA);
+
+ ~ObjectStream();
+
+ // Return the object number of this object stream.
+ int getObjStrNum() { return objStrNum; }
+
+ // Get the <objIdx>th object from this stream, which should be
+ // object number <objNum>, generation 0.
+ Object *getObject(int objIdx, int objNum, Object *obj);
+
+private:
+
+ int objStrNum; // object number of the object stream
+ int nObjects; // number of objects in the stream
+ Object *objs; // the objects (length = nObjects)
+ int *objNums; // the object numbers (length = nObjects)
+};
+
+ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
+ Stream *str;
+ Parser *parser;
+ int *offsets;
+ Object objStr, obj1, obj2;
+ int first, i;
+
+ objStrNum = objStrNumA;
+ nObjects = 0;
+ objs = NULL;
+ objNums = NULL;
+
+ if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) {
+ goto err1;
+ }
+
+ if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) {
+ obj1.free();
+ goto err1;
+ }
+ nObjects = obj1.getInt();
+ obj1.free();
+ if (nObjects == 0) {
+ goto err1;
+ }
+
+ if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) {
+ obj1.free();
+ goto err1;
+ }
+ first = obj1.getInt();
+ obj1.free();
+
+ objs = new Object[nObjects];
+ objNums = (int *)gmalloc(nObjects * sizeof(int));
+ offsets = (int *)gmalloc(nObjects * sizeof(int));
+
+ // parse the header: object numbers and offsets
+ objStr.streamReset();
+ obj1.initNull();
+ str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
+ parser = new Parser(xref, new Lexer(xref, str));
+ for (i = 0; i < nObjects; ++i) {
+ parser->getObj(&obj1);
+ parser->getObj(&obj2);
+ if (!obj1.isInt() || !obj2.isInt()) {
+ obj1.free();
+ obj2.free();
+ delete parser;
+ gfree(offsets);
+ goto err1;
+ }
+ objNums[i] = obj1.getInt();
+ offsets[i] = obj2.getInt();
+ obj1.free();
+ obj2.free();
+ }
+ while (str->getChar() != EOF) ;
+ delete parser;
+
+ // skip to the first object - this shouldn't be necessary because
+ // the First key is supposed to be equal to offsets[0], but just in
+ // case...
+ for (i = first; i < offsets[0]; ++i) {
+ objStr.getStream()->getChar();
+ }
+
+ // parse the objects
+ for (i = 0; i < nObjects; ++i) {
+ obj1.initNull();
+ if (i == nObjects - 1) {
+ str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0);
+ } else {
+ str = new EmbedStream(objStr.getStream(), &obj1, gTrue,
+ offsets[i+1] - offsets[i]);
+ }
+ parser = new Parser(xref, new Lexer(xref, str));
+ parser->getObj(&objs[i]);
+ while (str->getChar() != EOF) ;
+ delete parser;
+ }
+
+ gfree(offsets);
+
+ err1:
+ objStr.free();
+ return;
+}
+
+ObjectStream::~ObjectStream() {
+ int i;
+
+ if (objs) {
+ for (i = 0; i < nObjects; ++i) {
+ objs[i].free();
+ }
+ delete[] objs;
+ }
+ gfree(objNums);
+}
+
+Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
+ if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) {
+ return obj->initNull();
+ }
+ return objs[objIdx].copy(obj);
+}
+
+//------------------------------------------------------------------------
// XRef
//------------------------------------------------------------------------
XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
Guint pos;
- int i;
+ Object obj;
ok = gTrue;
errCode = errNone;
@@ -59,35 +196,28 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
entries = NULL;
streamEnds = NULL;
streamEndsLen = 0;
+ objStr = NULL;
// read the trailer
str = strA;
start = str->getStart();
- pos = readTrailer();
+ pos = getStartXref();
- // if there was a problem with the trailer,
- // try to reconstruct the xref table
+ // if there was a problem with the 'startxref' position, try to
+ // reconstruct the xref table
if (pos == 0) {
if (!(ok = constructXRef())) {
errCode = errDamaged;
return;
}
- // trailer is ok - read the xref table
+ // read the xref table
} else {
- entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
- for (i = 0; i < size; ++i) {
- entries[i].offset = 0xffffffff;
- entries[i].used = gFalse;
- }
while (readXRef(&pos)) ;
// if there was a problem with the xref table,
// try to reconstruct it
if (!ok) {
- gfree(entries);
- size = 0;
- entries = NULL;
if (!(ok = constructXRef())) {
errCode = errDamaged;
return;
@@ -95,6 +225,20 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
}
}
+ // get the root dictionary (catalog) object
+ trailerDict.dictLookupNF("Root", &obj);
+ if (obj.isRef()) {
+ rootNum = obj.getRefNum();
+ rootGen = obj.getRefGen();
+ obj.free();
+ } else {
+ obj.free();
+ if (!(ok = constructXRef())) {
+ errCode = errDamaged;
+ return;
+ }
+ }
+
// now set the trailer dictionary's xref pointer so we can fetch
// indirect objects from it
trailerDict.getDict()->setXRef(this);
@@ -116,188 +260,154 @@ XRef::~XRef() {
if (streamEnds) {
gfree(streamEnds);
}
+ if (objStr) {
+ delete objStr;
+ }
}
-// Read startxref position, xref table size, and root. Returns
-// first xref position.
-Guint XRef::readTrailer() {
- Parser *parser;
- Object obj;
+// Read the 'startxref' position.
+Guint XRef::getStartXref() {
char buf[xrefSearchSize+1];
- int n;
- Guint pos, pos1;
char *p;
- int c;
- int i;
+ int c, n, i;
// read last xrefSearchSize bytes
str->setPos(xrefSearchSize, -1);
for (n = 0; n < xrefSearchSize; ++n) {
- if ((c = str->getChar()) == EOF)
+ if ((c = str->getChar()) == EOF) {
break;
+ }
buf[n] = c;
}
buf[n] = '\0';
// find startxref
for (i = n - 9; i >= 0; --i) {
- if (!strncmp(&buf[i], "startxref", 9))
+ if (!strncmp(&buf[i], "startxref", 9)) {
break;
+ }
}
- if (i < 0)
+ if (i < 0) {
return 0;
+ }
for (p = &buf[i+9]; isspace(*p); ++p) ;
- pos = lastXRefPos = strToUnsigned(p);
-
- // find trailer dict by looking after first xref table
- // (NB: we can't just use the trailer dict at the end of the file --
- // this won't work for linearized files.)
- str->setPos(start + pos);
- for (i = 0; i < 4; ++i)
- buf[i] = str->getChar();
- if (strncmp(buf, "xref", 4))
- return 0;
- pos1 = pos + 4;
- while (1) {
- str->setPos(start + pos1);
- for (i = 0; i < 35; ++i) {
- if ((c = str->getChar()) == EOF)
- return 0;
- buf[i] = c;
- }
- if (!strncmp(buf, "trailer", 7))
- break;
- p = buf;
- while (isspace(*p)) ++p;
- while ('0' <= *p && *p <= '9') ++p;
- while (isspace(*p)) ++p;
- n = atoi(p);
- while ('0' <= *p && *p <= '9') ++p;
- while (isspace(*p)) ++p;
- if (p == buf)
- return 0;
- pos1 += (p - buf) + n * 20;
- }
- pos1 += 7;
-
- // read trailer dict
+ lastXRefPos = strToUnsigned(p);
+
+ return lastXRefPos;
+}
+
+// Read one xref table section. Also reads the associated trailer
+// dictionary, and returns the prev pointer (if any).
+GBool XRef::readXRef(Guint *pos) {
+ Parser *parser;
+ Object obj;
+ GBool more;
+
+ // start up a parser, parse one token
obj.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
- str->makeSubStream(start + pos1, gFalse, 0, &obj)));
- parser->getObj(&trailerDict);
- if (trailerDict.isDict()) {
- trailerDict.dictLookupNF("Size", &obj);
- if (obj.isInt())
- size = obj.getInt();
- else
- pos = 0;
+ str->makeSubStream(start + *pos, gFalse, 0, &obj)));
+ parser->getObj(&obj);
+
+ // parse an old-style xref table
+ if (obj.isCmd("xref")) {
obj.free();
- trailerDict.dictLookupNF("Root", &obj);
- if (obj.isRef()) {
- rootNum = obj.getRefNum();
- rootGen = obj.getRefGen();
- } else {
- pos = 0;
+ more = readXRefTable(parser, pos);
+
+ // parse an xref stream
+ } else if (obj.isInt()) {
+ obj.free();
+ if (!parser->getObj(&obj)->isInt()) {
+ goto err1;
+ }
+ obj.free();
+ if (!parser->getObj(&obj)->isCmd("obj")) {
+ goto err1;
}
obj.free();
+ if (!parser->getObj(&obj)->isStream()) {
+ goto err1;
+ }
+ more = readXRefStream(obj.getStream(), pos);
+ obj.free();
+
} else {
- pos = 0;
+ goto err1;
}
+
delete parser;
+ return more;
- // return first xref position
- return pos;
+ err1:
+ obj.free();
+ delete parser;
+ ok = gFalse;
+ return gFalse;
}
-// Read an xref table and the prev pointer from the trailer.
-GBool XRef::readXRef(Guint *pos) {
- Parser *parser;
- Object obj, obj2;
- char s[20];
+GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
+ XRefEntry entry;
GBool more;
- int first, newSize, n, i, j;
- int c;
-
- // seek to xref in stream
- str->setPos(start + *pos);
-
- // make sure it's an xref table
- while ((c = str->getChar()) != EOF && isspace(c)) ;
- s[0] = (char)c;
- s[1] = (char)str->getChar();
- s[2] = (char)str->getChar();
- s[3] = (char)str->getChar();
- if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) {
- goto err2;
- }
+ Object obj, obj2;
+ Guint pos2;
+ int first, n, newSize, i;
- // read xref
while (1) {
- while ((c = str->lookChar()) != EOF && isspace(c)) {
- str->getChar();
- }
- if (c == 't') {
+ parser->getObj(&obj);
+ if (obj.isCmd("trailer")) {
+ obj.free();
break;
}
- for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
- s[i] = (char)c;
- }
- if (i == 0) {
- goto err2;
+ if (!obj.isInt()) {
+ goto err1;
}
- s[i] = '\0';
- first = atoi(s);
- while ((c = str->lookChar()) != EOF && isspace(c)) {
- str->getChar();
- }
- for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
- s[i] = (char)c;
- }
- if (i == 0) {
- goto err2;
- }
- s[i] = '\0';
- n = atoi(s);
- while ((c = str->lookChar()) != EOF && isspace(c)) {
- str->getChar();
+ first = obj.getInt();
+ obj.free();
+ if (!parser->getObj(&obj)->isInt()) {
+ goto err1;
}
- // check for buggy PDF files with an incorrect (too small) xref
- // table size
+ n = obj.getInt();
+ obj.free();
if (first + n > size) {
- newSize = size + 256;
+ for (newSize = size ? 2 * size : 1024;
+ first + n > newSize;
+ newSize <<= 1) ;
entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
for (i = size; i < newSize; ++i) {
entries[i].offset = 0xffffffff;
- entries[i].used = gFalse;
+ entries[i].type = xrefEntryFree;
}
size = newSize;
}
for (i = first; i < first + n; ++i) {
- for (j = 0; j < 20; ++j) {
- if ((c = str->getChar()) == EOF) {
- goto err2;
- }
- s[j] = (char)c;
+ if (!parser->getObj(&obj)->isInt()) {
+ goto err1;
+ }
+ entry.offset = (Guint)obj.getInt();
+ obj.free();
+ if (!parser->getObj(&obj)->isInt()) {
+ goto err1;
}
+ entry.gen = obj.getInt();
+ obj.free();
+ parser->getObj(&obj);
+ if (obj.isCmd("n")) {
+ entry.type = xrefEntryUncompressed;
+ } else if (obj.isCmd("f")) {
+ entry.type = xrefEntryFree;
+ } else {
+ goto err1;
+ }
+ obj.free();
if (entries[i].offset == 0xffffffff) {
- s[10] = '\0';
- entries[i].offset = strToUnsigned(s);
- s[16] = '\0';
- entries[i].gen = atoi(&s[11]);
- if (s[17] == 'n') {
- entries[i].used = gTrue;
- } else if (s[17] == 'f') {
- entries[i].used = gFalse;
- } else {
- goto err2;
- }
+ entries[i] = entry;
// PDF files of patents from the IBM Intellectual Property
// Network have a bug: the xref table claims to start at 1
// instead of 0.
if (i == 1 && first == 1 &&
entries[1].offset == 0 && entries[1].gen == 65535 &&
- !entries[1].used) {
+ entries[1].type == xrefEntryFree) {
i = first = 0;
entries[0] = entries[1];
entries[1].offset = 0xffffffff;
@@ -306,44 +416,203 @@ GBool XRef::readXRef(Guint *pos) {
}
}
- // read prev pointer from trailer dictionary
- obj.initNull();
- parser = new Parser(NULL,
- new Lexer(NULL,
- str->makeSubStream(str->getPos(), gFalse, 0, &obj)));
- parser->getObj(&obj);
- if (!obj.isCmd("trailer")) {
- goto err1;
- }
- obj.free();
- parser->getObj(&obj);
- if (!obj.isDict()) {
+ // read the trailer dictionary
+ if (!parser->getObj(&obj)->isDict()) {
goto err1;
}
+
+ // get the 'Prev' pointer
obj.getDict()->lookupNF("Prev", &obj2);
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;
}
- obj.free();
obj2.free();
- delete parser;
+ // save the first trailer dictionary
+ if (trailerDict.isNone()) {
+ obj.copy(&trailerDict);
+ }
+
+ // check for an 'XRefStm' key
+ if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) {
+ pos2 = obj2.getInt();
+ readXRef(&pos2);
+ if (!ok) {
+ goto err1;
+ }
+ }
+ obj2.free();
+
+ obj.free();
return more;
err1:
obj.free();
- err2:
ok = gFalse;
return gFalse;
}
+GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
+ Dict *dict;
+ int w[3];
+ GBool more;
+ Object obj, obj2, idx;
+ int newSize, first, n, i;
+
+ dict = xrefStr->getDict();
+
+ if (!dict->lookupNF("Size", &obj)->isInt()) {
+ goto err1;
+ }
+ newSize = obj.getInt();
+ obj.free();
+ if (newSize > size) {
+ entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
+ for (i = size; i < newSize; ++i) {
+ entries[i].offset = 0xffffffff;
+ entries[i].type = xrefEntryFree;
+ }
+ size = newSize;
+ }
+
+ if (!dict->lookupNF("W", &obj)->isArray() ||
+ obj.arrayGetLength() < 3) {
+ goto err1;
+ }
+ for (i = 0; i < 3; ++i) {
+ if (!obj.arrayGet(i, &obj2)->isInt()) {
+ obj2.free();
+ goto err1;
+ }
+ w[i] = obj2.getInt();
+ obj2.free();
+ }
+ obj.free();
+
+ xrefStr->reset();
+ dict->lookupNF("Index", &idx);
+ if (idx.isArray()) {
+ for (i = 0; i+1 < idx.arrayGetLength(); i += 2) {
+ if (!idx.arrayGet(i, &obj)->isInt()) {
+ idx.free();
+ goto err1;
+ }
+ first = obj.getInt();
+ obj.free();
+ if (!idx.arrayGet(i+1, &obj)->isInt()) {
+ idx.free();
+ goto err1;
+ }
+ n = obj.getInt();
+ obj.free();
+ if (!readXRefStreamSection(xrefStr, w, first, n)) {
+ idx.free();
+ goto err0;
+ }
+ }
+ } else {
+ if (!readXRefStreamSection(xrefStr, w, 0, size)) {
+ idx.free();
+ goto err0;
+ }
+ }
+ idx.free();
+
+ dict->lookupNF("Prev", &obj);
+ if (obj.isInt()) {
+ *pos = (Guint)obj.getInt();
+ more = gTrue;
+ } else {
+ more = gFalse;
+ }
+ obj.free();
+ if (trailerDict.isNone()) {
+ trailerDict.initDict(dict);
+ }
+
+ return more;
+
+ err1:
+ obj.free();
+ err0:
+ ok = gFalse;
+ return gFalse;
+}
+
+GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
+ Guint offset;
+ int type, gen, c, newSize, i, j;
+
+ if (first + n > size) {
+ for (newSize = size ? 2 * size : 1024;
+ first + n > newSize;
+ newSize <<= 1) ;
+ entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
+ for (i = size; i < newSize; ++i) {
+ entries[i].offset = 0xffffffff;
+ entries[i].type = xrefEntryFree;
+ }
+ size = newSize;
+ }
+ for (i = first; i < first + n; ++i) {
+ if (w[0] == 0) {
+ type = 1;
+ } else {
+ for (type = 0, j = 0; j < w[0]; ++j) {
+ if ((c = xrefStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ type = (type << 8) + c;
+ }
+ }
+ for (offset = 0, j = 0; j < w[1]; ++j) {
+ if ((c = xrefStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ offset = (offset << 8) + c;
+ }
+ for (gen = 0, j = 0; j < w[2]; ++j) {
+ if ((c = xrefStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ gen = (gen << 8) + c;
+ }
+ switch (type) {
+ case 0:
+ entries[i].offset = offset;
+ entries[i].gen = gen;
+ entries[i].type = xrefEntryFree;
+ break;
+ case 1:
+ entries[i].offset = offset;
+ entries[i].gen = gen;
+ entries[i].type = xrefEntryUncompressed;
+ break;
+ case 2:
+ entries[i].offset = offset;
+ entries[i].gen = gen;
+ entries[i].type = xrefEntryCompressed;
+ break;
+ default:
+ return gFalse;
+ }
+ }
+
+ return gTrue;
+}
+
// Attempt to construct an xref table for a damaged file.
GBool XRef::constructXRef() {
Parser *parser;
- Object obj;
+ Object newTrailerDict, obj;
char buf[256];
Guint pos;
int num, gen;
@@ -353,6 +622,10 @@ GBool XRef::constructXRef() {
int i;
GBool gotRoot;
+ gfree(entries);
+ size = 0;
+ entries = NULL;
+
error(0, "PDF file is damaged - attempting to reconstruct xref table...");
gotRoot = gFalse;
streamEndsLen = streamEndsSize = 0;
@@ -371,20 +644,21 @@ GBool XRef::constructXRef() {
parser = new Parser(NULL,
new Lexer(NULL,
str->makeSubStream(start + pos + 7, gFalse, 0, &obj)));
- if (!trailerDict.isNone())
- trailerDict.free();
- parser->getObj(&trailerDict);
- if (trailerDict.isDict()) {
- trailerDict.dictLookupNF("Root", &obj);
+ parser->getObj(&newTrailerDict);
+ if (newTrailerDict.isDict()) {
+ newTrailerDict.dictLookupNF("Root", &obj);
if (obj.isRef()) {
rootNum = obj.getRefNum();
rootGen = obj.getRefGen();
+ if (!trailerDict.isNone()) {
+ trailerDict.free();
+ }
+ newTrailerDict.copy(&trailerDict);
gotRoot = gTrue;
}
obj.free();
- } else {
- pos = 0;
}
+ newTrailerDict.free();
delete parser;
// look for object
@@ -413,14 +687,15 @@ GBool XRef::constructXRef() {
grealloc(entries, newSize * sizeof(XRefEntry));
for (i = size; i < newSize; ++i) {
entries[i].offset = 0xffffffff;
- entries[i].used = gFalse;
+ entries[i].type = xrefEntryFree;
}
size = newSize;
}
- if (!entries[num].used || gen >= entries[num].gen) {
+ if (entries[num].type == xrefEntryFree ||
+ gen >= entries[num].gen) {
entries[num].offset = pos - start;
entries[num].gen = gen;
- entries[num].used = gTrue;
+ entries[num].type = xrefEntryUncompressed;
}
}
}
@@ -451,9 +726,12 @@ GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
GBool encrypted1;
GBool ret;
+ keyLength = 0;
+ encVersion = encRevision = 0;
ret = gFalse;
permFlags = defPermFlags;
+ ownerPasswordOk = gFalse;
trailerDict.dictLookup("Encrypt", &encrypt);
if ((encrypted1 = encrypt.isDict())) {
ret = gTrue;
@@ -544,38 +822,34 @@ GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
GBool XRef::okToPrint(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
- if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permPrint)) {
- return gFalse;
- }
-#endif
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint);
+#else
return gTrue;
+#endif
}
GBool XRef::okToChange(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
- if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permChange)) {
- return gFalse;
- }
-#endif
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange);
+#else
return gTrue;
+#endif
}
GBool XRef::okToCopy(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
- if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permCopy)) {
- return gFalse;
- }
-#endif
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy);
+#else
return gTrue;
+#endif
}
GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
- if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permNotes)) {
- return gFalse;
- }
-#endif
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes);
+#else
return gTrue;
+#endif
}
Object *XRef::fetch(int num, int gen, Object *obj) {
@@ -585,12 +859,16 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
// check for bogus ref - this can happen in corrupted PDF files
if (num < 0 || num >= size) {
- obj->initNull();
- return obj;
+ goto err;
}
e = &entries[num];
- if (e->gen == gen && e->offset != 0xffffffff) {
+ switch (e->type) {
+
+ case xrefEntryUncompressed:
+ if (e->gen != gen) {
+ goto err;
+ }
obj1.initNull();
parser = new Parser(this,
new Lexer(this,
@@ -598,26 +876,44 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
- if (obj1.isInt() && obj1.getInt() == num &&
- obj2.isInt() && obj2.getInt() == gen &&
- obj3.isCmd("obj")) {
+ if (!obj1.isInt() || obj1.getInt() != num ||
+ !obj2.isInt() || obj2.getInt() != gen ||
+ !obj3.isCmd("obj")) {
+ goto err;
+ }
#ifndef NO_DECRYPTION
- parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
- num, gen);
+ parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
+ num, gen);
#else
- parser->getObj(obj);
+ parser->getObj(obj);
#endif
- } else {
- obj->initNull();
- }
obj1.free();
obj2.free();
obj3.free();
delete parser;
- } else {
- obj->initNull();
+ break;
+
+ case xrefEntryCompressed:
+ if (gen != 0) {
+ goto err;
+ }
+ if (!objStr || objStr->getObjStrNum() != (int)e->offset) {
+ if (objStr) {
+ delete objStr;
+ }
+ objStr = new ObjectStream(this, e->offset);
+ }
+ objStr->getObject(e->gen, num, obj);
+ break;
+
+ default:
+ goto err;
}
+
return obj;
+
+ err:
+ return obj->initNull();
}
Object *XRef::getDocInfo(Object *obj) {
diff --git a/pdf2swf/xpdf/XRef.h b/pdf2swf/xpdf/XRef.h
index 7876fa6c..bec487a1 100644
--- a/pdf2swf/xpdf/XRef.h
+++ b/pdf2swf/xpdf/XRef.h
@@ -2,14 +2,16 @@
//
// XRef.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef XREF_H
#define XREF_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
@@ -18,15 +20,23 @@
class Dict;
class Stream;
+class Parser;
+class ObjectStream;
//------------------------------------------------------------------------
// XRef
//------------------------------------------------------------------------
+enum XRefEntryType {
+ xrefEntryFree,
+ xrefEntryUncompressed,
+ xrefEntryCompressed
+};
+
struct XRefEntry {
Guint offset;
int gen;
- GBool used;
+ XRefEntryType type;
};
class XRef {
@@ -81,6 +91,11 @@ public:
// Returns false if unknown or file is not damaged.
GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
+ // Direct access.
+ int getSize() { return size; }
+ XRefEntry *getEntry(int i) { return &entries[i]; }
+ Object *getTrailerDict() { return &trailerDict; }
+
private:
BaseStream *str; // input stream
@@ -96,6 +111,7 @@ private:
Guint *streamEnds; // 'endstream' positions - only used in
// damaged files
int streamEndsLen; // number of valid entries in streamEnds
+ ObjectStream *objStr; // cached object stream
#ifndef NO_DECRYPTION
GBool encrypted; // true if file is encrypted
int encVersion; // encryption algorithm
@@ -106,8 +122,11 @@ private:
GBool ownerPasswordOk; // true if owner password is correct
#endif
- Guint readTrailer();
+ Guint getStartXref();
GBool readXRef(Guint *pos);
+ GBool readXRefTable(Parser *parser, Guint *pos);
+ GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n);
+ GBool readXRefStream(Stream *xrefStr, Guint *pos);
GBool constructXRef();
GBool checkEncrypted(GString *ownerPassword, GString *userPassword);
Guint strToUnsigned(char *s);
diff --git a/pdf2swf/xpdf/aconf.h b/pdf2swf/xpdf/aconf.h
index d288e798..524cceed 100644
--- a/pdf2swf/xpdf/aconf.h
+++ b/pdf2swf/xpdf/aconf.h
@@ -19,5 +19,6 @@
// SELECT_TAKES_INT
// HAVE_FSEEK64
// HAVE_MKSTEMPS
+// HAVE_FSEEKO 1
#endif
diff --git a/pdf2swf/xpdf/config.h b/pdf2swf/xpdf/config.h
index 39cb2918..bf6baf4b 100644
--- a/pdf2swf/xpdf/config.h
+++ b/pdf2swf/xpdf/config.h
@@ -2,7 +2,7 @@
//
// config.h
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2004 Glyph & Cog, LLC
//
//========================================================================
@@ -14,15 +14,23 @@
//------------------------------------------------------------------------
// xpdf version
-
-#define xpdfVersion "1.01"
+#define xpdfVersion "3.00"
+#define xpdfVersionNum 3.00
+#define xpdfMajorVersion 3
+#define xpdfMinorVersion 0
+#define xpdfMajorVersionStr "3"
+#define xpdfMinorVersionStr "0"
// supported PDF version
-#define supportedPDFVersionStr "1.4"
-#define supportedPDFVersionNum 1.4
+#define supportedPDFVersionStr "1.5"
+#define supportedPDFVersionNum 1.5
// copyright notice
-#define xpdfCopyright "Copyright 1996-2002 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2004 Glyph & Cog, LLC"
+
+// Windows resource file stuff
+#define winxpdfVersion "WinXpdf 3.00"
+#define xpdfCopyrightAmp "Copyright 1996-2004 Glyph && Cog, LLC"
//------------------------------------------------------------------------
// paper size
@@ -74,46 +82,18 @@
// popen
//------------------------------------------------------------------------
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__BORLANDC__)
#define popen _popen
#define pclose _pclose
#endif
-#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(__CYGWIN32__) || defined(MACOS)
+#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS)
#define POPEN_READ_MODE "rb"
#else
#define POPEN_READ_MODE "r"
#endif
//------------------------------------------------------------------------
-// uncompress program
-//------------------------------------------------------------------------
-
-#ifdef HAVE_POPEN
-
-// command to uncompress to stdout
-# ifdef USE_GZIP
-# define uncompressCmd "gzip -d -c -q"
-# else
-# ifdef __EMX__
-# define uncompressCmd "compress -d -c"
-# else
-# define uncompressCmd "uncompress -c"
-# endif // __EMX__
-# endif // USE_GZIP
-
-#else // HAVE_POPEN
-
-// command to uncompress a file
-# ifdef USE_GZIP
-# define uncompressCmd "gzip -d -q"
-# else
-# define uncompressCmd "uncompress"
-# endif // USE_GZIP
-
-#endif // HAVE_POPEN
-
-//------------------------------------------------------------------------
// Win32 stuff
//------------------------------------------------------------------------
@@ -121,7 +101,7 @@
#undef CDECL
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__BORLANDC__)
#define CDECL __cdecl
#else
#define CDECL
diff --git a/pdf2swf/xpdf/gfile.cc b/pdf2swf/xpdf/gfile.cc
index b4d88cd1..11f5cf69 100644
--- a/pdf2swf/xpdf/gfile.cc
+++ b/pdf2swf/xpdf/gfile.cc
@@ -4,20 +4,13 @@
//
// Miscellaneous file and directory name manipulation.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
-#include "../../config.h"
-#ifdef WIN32
- extern "C" {
-//# ifndef _MSC_VER
-//# include <kpathsea/win32lib.h>
-//# endif
- }
-#else // !WIN32
+#ifndef WIN32
# if defined(MACOS)
# include <sys/stat.h>
# elif !defined(ACORN)
@@ -443,58 +436,11 @@ time_t getModTime(char *fileName) {
return statBuf.st_mtime;
#endif
}
-
-static char* getTempDir()
-{
-#ifdef WIN32
- char*dir = getenv("TMP");
- if(!dir) dir = getenv("TEMP");
- if(!dir) dir = getenv("tmp");
- if(!dir) dir = getenv("temp");
- if(!dir) dir = "C:\\";
-#else
- char* dir = "/tmp/";
-#endif
- return dir;
-}
-
-char* mktmpname(char*ptr) {
- static char tmpbuf[128];
- char*dir = getTempDir();
- int l = strlen(dir);
- char*sep = "";
- if(!ptr)
- ptr = tmpbuf;
- if(l && dir[l-1]!='/' && dir[l-1]!='\\') {
-#ifdef WIN32
- sep = "\\";
-#else
- sep = "/";
-#endif
- }
-
- // used to be mktemp. This does remove the warnings, but
- // It's not exactly an improvement.
-#ifdef HAVE_LRAND48
- sprintf(ptr, "%s%s%08x%08x",dir,sep,lrand48(),lrand48());
-#else
-# ifdef HAVE_RAND
- sprintf(ptr, "%s%s%08x%08x",dir,sep,rand(),rand());
-# else
- static int count = 1;
- sprintf(ptr, "%s%s%08x%04x%04x",dir,sep,time(0),(unsigned int)tmpbuf^((unsigned int)tmpbuf)>>16,count);
- count ++;
-# endif
-#endif
- return ptr;
-}
GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
#if defined(WIN32)
//---------- Win32 ----------
char *s;
- char buf[_MAX_PATH];
- char *fp;
if (!(s = _tempnam(getenv("TEMP"), NULL))) {
return gFalse;
@@ -517,7 +463,7 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
// with this file name after the tmpnam call and before the fopen
// call. I will happily accept fixes to this function for non-Unix
// OSs.
- if (!(s = mktmpname(NULL))) { //was: tmpnam
+ if (!(s = tmpnam(NULL))) {
return gFalse;
}
*name = new GString(s);
@@ -544,7 +490,7 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
(*name)->append("/XXXXXX")->append(ext);
fd = mkstemps((*name)->getCString(), strlen(ext));
#else
- if (!(s = mktmpname(NULL))) { //was: tmpnam
+ if (!(s = tmpnam(NULL))) {
return gFalse;
}
*name = new GString(s);
@@ -561,7 +507,7 @@ GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
(*name)->append("/XXXXXX");
fd = mkstemp((*name)->getCString());
#else // HAVE_MKSTEMP
- if (!(s = mktmpname(NULL))) { //was: tmpnam
+ if (!(s = tmpnam(NULL))) {
return gFalse;
}
*name = new GString(s);
@@ -692,36 +638,48 @@ GDir::~GDir() {
}
GDirEntry *GDir::getNextEntry() {
- struct dirent *ent;
GDirEntry *e;
- e = NULL;
#if defined(WIN32)
- e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
- if (hnd && !FindNextFile(hnd, &ffd)) {
- FindClose(hnd);
- hnd = NULL;
+ if (hnd) {
+ e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
+ if (hnd && !FindNextFile(hnd, &ffd)) {
+ FindClose(hnd);
+ hnd = NULL;
+ }
+ } else {
+ e = NULL;
}
#elif defined(ACORN)
#elif defined(MACOS)
-#else
+#elif defined(VMS)
+ struct dirent *ent;
+ e = NULL;
if (dir) {
-#ifdef VMS
if (needParent) {
e = new GDirEntry(path->getCString(), "-", doStat);
needParent = gFalse;
return e;
}
-#endif
ent = readdir(dir);
-#ifndef VMS
- if (ent && !strcmp(ent->d_name, "."))
+ if (ent) {
+ e = new GDirEntry(path->getCString(), ent->d_name, doStat);
+ }
+ }
+#else
+ struct dirent *ent;
+ e = NULL;
+ if (dir) {
+ ent = readdir(dir);
+ if (ent && !strcmp(ent->d_name, ".")) {
ent = readdir(dir);
-#endif
- if (ent)
+ }
+ if (ent) {
e = new GDirEntry(path->getCString(), ent->d_name, doStat);
+ }
}
#endif
+
return e;
}
@@ -734,6 +692,7 @@ void GDir::rewind() {
tmp = path->copy();
tmp->append("/*.*");
hnd = FindFirstFile(tmp->getCString(), &ffd);
+ delete tmp;
#elif defined(ACORN)
#elif defined(MACOS)
#else
diff --git a/pdf2swf/xpdf/gfile.h b/pdf2swf/xpdf/gfile.h
index aa5e9d8c..82f1d7a9 100644
--- a/pdf2swf/xpdf/gfile.h
+++ b/pdf2swf/xpdf/gfile.h
@@ -4,7 +4,7 @@
//
// Miscellaneous file and directory name manipulation.
//
-// Copyright 1996-2002 Glyph & Cog, LLC
+// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
@@ -14,14 +14,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
-#include "./aconf.h"
#if defined(WIN32)
# include <sys/stat.h>
# ifdef FPTEX
# include <win32lib.h>
# else
# include <windows.h>
-# include <winbase.h>
# endif
#elif defined(ACORN)
#elif defined(MACOS)
@@ -137,7 +135,4 @@ private:
#endif
};
-/* create a temporary filename */
-char* mktmpname(char*ptr);
-
#endif
diff --git a/pdf2swf/xpdf/gmem.h b/pdf2swf/xpdf/gmem.h
index 93ccb94b..587e7fa4 100644
--- a/pdf2swf/xpdf/gmem.h
+++ b/pdf2swf/xpdf/gmem.h
@@ -3,7 +3,7 @@
*
* Memory routines with out-of-memory checking.
*
- * Copyright 1996-2002 Glyph & Cog, LLC
+ * Copyright 1996-2003 Glyph & Cog, LLC
*/
#ifndef GMEM_H
diff --git a/pdf2swf/xpdf/gtypes.h b/pdf2swf/xpdf/gtypes.h
index 1879b88b..9f64f57d 100644
--- a/pdf2swf/xpdf/gtypes.h
+++ b/pdf2swf/xpdf/gtypes.h
@@ -3,7 +3,7 @@
*
* Some useful simple types.
*
- * Copyright 1996-2002 Glyph & Cog, LLC
+ * Copyright 1996-2003 Glyph & Cog, LLC
*/
#ifndef GTYPES_H