Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'pdf')
-rw-r--r--pdf/goo/GHash.cc167
-rw-r--r--pdf/goo/GHash.h7
-rw-r--r--pdf/xpdf/DisplayFontTable.h29
-rw-r--r--pdf/xpdf/ErrorCodes.h2
-rw-r--r--pdf/xpdf/FTFont.cc703
-rw-r--r--pdf/xpdf/FTFont.h134
-rw-r--r--pdf/xpdf/FontFile.cc4113
-rw-r--r--pdf/xpdf/FontFile.h261
-rw-r--r--pdf/xpdf/Function.h4
-rw-r--r--pdf/xpdf/Gfx.cc28
-rw-r--r--pdf/xpdf/Gfx.h2
-rw-r--r--pdf/xpdf/GfxFont.cc104
-rw-r--r--pdf/xpdf/GfxFont.h4
-rw-r--r--pdf/xpdf/GfxState.cc37
-rw-r--r--pdf/xpdf/GfxState.h2
-rw-r--r--pdf/xpdf/GlobalParams.cc358
-rw-r--r--pdf/xpdf/GlobalParams.h55
-rw-r--r--pdf/xpdf/Makefile.am33
-rw-r--r--pdf/xpdf/Object.cc7
-rw-r--r--pdf/xpdf/Object.h1
-rw-r--r--pdf/xpdf/Outline.cc19
-rw-r--r--pdf/xpdf/OutputDev.cc3
-rw-r--r--pdf/xpdf/OutputDev.h3
-rw-r--r--pdf/xpdf/PBMOutputDev.cc162
-rw-r--r--pdf/xpdf/PBMOutputDev.h64
-rw-r--r--pdf/xpdf/PDFDoc.cc18
-rw-r--r--pdf/xpdf/PDFDoc.h9
-rw-r--r--pdf/xpdf/PSOutputDev.cc576
-rw-r--r--pdf/xpdf/PSOutputDev.h34
-rw-r--r--pdf/xpdf/Page.cc10
-rw-r--r--pdf/xpdf/Page.h6
-rw-r--r--pdf/xpdf/Parser.cc2
-rw-r--r--pdf/xpdf/SFont.cc81
-rw-r--r--pdf/xpdf/SFont.h142
-rw-r--r--pdf/xpdf/Stream.cc84
-rw-r--r--pdf/xpdf/Stream.h23
-rw-r--r--pdf/xpdf/T1Font.cc566
-rw-r--r--pdf/xpdf/T1Font.h111
-rw-r--r--pdf/xpdf/TTFont.cc485
-rw-r--r--pdf/xpdf/TTFont.h127
-rw-r--r--pdf/xpdf/TextOutputDev.cc108
-rw-r--r--pdf/xpdf/TextOutputDev.h5
-rw-r--r--pdf/xpdf/XOutputDev.cc3986
-rw-r--r--pdf/xpdf/XOutputDev.h680
-rw-r--r--pdf/xpdf/XPixmapOutputDev.cc84
-rw-r--r--pdf/xpdf/XPixmapOutputDev.h63
-rw-r--r--pdf/xpdf/XRef.cc655
-rw-r--r--pdf/xpdf/XRef.h16
-rw-r--r--pdf/xpdf/pdffonts.cc18
-rw-r--r--pdf/xpdf/pdfimages.cc2
-rw-r--r--pdf/xpdf/pdfinfo.cc37
-rw-r--r--pdf/xpdf/pdftopbm.cc147
-rw-r--r--pdf/xpdf/pdftops.cc81
-rw-r--r--pdf/xpdf/pdftotext.cc2
-rw-r--r--pdf/xpdf/vms_make.com6
-rw-r--r--pdf/xpdf/xpdf.cc39
-rw-r--r--pdf/xpdf/xpdfconfig.h24
57 files changed, 1814 insertions, 12715 deletions
diff --git a/pdf/goo/GHash.cc b/pdf/goo/GHash.cc
index 7036316..1dd0e26 100644
--- a/pdf/goo/GHash.cc
+++ b/pdf/goo/GHash.cc
@@ -20,7 +20,10 @@
struct GHashBucket {
GString *key;
- void *val;
+ union {
+ void *p;
+ int i;
+ } val;
GHashBucket *next;
};
@@ -61,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.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 = val;
+ p->val.i = val;
h = hash(key);
p->next = tab[h];
tab[h] = p;
@@ -103,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) {
@@ -113,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) {
@@ -133,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;
@@ -156,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;
@@ -184,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;
}
@@ -193,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/pdf/goo/GHash.h b/pdf/goo/GHash.h
index 69c767b..4a6e08d 100644
--- a/pdf/goo/GHash.h
+++ b/pdf/goo/GHash.h
@@ -29,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/pdf/xpdf/DisplayFontTable.h b/pdf/xpdf/DisplayFontTable.h
deleted file mode 100644
index 3c2379f..0000000
--- a/pdf/xpdf/DisplayFontTable.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//========================================================================
-//
-// DisplayFontTable.h
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-static struct {
- char *name;
- char *xlfd;
- char *encoding;
-} displayFontTab[] = {
- {"Courier", "-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Courier-Bold", "-*-courier-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Courier-BoldOblique", "-*-courier-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Courier-Oblique", "-*-courier-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Helvetica", "-*-helvetica-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Helvetica-Bold", "-*-helvetica-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Helvetica-BoldOblique", "-*-helvetica-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Helvetica-Oblique", "-*-helvetica-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Symbol", "-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", "Symbol"},
- {"Times-Bold", "-*-times-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Times-BoldItalic", "-*-times-bold-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Times-Italic", "-*-times-medium-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"Times-Roman", "-*-times-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
- {"ZapfDingbats", "-*-zapfdingbats-medium-r-normal-*-%s-*-*-*-*-*-*-*", "ZapfDingbats"},
- {NULL}
-};
diff --git a/pdf/xpdf/ErrorCodes.h b/pdf/xpdf/ErrorCodes.h
index 6eb1435..b28528d 100644
--- a/pdf/xpdf/ErrorCodes.h
+++ b/pdf/xpdf/ErrorCodes.h
@@ -31,4 +31,6 @@
#define errBadPageNum 9 // invalid page number
+#define errFileIO 10 // file I/O error
+
#endif
diff --git a/pdf/xpdf/FTFont.cc b/pdf/xpdf/FTFont.cc
deleted file mode 100644
index 1a5ecfa..0000000
--- a/pdf/xpdf/FTFont.cc
+++ /dev/null
@@ -1,703 +0,0 @@
-//========================================================================
-//
-// FTFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <math.h>
-#include <string.h>
-#include "gmem.h"
-#include "freetype/ftoutln.h"
-#include "freetype/internal/ftobjs.h"
-#if 1 //~ cff cid->gid map
-#include "freetype/internal/cfftypes.h"
-#include "freetype/internal/tttypes.h"
-#endif
-#include "GlobalParams.h"
-#include "GfxState.h"
-#include "FTFont.h"
-
-//------------------------------------------------------------------------
-
-FTFontEngine::FTFontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA, GBool aaA):
- SFontEngine(displayA, visualA, depthA, colormapA) {
-
- ok = gFalse;
- if (FT_Init_FreeType(&lib)) {
- return;
- }
- aa = aaA;
- ok = gTrue;
-}
-
-FTFontEngine::~FTFontEngine() {
- FT_Done_FreeType(lib);
-}
-
-//------------------------------------------------------------------------
-
-FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
- char **fontEnc, Gushort *codeToGID) {
- char *name;
- int i;
-
- ok = gFalse;
- engine = engineA;
- codeMap = NULL;
- cidToGID = NULL;
- cidToGIDLen = 0;
-
- if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
- return;
- }
-
- if (!strcmp(face->driver->root.clazz->module_name, "type1") ||
- !strcmp(face->driver->root.clazz->module_name, "cff")) {
- mode = ftFontModeCodeMapDirect;
- codeMap = (Guint *)gmalloc(256 * sizeof(Guint));
- for (i = 0; i < 256; ++i) {
- codeMap[i] = 0;
- if ((name = fontEnc[i])) {
- codeMap[i] = FT_Get_Name_Index(face, name);
- }
- }
-
- } else {
- mode = ftFontModeCodeMapDirect;
- codeMap = (Guint *)gmalloc(256 * sizeof(Guint));
- for (i = 0; i < 256; ++i) {
- codeMap[i] = (int)codeToGID[i];
- }
- }
-
- ok = gTrue;
-}
-
-FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
- Gushort *cidToGIDA, int cidToGIDLenA, GBool embedded) {
- int i;
-
- ok = gFalse;
- engine = engineA;
- codeMap = NULL;
- cidToGID = NULL;
- cidToGIDLen = 0;
-
- if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
- return;
- }
- cidToGIDLen = cidToGIDLenA;
- cidToGID = (Gushort *)gmalloc(cidToGIDLen * sizeof(Gushort));
- memcpy(cidToGID, cidToGIDA, cidToGIDLen * sizeof(Gushort));
- if (!strcmp(face->driver->root.clazz->module_name, "t1cid")) {
- mode = ftFontModeCID;
- } else if (!strcmp(face->driver->root.clazz->module_name, "cff")) {
- mode = ftFontModeCFFCharset;
- } else if (embedded) {
- mode = ftFontModeCIDToGIDMap;
- } else {
- mode = ftFontModeUnicode;
- for (i = 0; i < face->num_charmaps; ++i) {
- if ((face->charmaps[i]->platform_id == 3 &&
- face->charmaps[i]->encoding_id == 1) ||
- face->charmaps[i]->platform_id == 0) {
- break;
- }
- }
- if (i == face->num_charmaps) {
- i = 0;
- }
- FT_Set_Charmap(face, face->charmaps[i]);
- }
- ok = gTrue;
-}
-
-FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
- GBool embedded) {
- int i;
-
- ok = gFalse;
- engine = engineA;
- codeMap = NULL;
- cidToGID = NULL;
- cidToGIDLen = 0;
-
- if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
- return;
- }
- if (!strcmp(face->driver->root.clazz->module_name, "t1cid")) {
- mode = ftFontModeCID;
- } else if (embedded) {
- mode = ftFontModeCFFCharset;
- } else {
- mode = ftFontModeUnicode;
- for (i = 0; i < face->num_charmaps; ++i) {
- if ((face->charmaps[i]->platform_id == 3 &&
- face->charmaps[i]->encoding_id == 1) ||
- face->charmaps[i]->platform_id == 0) {
- break;
- }
- }
- if (i == face->num_charmaps) {
- i = 0;
- }
- FT_Set_Charmap(face, face->charmaps[i]);
- }
- ok = gTrue;
-}
-
-FTFontFile::~FTFontFile() {
- if (face) {
- FT_Done_Face(face);
- }
- if (codeMap) {
- gfree(codeMap);
- }
- if (cidToGID) {
- gfree(cidToGID);
- }
-}
-
-//------------------------------------------------------------------------
-
-FTFont::FTFont(FTFontFile *fontFileA, double *m) {
- FTFontEngine *engine;
- FT_Face face;
- double size, div;
- int x, xMin, xMax;
- int y, yMin, yMax;
- int i;
-
- ok = gFalse;
- fontFile = fontFileA;
- engine = fontFile->engine;
- face = fontFile->face;
- if (FT_New_Size(face, &sizeObj)) {
- return;
- }
- face->size = sizeObj;
- size = sqrt(m[2]*m[2] + m[3]*m[3]);
- if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
- return;
- }
-
- div = face->bbox.xMax > 20000 ? 65536 : 1;
-
- // transform the four corners of the font bounding box -- the min
- // and max values form the bounding box of the transformed font
- x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMin) /
- (div * face->units_per_EM));
- xMin = xMax = x;
- y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMin) /
- (div * face->units_per_EM));
- yMin = yMax = y;
- x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMax) /
- (div * face->units_per_EM));
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMax) /
- (div * face->units_per_EM));
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMin) /
- (div * face->units_per_EM));
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMin) /
- (div * face->units_per_EM));
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMax) /
- (div * face->units_per_EM));
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMax) /
- (div * face->units_per_EM));
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- // This is a kludge: some buggy PDF generators embed fonts with
- // zero bounding boxes.
- if (xMax == xMin) {
- xMin = 0;
- xMax = (int)size;
- }
- if (yMax == yMin) {
- yMin = 0;
- yMax = (int)(1.2 * size);
- }
- // this should be (max - min + 1), but we add some padding to
- // deal with rounding errors, bogus bboxes, etc.
- glyphW = xMax - xMin + 3;
- glyphW += glyphW >> 1;
- glyphH = yMax - yMin + 3;
- glyphH += glyphH >> 1;
- if (engine->aa) {
- glyphSize = glyphW * glyphH;
- } else {
- glyphSize = ((glyphW + 7) >> 3) * glyphH;
- }
-
- // set up the glyph pixmap cache
- cacheAssoc = 8;
- if (glyphSize <= 256) {
- cacheSets = 8;
- } else if (glyphSize <= 512) {
- cacheSets = 4;
- } else if (glyphSize <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
- cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
- cacheTags = (FTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
- sizeof(FTFontCacheTag));
- for (i = 0; i < cacheSets * cacheAssoc; ++i) {
- cacheTags[i].mru = i & (cacheAssoc - 1);
- }
-
- // create the XImage
- if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
- ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
- return;
- }
- image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
-
- // compute the transform matrix
- matrix.xx = (FT_Fixed)((m[0] / size) * 65536);
- matrix.yx = (FT_Fixed)((m[1] / size) * 65536);
- matrix.xy = (FT_Fixed)((m[2] / size) * 65536);
- matrix.yy = (FT_Fixed)((m[3] / size) * 65536);
-
- ok = gTrue;
-}
-
-FTFont::~FTFont() {
- gfree(cacheTags);
- gfree(cache);
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
-}
-
-GBool FTFont::drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u) {
- FTFontEngine *engine;
- XColor xcolor;
- int bgR, bgG, bgB;
- Gulong colors[5];
- Guchar *bitmap, *p;
- GBool tempBitmap;
- XImage *img;
- int pix;
- int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
- int xx, yy, xx1;
-
- engine = fontFile->engine;
-
- // no Unicode index for this char - don't draw anything
- if (fontFile->mode == ftFontModeUnicode && u == 0) {
- return gFalse;
- }
-
- // generate the glyph pixmap
- if (!(bitmap = getGlyphPixmap(c, u, &xOffset, &yOffset, &gw, &gh,
- &tempBitmap))) {
- return gFalse;
- }
-
- // compute: (x0,y0) = position in destination drawable
- // (x1,y1) = position in glyph image
- // (w0,h0) = size of image transfer
- x0 = x - xOffset;
- y0 = y - yOffset;
- x1 = 0;
- y1 = 0;
- w0 = gw;
- h0 = gh;
- if (x0 < 0) {
- x1 = -x0;
- w0 += x0;
- x0 = 0;
- }
- if (x0 + w0 > w) {
- w0 = w - x0;
- }
- if (w0 < 0) {
- goto done;
- }
- if (y0 < 0) {
- y1 = -y0;
- h0 += y0;
- y0 = 0;
- }
- if (y0 + h0 > h) {
- h0 = h - y0;
- }
- if (h0 < 0) {
- goto done;
- }
-
- // getGlyphPixmap may have returned a larger-than-cache-entry
- // bitmap, in which case we need to allocate a temporary XImage here
- if (tempBitmap) {
- if (!(img = XCreateImage(engine->display, engine->visual, engine->depth,
- ZPixmap, 0, NULL, gw, gh, 8, 0))) {
- goto done;
- }
- img->data = (char *)gmalloc(gh * img->bytes_per_line);
- } else {
- img = image;
- }
-
- // read the X image
- XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
- ZPixmap, img, x1, y1);
-
- if (engine->aa) {
-
- // compute the colors
- xcolor.pixel = XGetPixel(img, x1 + w0/2, y1 + h0/2);
- XQueryColor(engine->display, engine->colormap, &xcolor);
- bgR = xcolor.red;
- bgG = xcolor.green;
- bgB = xcolor.blue;
- colors[1] = engine->findColor((r + 3*bgR) / 4,
- (g + 3*bgG) / 4,
- (b + 3*bgB) / 4);
- colors[2] = engine->findColor((r + bgR) / 2,
- (g + bgG) / 2,
- (b + bgB) / 2);
- colors[3] = engine->findColor((3*r + bgR) / 4,
- (3*g + bgG) / 4,
- (3*b + bgB) / 4);
- colors[4] = engine->findColor(r, g, b);
-
- // stuff the glyph pixmap into the X image
- p = bitmap;
- for (yy = 0; yy < gh; ++yy) {
- for (xx = 0; xx < gw; ++xx) {
- pix = *p++ & 0xff;
- // this is a heuristic which seems to produce decent
- // results -- the linear mapping would be:
- // pix = (pix * 5) / 256;
- pix = ((pix + 10) * 5) / 256;
- if (pix > 4) {
- pix = 4;
- }
- if (pix > 0) {
- XPutPixel(img, xx, yy, colors[pix]);
- }
- }
- }
-
- } else {
-
- // one color
- colors[1] = engine->findColor(r, g, b);
-
- // stuff the glyph bitmap into the X image
- p = bitmap;
- for (yy = 0; yy < gh; ++yy) {
- for (xx = 0; xx < gw; xx += 8) {
- pix = *p++;
- for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
- if (pix & 0x80) {
- XPutPixel(img, xx1, yy, colors[1]);
- }
- pix <<= 1;
- }
- }
- }
-
- }
-
- // draw the X image
- XPutImage(engine->display, d, gc, img, x1, y1, x0, y0, w0, h0);
-
- if (tempBitmap) {
- gfree(img->data);
- img->data = NULL;
- XDestroyImage(img);
- }
- done:
- if (tempBitmap) {
- gfree(bitmap);
- }
- return gTrue;
-}
-
-Guchar *FTFont::getGlyphPixmap(CharCode c, Unicode u,
- int *x, int *y, int *w, int *h,
- GBool *tempBitmap) {
- FT_GlyphSlot slot;
- FT_UInt idx;
- int rowSize;
- int i, j, k;
- Guchar *ret, *p, *q;
-
- // check the cache
- i = (c & (cacheSets - 1)) * cacheAssoc;
- for (j = 0; j < cacheAssoc; ++j) {
- if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
- *x = cacheTags[i+j].x;
- *y = cacheTags[i+j].y;
- *w = cacheTags[i+j].w;
- *h = cacheTags[i+j].h;
- for (k = 0; k < cacheAssoc; ++k) {
- if (k != j &&
- (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
- ++cacheTags[i+k].mru;
- }
- }
- cacheTags[i+j].mru = 0x8000;
- *tempBitmap = gFalse;
- return cache + (i+j) * glyphSize;
- }
- }
-
- // generate the glyph pixmap or bitmap
- fontFile->face->size = sizeObj;
- FT_Set_Transform(fontFile->face, &matrix, NULL);
- slot = fontFile->face->glyph;
- idx = getGlyphIndex(c, u);
- // if we have the FT2 bytecode interpreter, autohinting won't be used
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- if (FT_Load_Glyph(fontFile->face, idx,
- fontFile->engine->aa ? FT_LOAD_NO_BITMAP
- : FT_LOAD_DEFAULT)) {
- return gFalse;
- }
-#else
- // FT2's autohinting doesn't always work very well (especially with
- // font subsets), so turn it off if anti-aliasing is enabled; if
- // anti-aliasing is disabled, this seems to be a tossup - some fonts
- // look better with hinting, some without, so leave hinting on
- if (FT_Load_Glyph(fontFile->face, idx,
- fontFile->engine->aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP
- : FT_LOAD_DEFAULT)) {
- return gFalse;
- }
-#endif
- if (FT_Render_Glyph(slot,
- fontFile->engine->aa ? ft_render_mode_normal :
- ft_render_mode_mono)) {
- return gFalse;
- }
-
- // copy the glyph into the cache or a temporary bitmap
- *x = -slot->bitmap_left;
- *y = slot->bitmap_top;
- *w = slot->bitmap.width;
- *h = slot->bitmap.rows;
- if (fontFile->engine->aa) {
- rowSize = *w;
- } else {
- rowSize = (*w + 7) >> 3;
- }
- if (*w > glyphW || *h > glyphH) {
- // the glyph doesn't fit in the bounding box -- return a
- // temporary, uncached bitmap (this shouldn't happen but some
- // fonts have incorrect bboxes)
- ret = (Guchar *)gmalloc(*h * rowSize);
- *tempBitmap = gTrue;
- } else {
- // store glyph pixmap in cache
- ret = NULL; // make gcc happy
- for (j = 0; j < cacheAssoc; ++j) {
- if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
- cacheTags[i+j].mru = 0x8000;
- cacheTags[i+j].code = c;
- cacheTags[i+j].x = *x;
- cacheTags[i+j].y = *y;
- cacheTags[i+j].w = *w;
- cacheTags[i+j].h = *h;
- ret = cache + (i+j) * glyphSize;
- } else {
- ++cacheTags[i+j].mru;
- }
- }
- *tempBitmap = gFalse;
- }
- for (k = 0, p = ret, q = slot->bitmap.buffer;
- k < slot->bitmap.rows;
- ++k, p += rowSize, q += slot->bitmap.pitch) {
- memcpy(p, q, rowSize);
- }
- return ret;
-}
-
-GBool FTFont::getCharPath(CharCode c, Unicode u, GfxState *state) {
- static FT_Outline_Funcs outlineFuncs = {
- &charPathMoveTo,
- &charPathLineTo,
- &charPathConicTo,
- &charPathCubicTo,
- 0, 0
- };
- FT_GlyphSlot slot;
- FT_UInt idx;
- FT_Glyph glyph;
-
- fontFile->face->size = sizeObj;
- FT_Set_Transform(fontFile->face, &matrix, NULL);
- slot = fontFile->face->glyph;
- idx = getGlyphIndex(c, u);
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) {
- return gFalse;
- }
-#else
- // FT2's autohinting doesn't always work very well (especially with
- // font subsets), so turn it off if anti-aliasing is enabled; if
- // anti-aliasing is disabled, this seems to be a tossup - some fonts
- // look better with hinting, some without, so leave hinting on
- if (FT_Load_Glyph(fontFile->face, idx,
- fontFile->engine->aa ? FT_LOAD_NO_HINTING
- : FT_LOAD_DEFAULT)) {
- return gFalse;
- }
-#endif
- if (FT_Get_Glyph(slot, &glyph)) {
- return gFalse;
- }
- FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
- &outlineFuncs, state);
- return gTrue;
-}
-
-int FTFont::charPathMoveTo(FT_Vector *pt, void *state) {
- ((GfxState *)state)->moveTo(pt->x / 64.0, -pt->y / 64.0);
- return 0;
-}
-
-int FTFont::charPathLineTo(FT_Vector *pt, void *state) {
- ((GfxState *)state)->lineTo(pt->x / 64.0, -pt->y / 64.0);
- return 0;
-}
-
-int FTFont::charPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *state) {
- double x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
-
- x0 = ((GfxState *)state)->getCurX();
- y0 = ((GfxState *)state)->getCurY();
- xc = ctrl->x / 64.0;
- yc = -ctrl->y / 64.0;
- x3 = pt->x / 64.0;
- y3 = -pt->y / 64.0;
-
- // A second-order Bezier curve is defined by two endpoints, p0 and
- // p3, and one control point, pc:
- //
- // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
- //
- // A third-order Bezier curve is defined by the same two endpoints,
- // p0 and p3, and two control points, p1 and p2:
- //
- // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
- //
- // Applying some algebra, we can convert a second-order curve to a
- // third-order curve:
- //
- // p1 = (1/3) * (p0 + 2pc)
- // p2 = (1/3) * (2pc + p3)
-
- x1 = (1.0 / 3.0) * (x0 + 2 * xc);
- y1 = (1.0 / 3.0) * (y0 + 2 * yc);
- x2 = (1.0 / 3.0) * (2 * xc + x3);
- y2 = (1.0 / 3.0) * (2 * yc + y3);
-
- ((GfxState *)state)->curveTo(x1, y1, x2, y2, x3, y3);
- return 0;
-}
-
-int FTFont::charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
- FT_Vector *pt, void *state) {
- ((GfxState *)state)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
- ctrl2->x / 64.0, -ctrl2->y / 64.0,
- pt->x / 64.0, -pt->y / 64.0);
- return 0;
-}
-
-FT_UInt FTFont::getGlyphIndex(CharCode c, Unicode u) {
- FT_UInt idx;
- int j;
-
- idx = 0; // make gcc happy
- switch (fontFile->mode) {
- case ftFontModeUnicode:
- idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)u);
- break;
- case ftFontModeCodeMapDirect:
- if (c <= 0xff) {
- idx = (FT_UInt)fontFile->codeMap[c];
- } else {
- idx = 0;
- }
- break;
- case ftFontModeCIDToGIDMap:
- if (fontFile->cidToGIDLen) {
- if ((int)c < fontFile->cidToGIDLen) {
- idx = (FT_UInt)fontFile->cidToGID[c];
- } else {
- idx = (FT_UInt)0;
- }
- } else {
- idx = (FT_UInt)c;
- }
- break;
- case ftFontModeCFFCharset:
-#if 1 //~ cff cid->gid map
- {
-#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0
- CFF_Font *cff = (CFF_Font *)((TT_Face)fontFile->face)->extra.data;
-#else
- CFF_Font cff = (CFF_Font)((TT_Face)fontFile->face)->extra.data;
-#endif
- idx = 0;
- for (j = 0; j < (int)cff->num_glyphs; ++j) {
- if (cff->charset.sids[j] == c) {
- idx = j;
- break;
- }
- }
- }
-#endif
- break;
- case ftFontModeCID:
- idx = c;
- break;
- }
- return idx;
-}
-
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
diff --git a/pdf/xpdf/FTFont.h b/pdf/xpdf/FTFont.h
deleted file mode 100644
index 8da5558..0000000
--- a/pdf/xpdf/FTFont.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//========================================================================
-//
-// FTFont.h
-//
-// An X wrapper for the FreeType font rasterizer.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FTFONT_H
-#define FTFONT_H
-
-#include <aconf.h>
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <freetype/freetype.h>
-#include "CharTypes.h"
-#include "SFont.h"
-
-//------------------------------------------------------------------------
-
-class FTFontEngine: public SFontEngine {
-public:
-
- FTFontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA, GBool aaA);
- GBool isOk() { return ok; }
- virtual ~FTFontEngine();
-
-private:
-
- FT_Library lib;
- GBool aa;
- Gulong palette[5];
- GBool ok;
-
- friend class FTFontFile;
- friend class FTFont;
-};
-
-//------------------------------------------------------------------------
-
-enum FTFontIndexMode {
- ftFontModeUnicode,
- ftFontModeCodeMapDirect,
- ftFontModeCIDToGIDMap,
- ftFontModeCFFCharset,
- ftFontModeCID
-};
-
-class FTFontFile: public SFontFile {
-public:
-
- // 8-bit font, TrueType or Type 1/1C
- FTFontFile(FTFontEngine *engineA, char *fontFileName,
- char **fontEnc, Gushort *codeToGID);
-
- // CID font, TrueType
- FTFontFile(FTFontEngine *engineA, char *fontFileName,
- Gushort *cidToGIDA, int cidToGIDLenA, GBool embedded);
-
- // CID font, Type 0C (CFF)
- FTFontFile(FTFontEngine *engineA, char *fontFileName,
- GBool embedded);
-
- GBool isOk() { return ok; }
- virtual ~FTFontFile();
-
-private:
-
- FTFontEngine *engine;
- FT_Face face;
- FTFontIndexMode mode;
- Guint *codeMap;
- Gushort *cidToGID;
- int cidToGIDLen;
- GBool ok;
-
- friend class FTFont;
-};
-
-//------------------------------------------------------------------------
-
-struct FTFontCacheTag {
- Gushort code;
- Gushort mru; // valid bit (0x8000) and MRU index
- int x, y, w, h; // offset and size of glyph
-};
-
-class FTFont: public SFont {
-public:
-
- FTFont(FTFontFile *fontFileA, double *m);
- GBool isOk() { return ok; }
- virtual ~FTFont();
- virtual GBool drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u);
- virtual GBool getCharPath(CharCode c, Unicode u, GfxState *state);
-
-private:
-
- Guchar *getGlyphPixmap(CharCode c, Unicode u,
- int *x, int *y, int *w, int *h,
- GBool *tempBitmap);
- static int charPathMoveTo(FT_Vector *pt, void *state);
- static int charPathLineTo(FT_Vector *pt, void *state);
- static int charPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *state);
- static int charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
- FT_Vector *pt, void *state);
- FT_UInt getGlyphIndex(CharCode c, Unicode u);
-
- FTFontFile *fontFile;
- FT_Size sizeObj;
- XImage *image;
- FT_Matrix matrix;
- int glyphW, glyphH; // size of glyph pixmaps
- int glyphSize; // size of glyph pixmaps, in bytes
- Guchar *cache; // glyph pixmap cache
- FTFontCacheTag *cacheTags; // cache tags, i.e., char codes
- int cacheSets; // number of sets in cache
- int cacheAssoc; // cache associativity (glyphs per set)
- GBool ok;
-};
-
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#endif
diff --git a/pdf/xpdf/FontFile.cc b/pdf/xpdf/FontFile.cc
deleted file mode 100644
index 0c44422..0000000
--- a/pdf/xpdf/FontFile.cc
+++ /dev/null
@@ -1,4113 +0,0 @@
-//========================================================================
-//
-// FontFile.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <locale.h>
-#include <math.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "GHash.h"
-#include "Error.h"
-#include "GlobalParams.h"
-#include "CharCodeToUnicode.h"
-#include "FontEncodingTables.h"
-#include "FontFile.h"
-
-#include "CompactFontTables.h"
-
-//------------------------------------------------------------------------
-
-static inline char *nextLine(char *line, char *end) {
- while (line < end && *line != '\n' && *line != '\r')
- ++line;
- while (line < end && (*line == '\n' || *line == '\r'))
- ++line;
- return line;
-}
-
-static char hexChars[17] = "0123456789ABCDEF";
-
-//------------------------------------------------------------------------
-// FontFile
-//------------------------------------------------------------------------
-
-FontFile::FontFile() {
-}
-
-FontFile::~FontFile() {
-}
-
-//------------------------------------------------------------------------
-// Type1FontFile
-//------------------------------------------------------------------------
-
-Type1FontFile::Type1FontFile(char *file, int len) {
- char *line, *line1, *p, *p2;
- GBool haveEncoding;
- char buf[256];
- char c;
- int n, code, i, j;
-
- name = NULL;
- encoding = (char **)gmalloc(256 * sizeof(char *));
- for (i = 0; i < 256; ++i) {
- encoding[i] = NULL;
- }
- haveEncoding = gFalse;
-
- for (i = 1, line = file;
- i <= 100 && line < file + len && !haveEncoding;
- ++i) {
-
- // get font name
- if (!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 = nextLine(line, file + len);
-
- // get encoding
- } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
- for (j = 0; j < 256; ++j) {
- if (standardEncoding[j]) {
- encoding[j] = copyString(standardEncoding[j]);
- }
- }
- haveEncoding = gTrue;
- } else if (!strncmp(line, "/Encoding 256 array", 19)) {
- for (j = 0; j < 300; ++j) {
- line1 = nextLine(line, file + len);
- 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
- haveEncoding = gTrue;
-
- } else {
- line = nextLine(line, file + len);
- }
- }
-}
-
-Type1FontFile::~Type1FontFile() {
- int i;
-
- if (name) {
- gfree(name);
- }
- for (i = 0; i < 256; ++i) {
- gfree(encoding[i]);
- }
- gfree(encoding);
-}
-
-//------------------------------------------------------------------------
-// Type1CFontFile
-//------------------------------------------------------------------------
-
-struct Type1CTopDict {
- int version;
- int notice;
- int copyright;
- int fullName;
- int familyName;
- int weight;
- int isFixedPitch;
- double italicAngle;
- double underlinePosition;
- double underlineThickness;
- int paintType;
- int charstringType;
- double fontMatrix[6];
- int uniqueID;
- double fontBBox[4];
- double strokeWidth;
- int charset;
- int encoding;
- int charStrings;
- int privateSize;
- int privateOffset;
-
- //----- CIDFont entries
- int registry;
- int ordering;
- int supplement;
- int fdArrayOffset;
- int fdSelectOffset;
-};
-
-struct Type1CPrivateDict {
- GString *dictData;
- int subrsOffset;
- double defaultWidthX;
- GBool defaultWidthXFP;
- double nominalWidthX;
- GBool nominalWidthXFP;
-};
-
-Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
- int nameIdxPos, namePos, nameLen;
-
- file = (Guchar *)fileA;
- len = lenA;
- name = NULL;
- encoding = NULL;
- ok = gFalse;
-
- // some tools embed Type 1C fonts with an extra whitespace char at
- // the beginning
- if (len > 0 && file[0] != '\x01') {
- ++file;
- --len;
- }
-
- // make sure the header exists
- if (len < 4) {
- return;
- }
-
- // read name index (first font only)
- nameIdxPos = file[2] & 0xff;
- if ((namePos = getIndexValPos(nameIdxPos, 0, &nameLen)) < 0) {
- return;
- }
- name = new GString((char *)&file[namePos], nameLen);
-
- topDictIdxPos = getIndexEnd(nameIdxPos);
- stringIdxPos = getIndexEnd(topDictIdxPos);
- gsubrIdxPos = getIndexEnd(stringIdxPos);
-
- ok = gTrue;
-}
-
-Type1CFontFile::~Type1CFontFile() {
- int i;
-
- delete name;
- if (encoding) {
- for (i = 0; i < 256; ++i) {
- gfree(encoding[i]);
- }
- gfree(encoding);
- }
-}
-
-char *Type1CFontFile::getName() {
- return name->getCString();
-}
-
-char **Type1CFontFile::getEncoding() {
- if (!encoding) {
- readEncoding();
- }
- return encoding;
-}
-
-void Type1CFontFile::readEncoding() {
- char buf[256];
- int idxPos, idxLen, pos;
- int nGlyphs;
- int nCodes, nRanges, nLeft, nSups;
- Gushort *glyphNames;
- int charset, enc, charstrings;
- int encFormat;
- int c, sid;
- double x;
- GBool isFP;
- int key;
- int i, j;
-
- encoding = (char **)gmalloc(256 * sizeof(char *));
- for (i = 0; i < 256; ++i) {
- encoding[i] = NULL;
- }
-
- // read top dict (first font only)
- if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
- return;
- }
- charset = enc = charstrings = 0;
- i = 0;
- pos = idxPos;
- while (pos < idxPos + idxLen) {
- if (file[pos] <= 27 || file[pos] == 31) {
- key = file[pos++];
- if (key == 0x0c) {
- if (pos >= idxPos + idxLen) {
- return;
- }
- key = (key << 8) | file[pos++];
- }
- if (key == 0x0f) { // charset
- charset = (int)op[0];
- } else if (key == 0x10) { // encoding
- enc = (int)op[0];
- } else if (key == 0x11) { // charstrings
- charstrings = (int)op[0];
- }
- i = 0;
- } else {
- x = getNum(&pos, &isFP);
- if (i < 48) {
- op[i++] = x;
- }
- }
- }
-
- // get number of glyphs from charstrings index
- nGlyphs = getIndexLen(charstrings);
-
- // read charset (GID -> name mapping)
- glyphNames = readCharset(charset, nGlyphs);
-
- // read encoding (GID -> code mapping)
- if (enc == 0) {
- for (i = 0; i < 256; ++i) {
- if (standardEncoding[i]) {
- encoding[i] = copyString(standardEncoding[i]);
- }
- }
- } else if (enc == 1) {
- for (i = 0; i < 256; ++i) {
- if (expertEncoding[i]) {
- encoding[i] = copyString(expertEncoding[i]);
- }
- }
- } else {
- pos = enc;
- if (pos < 0 || pos >= len) {
- goto err0;
- }
- encFormat = file[pos++];
- if ((encFormat & 0x7f) == 0) {
- if (pos >= len) {
- goto err0;
- }
- nCodes = 1 + file[pos++];
- if (nCodes > nGlyphs) {
- nCodes = nGlyphs;
- }
- if (pos + nCodes - 1 > len) {
- goto err0;
- }
- for (i = 1; i < nCodes; ++i) {
- c = file[pos++];
- if (encoding[c]) {
- gfree(encoding[c]);
- }
- encoding[c] = copyString(getString(glyphNames[i], buf));
- }
- } else if ((encFormat & 0x7f) == 1) {
- if (pos >= len) {
- goto err0;
- }
- nRanges = file[pos++];
- if (pos + 2 * nRanges > len) {
- goto err0;
- }
- nCodes = 1;
- for (i = 0; i < nRanges; ++i) {
- c = file[pos++];
- nLeft = file[pos++];
- for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
- if (c < 256) {
- if (encoding[c]) {
- gfree(encoding[c]);
- }
- encoding[c] = copyString(getString(glyphNames[nCodes], buf));
- }
- ++nCodes;
- ++c;
- }
- }
- }
- if (encFormat & 0x80) {
- if (pos >= len) {
- goto err0;
- }
- nSups = file[pos++];
- if (pos + nSups * 3 > len) {
- goto err0;
- }
- for (i = 0; i < nSups; ++i) {
- c = file[pos++];
- sid = getWord(pos, 2);
- pos += 2;
- if (encoding[c]) {
- gfree(encoding[c]);
- }
- encoding[c] = copyString(getString(sid, buf));
- }
- }
- }
-
- err0:
- if (charset < 0 || charset > 2) {
- gfree(glyphNames);
- }
-}
-
-void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
- void *outputStreamA) {
- Type1CTopDict dict;
- Type1CPrivateDict privateDict;
- char buf[512], eBuf[256];
- int idxPos, idxLen, pos;
- int nGlyphs, nCodes, nRanges, nLeft, nSups;
- Gushort *glyphNames;
- int encFormat, nCharStrings;
- int c, sid;
- int i, j;
-
- outputFunc = outputFuncA;
- outputStream = outputStreamA;
-
- // read top dict (first font only)
- readTopDict(&dict);
-
- // write header and font dictionary, up to encoding
- (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
- (*outputFunc)(outputStream, name->getCString(), name->getLength());
- if (dict.version != 0) {
- getString(dict.version, buf);
- (*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 (dict.version != 0) {
- (*outputFunc)(outputStream, "/version (", 10);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (dict.notice != 0) {
- getString(dict.notice, buf);
- (*outputFunc)(outputStream, "/Notice (", 9);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (dict.copyright != 0) {
- getString(dict.copyright, buf);
- (*outputFunc)(outputStream, "/Copyright (", 12);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (dict.fullName != 0) {
- getString(dict.fullName, buf);
- (*outputFunc)(outputStream, "/FullName (", 11);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (dict.familyName != 0) {
- getString(dict.familyName, buf);
- (*outputFunc)(outputStream, "/FamilyName (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (dict.weight != 0) {
- getString(dict.weight, buf);
- (*outputFunc)(outputStream, "/Weight (", 9);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") readonly def\n", 15);
- }
- if (dict.isFixedPitch) {
- (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
- } else {
- (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
- }
- sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/UnderlineThickness %g def\n", dict.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", dict.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",
- dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
- dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
- dict.fontBBox[0], dict.fontBBox[1],
- dict.fontBBox[2], dict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
- if (dict.uniqueID != 0) {
- sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
-
- // get number of glyphs from charstrings index
- nGlyphs = getIndexLen(dict.charStrings);
-
- // read charset
- glyphNames = readCharset(dict.charset, nGlyphs);
-
- // read encoding (glyph -> code mapping), write Type 1 encoding
- (*outputFunc)(outputStream, "/Encoding ", 10);
- if (dict.encoding == 0) {
- (*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);
- if (dict.encoding == 1) {
- for (i = 0; i < 256; ++i) {
- if (expertEncoding[i]) {
- sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- }
- }
- } else {
- pos = dict.encoding;
- if (pos < 0 || pos >= len) {
- goto err0;
- }
- encFormat = file[pos++];
- if ((encFormat & 0x7f) == 0) {
- if (pos >= len) {
- goto err0;
- }
- nCodes = 1 + file[pos++];
- if (nCodes > nGlyphs) {
- nCodes = nGlyphs;
- }
- if (pos + nCodes - 1 > len) {
- goto err0;
- }
- for (i = 1; i < nCodes; ++i) {
- c = file[pos++];
- sprintf(buf, "dup %d /", c);
- (*outputFunc)(outputStream, buf, strlen(buf));
- getString(glyphNames[i], buf);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, " put\n", 5);
- }
- } else if ((encFormat & 0x7f) == 1) {
- if (pos >= len) {
- goto err0;
- }
- nRanges = file[pos++];
- if (pos + 2 * nRanges > len) {
- goto err0;
- }
- nCodes = 1;
- for (i = 0; i < nRanges; ++i) {
- c = file[pos++];
- nLeft = file[pos++];
- for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
- sprintf(buf, "dup %d /", c);
- (*outputFunc)(outputStream, buf, strlen(buf));
- getString(glyphNames[nCodes], buf);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, " put\n", 5);
- ++nCodes;
- ++c;
- }
- }
- }
- if (encFormat & 0x80) {
- if (pos >= len) {
- goto err0;
- }
- nSups = file[pos++];
- if (pos + nSups * 3 > len) {
- goto err0;
- }
- for (i = 0; i < nSups; ++i) {
- c = file[pos++];
- sid = getWord(pos, 2);
- pos += 2;
- sprintf(buf, "dup %d /", c);
- (*outputFunc)(outputStream, buf, strlen(buf));
- getString(sid, buf);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, " put\n", 5);
- }
- }
- err0:;
- }
- (*outputFunc)(outputStream, "readonly def\n", 13);
- }
- (*outputFunc)(outputStream, "currentdict end\n", 16);
-
- // start the binary section
- (*outputFunc)(outputStream, "currentfile eexec\n", 18);
- r1 = 55665;
- line = 0;
-
- // get private dictionary
- eexecWrite("\x83\xca\x73\xd5");
- eexecWrite("dup /Private 32 dict dup begin\n");
- eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
- eexecWrite("/ND {noaccess def} executeonly def\n");
- eexecWrite("/NP {noaccess put} executeonly def\n");
- eexecWrite("/MinFeature {16 16} def\n");
- eexecWrite("/password 5839 def\n");
- readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
- eexecWrite(privateDict.dictData->getCString());
- defaultWidthX = privateDict.defaultWidthX;
- defaultWidthXFP = privateDict.defaultWidthXFP;
- nominalWidthX = privateDict.nominalWidthX;
- nominalWidthXFP = privateDict.nominalWidthXFP;
-
- // set up subroutines
- subrIdxPos = privateDict.subrsOffset;
- i = getIndexLen(gsubrIdxPos);
- gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
- i = getIndexLen(subrIdxPos);
- subrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-
- // get CharStrings
- nCharStrings = getIndexLen(dict.charStrings);
- sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
- eexecWrite(eBuf);
- for (i = 0; i < nCharStrings; ++i) {
- if ((idxPos = getIndexValPos(dict.charStrings, i, &idxLen)) >= 0) {
- eexecCvtGlyph(getString(glyphNames[i], buf), idxPos, idxLen);
- }
- }
- eexecWrite("end\n");
- eexecWrite("end\n");
- eexecWrite("readonly put\n");
- eexecWrite("noaccess put\n");
- eexecWrite("dup /FontName get exch definefont pop\n");
- eexecWrite("mark currentfile closefile\n");
-
- // trailer
- if (line > 0) {
- (*outputFunc)(outputStream, "\n", 1);
- }
- for (i = 0; i < 8; ++i) {
- (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
- }
- (*outputFunc)(outputStream, "cleartomark\n", 12);
-
- // clean up
- delete privateDict.dictData;
- if (dict.charset > 2) {
- gfree(glyphNames);
- }
-}
-
-void Type1CFontFile::convertToCIDType0(char *psName,
- FontFileOutputFunc outputFuncA,
- void *outputStreamA) {
- Type1CTopDict dict;
- Type1CPrivateDict *privateDicts;
- GString *charStrings;
- int *charStringOffsets;
- Gushort *charset;
- int *cidMap;
- Guchar *fdSelect;
- int idxPos, idxLen, pos;
- char buf[512], buf2[16];
- int nGlyphs, nCIDs, gdBytes, nFDs;
- int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
- int key;
- double x;
- GBool isFP;
- int i, j, k, n;
-
- outputFunc = outputFuncA;
- outputStream = outputStreamA;
-
- (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
-
- // read top dict (first font only)
- readTopDict(&dict);
-
- // read the FDArray dictionaries and Private dictionaries
- if (dict.fdArrayOffset == 0) {
- nFDs = 1;
- privateDicts = (Type1CPrivateDict *)
- gmalloc(nFDs * sizeof(Type1CPrivateDict));
- privateDicts[0].dictData = new GString();
- privateDicts[0].subrsOffset = 0;
- privateDicts[0].defaultWidthX = 0;
- privateDicts[0].defaultWidthXFP = gFalse;
- privateDicts[0].nominalWidthX = 0;
- privateDicts[0].nominalWidthXFP = gFalse;
- } else {
- if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
- goto err0;
- }
- privateDicts = (Type1CPrivateDict *)
- gmalloc(nFDs * sizeof(Type1CPrivateDict));
- for (i = 0; i < nFDs; ++i) {
- privateDicts[i].dictData = NULL;
- }
- for (i = 0; i < nFDs; ++i) {
- privateDicts[i].dictData = NULL;
- if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
- goto err1;
- }
- pos = idxPos;
- j = 0;
- while (pos < idxPos + idxLen) {
- if (file[pos] <= 27 || file[pos] == 31) {
- key = file[pos++];
- if (key == 0x0c) {
- if (pos >= idxPos + idxLen) {
- goto err1;
- }
- key = (key << 8) | file[pos++];
- }
- if (key == 0x0012) {
- readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
- }
- j = 0;
- } else {
- x = getNum(&pos, &isFP);
- if (j < 48) {
- op[j] = x;
- fp[j++] = isFP;
- }
- }
- }
- if (!privateDicts[i].dictData) {
- privateDicts[i].dictData = new GString();
- privateDicts[i].subrsOffset = 0;
- privateDicts[i].defaultWidthX = 0;
- privateDicts[i].defaultWidthXFP = gFalse;
- privateDicts[i].nominalWidthX = 0;
- privateDicts[i].nominalWidthXFP = gFalse;
- }
- }
- }
-
- // get the glyph count
- if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
- goto err1;
- }
-
- // read the FDSelect table
- fdSelect = (Guchar *)gmalloc(nGlyphs);
- if (dict.fdSelectOffset == 0) {
- for (i = 0; i < nGlyphs; ++i) {
- fdSelect[i] = 0;
- }
- } else {
- pos = dict.fdSelectOffset;
- if (pos < 0 || pos >= len) {
- goto err2;
- }
- fdSelectFmt = file[pos++];
- if (fdSelectFmt == 0) {
- if (pos + nGlyphs > len) {
- goto err2;
- }
- memcpy(fdSelect, file + pos, nGlyphs);
- } else if (fdSelectFmt == 3) {
- if (pos + 4 > len) {
- goto err2;
- }
- nRanges = getWord(pos, 2);
- pos += 2;
- gid0 = getWord(pos, 2);
- pos += 2;
- if (pos + nRanges * 3 > len) {
- goto err2;
- }
- for (i = 1; i <= nRanges; ++i) {
- fd = file[pos++];
- gid1 = getWord(pos, 2);
- pos += 2;
- 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;
- }
- }
- }
-
- // read the charset, compute the CID-to-GID mapping
- charset = readCharset(dict.charset, nGlyphs);
- 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;
- }
-
- // set up global subroutines
- i = getIndexLen(gsubrIdxPos);
- gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-
- // build the charstrings
- charStrings = new GString();
- charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
- for (i = 0; i < nCIDs; ++i) {
- charStringOffsets[i] = charStrings->getLength();
- if (cidMap[i] >= 0) {
- if ((idxPos = getIndexValPos(dict.charStrings,
- cidMap[i], &idxLen)) >= 0) {
- j = fdSelect[cidMap[i]];
- defaultWidthX = privateDicts[j].defaultWidthX;
- defaultWidthXFP = privateDicts[j].defaultWidthXFP;
- nominalWidthX = privateDicts[j].nominalWidthX;
- nominalWidthXFP = privateDicts[j].nominalWidthXFP;
- subrIdxPos = privateDicts[j].subrsOffset;
- k = getIndexLen(subrIdxPos);
- subrBias = (k < 1240) ? 107 : (k < 33900) ? 1131 : 32768;
- cvtGlyph(idxPos, idxLen, gTrue);
- charStrings->append(charBuf);
- delete charBuf;
- }
- }
- }
- charStringOffsets[nCIDs] = charStrings->getLength();
-
- // 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, "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 (dict.registry > 0 && dict.ordering > 0) {
- getString(dict.registry, buf);
- (*outputFunc)(outputStream, " /Registry (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, ") def\n", 6);
- getString(dict.ordering, buf);
- (*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", dict.supplement);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "end def\n", 8);
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
- dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
- dict.fontBBox[0], dict.fontBBox[1],
- dict.fontBBox[2], dict.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 (dict.paintType != 0) {
- sprintf(buf, "/PaintType %d def\n", dict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/StrokeWidth %g def\n", dict.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", dict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
- (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
- privateDicts[i].dictData->getLength());
- (*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);
- gfree(charset);
- err2:
- gfree(fdSelect);
- err1:
- for (i = 0; i < nFDs; ++i) {
- if (privateDicts[i].dictData) {
- delete privateDicts[i].dictData;
- }
- }
- gfree(privateDicts);
- err0:;
-}
-
-void Type1CFontFile::convertToType0(char *psName,
- FontFileOutputFunc outputFuncA,
- void *outputStreamA) {
- Type1CTopDict dict;
- Type1CPrivateDict *privateDicts;
- Gushort *charset;
- int *cidMap;
- Guchar *fdSelect;
- int idxPos, idxLen, pos;
- char buf[512];
- char eBuf[256];
- int nGlyphs, nCIDs, nFDs;
- int fdSelectFmt, nRanges, gid0, gid1, fd;
- int key;
- double x;
- GBool isFP;
- int i, j;
-
- outputFunc = outputFuncA;
- outputStream = outputStreamA;
-
- // read top dict (first font only)
- readTopDict(&dict);
-
- // read the FDArray dictionaries and Private dictionaries
- if (dict.fdArrayOffset == 0) {
- nFDs = 1;
- privateDicts = (Type1CPrivateDict *)
- gmalloc(nFDs * sizeof(Type1CPrivateDict));
- privateDicts[0].dictData = new GString();
- privateDicts[0].subrsOffset = 0;
- privateDicts[0].defaultWidthX = 0;
- privateDicts[0].defaultWidthXFP = gFalse;
- privateDicts[0].nominalWidthX = 0;
- privateDicts[0].nominalWidthXFP = gFalse;
- } else {
- if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
- goto err0;
- }
- privateDicts = (Type1CPrivateDict *)
- gmalloc(nFDs * sizeof(Type1CPrivateDict));
- for (i = 0; i < nFDs; ++i) {
- privateDicts[i].dictData = NULL;
- }
- for (i = 0; i < nFDs; ++i) {
- privateDicts[i].dictData = NULL;
- if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
- goto err1;
- }
- pos = idxPos;
- j = 0;
- while (pos < idxPos + idxLen) {
- if (file[pos] <= 27 || file[pos] == 31) {
- key = file[pos++];
- if (key == 0x0c) {
- if (pos >= idxPos + idxLen) {
- goto err1;
- }
- key = (key << 8) | file[pos++];
- }
- if (key == 0x0012) {
- readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
- }
- j = 0;
- } else {
- x = getNum(&pos, &isFP);
- if (j < 48) {
- op[j] = x;
- fp[j++] = isFP;
- }
- }
- }
- if (!privateDicts[i].dictData) {
- privateDicts[i].dictData = new GString();
- privateDicts[i].subrsOffset = 0;
- privateDicts[i].defaultWidthX = 0;
- privateDicts[i].defaultWidthXFP = gFalse;
- privateDicts[i].nominalWidthX = 0;
- privateDicts[i].nominalWidthXFP = gFalse;
- }
- }
- }
-
- // get the glyph count
- if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
- goto err1;
- }
-
- // read the FDSelect table
- fdSelect = (Guchar *)gmalloc(nGlyphs);
- if (dict.fdSelectOffset == 0) {
- for (i = 0; i < nGlyphs; ++i) {
- fdSelect[i] = 0;
- }
- } else {
- pos = dict.fdSelectOffset;
- if (pos < 0 || pos >= len) {
- goto err2;
- }
- fdSelectFmt = file[pos++];
- if (fdSelectFmt == 0) {
- if (pos + nGlyphs > len) {
- goto err2;
- }
- memcpy(fdSelect, file + pos, nGlyphs);
- } else if (fdSelectFmt == 3) {
- if (pos + 4 > len) {
- goto err2;
- }
- nRanges = getWord(pos, 2);
- pos += 2;
- gid0 = getWord(pos, 2);
- pos += 2;
- if (pos + nRanges * 3 > len) {
- goto err2;
- }
- for (i = 1; i <= nRanges; ++i) {
- fd = file[pos++];
- gid1 = getWord(pos, 2);
- pos += 2;
- 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;
- }
- }
- }
-
- // read the charset, compute the CID-to-GID mapping
- charset = readCharset(dict.charset, nGlyphs);
- 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;
- }
-
- // set up global subroutines
- i = getIndexLen(gsubrIdxPos);
- gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
-
- // write the descendant Type 1 fonts
- for (i = 0; i < nCIDs; i += 256) {
-
- //~ 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",
- dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
- dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
- dict.fontBBox[0], dict.fontBBox[1],
- dict.fontBBox[2], dict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/PaintType %d def\n", dict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- if (dict.paintType != 0) {
- sprintf(buf, "/StrokeWidth %g def\n", dict.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);
- r1 = 55665;
- line = 0;
-
- // start the private dictionary
- eexecWrite("\x83\xca\x73\xd5");
- eexecWrite("dup /Private 32 dict dup begin\n");
- eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
- eexecWrite("/ND {noaccess def} executeonly def\n");
- eexecWrite("/NP {noaccess put} executeonly def\n");
- eexecWrite("/MinFeature {16 16} def\n");
- eexecWrite("/password 5839 def\n");
- eexecWrite(privateDicts[fd].dictData->getCString());
- defaultWidthX = privateDicts[fd].defaultWidthX;
- defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
- nominalWidthX = privateDicts[fd].nominalWidthX;
- nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
-
- // set up the subroutines
- subrIdxPos = privateDicts[fd].subrsOffset;
- j = getIndexLen(subrIdxPos);
- subrBias = (j < 1240) ? 107 : (j < 33900) ? 1131 : 32768;
-
- // start the CharStrings
- sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
- eexecWrite(eBuf);
-
- // write the .notdef CharString
- if ((idxPos = getIndexValPos(dict.charStrings, 0, &idxLen)) >= 0) {
- eexecCvtGlyph(".notdef", idxPos, idxLen);
- }
-
- // write the CharStrings
- for (j = 0; j < 256 && i+j < nCIDs; ++j) {
- if (cidMap[i+j] >= 0) {
- if ((idxPos = getIndexValPos(dict.charStrings,
- cidMap[i+j], &idxLen)) >= 0) {
- sprintf(buf, "c%02x", j);
- eexecCvtGlyph(buf, idxPos, idxLen);
- }
- }
- }
- eexecWrite("end\n");
- eexecWrite("end\n");
- eexecWrite("readonly put\n");
- eexecWrite("noaccess put\n");
- eexecWrite("dup /FontName get exch definefont pop\n");
- eexecWrite("mark currentfile closefile\n");
-
- // trailer
- if (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);
-
- // clean up
- gfree(cidMap);
- gfree(charset);
- err2:
- gfree(fdSelect);
- err1:
- for (i = 0; i < nFDs; ++i) {
- if (privateDicts[i].dictData) {
- delete privateDicts[i].dictData;
- }
- }
- gfree(privateDicts);
- err0:;
-}
-
-void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
- int idxPos, idxLen, pos;
- double x;
- GBool isFP;
- int key;
- int i;
-
- dict->version = 0;
- dict->notice = 0;
- dict->copyright = 0;
- dict->fullName = 0;
- dict->familyName = 0;
- dict->weight = 0;
- dict->isFixedPitch = 0;
- dict->italicAngle = 0;
- dict->underlinePosition = -100;
- dict->underlineThickness = 50;
- dict->paintType = 0;
- dict->charstringType = 2;
- dict->fontMatrix[0] = 0.001;
- dict->fontMatrix[1] = 0;
- dict->fontMatrix[2] = 0;
- dict->fontMatrix[3] = 0.001;
- dict->fontMatrix[4] = 0;
- dict->fontMatrix[5] = 0;
- dict->uniqueID = 0;
- dict->fontBBox[0] = 0;
- dict->fontBBox[1] = 0;
- dict->fontBBox[2] = 0;
- dict->fontBBox[3] = 0;
- dict->strokeWidth = 0;
- dict->charset = 0;
- dict->encoding = 0;
- dict->charStrings = 0;
- dict->privateSize = 0;
- dict->privateOffset = 0;
- dict->registry = 0;
- dict->ordering = 0;
- dict->supplement = 0;
- dict->fdArrayOffset = 0;
- dict->fdSelectOffset = 0;
- if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
- return;
- }
- i = 0;
- pos = idxPos;
- while (pos < idxPos + idxLen) {
- if (file[pos] <= 27 || file[pos] == 31) {
- key = file[pos++];
- if (key == 0x0c) {
- if (pos >= idxPos + idxLen) {
- break;
- }
- key = (key << 8) | file[pos++];
- }
- switch (key) {
- case 0x0000: dict->version = (int)op[0]; break;
- case 0x0001: dict->notice = (int)op[0]; break;
- case 0x0c00: dict->copyright = (int)op[0]; break;
- case 0x0002: dict->fullName = (int)op[0]; break;
- case 0x0003: dict->familyName = (int)op[0]; break;
- case 0x0004: dict->weight = (int)op[0]; break;
- case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
- case 0x0c02: dict->italicAngle = op[0]; break;
- case 0x0c03: dict->underlinePosition = op[0]; break;
- case 0x0c04: dict->underlineThickness = op[0]; break;
- case 0x0c05: dict->paintType = (int)op[0]; break;
- case 0x0c06: dict->charstringType = (int)op[0]; break;
- case 0x0c07: dict->fontMatrix[0] = op[0];
- dict->fontMatrix[1] = op[1];
- dict->fontMatrix[2] = op[2];
- dict->fontMatrix[3] = op[3];
- dict->fontMatrix[4] = op[4];
- dict->fontMatrix[5] = op[5]; break;
- case 0x000d: dict->uniqueID = (int)op[0]; break;
- case 0x0005: dict->fontBBox[0] = op[0];
- dict->fontBBox[1] = op[1];
- dict->fontBBox[2] = op[2];
- dict->fontBBox[3] = op[3]; break;
- case 0x0c08: dict->strokeWidth = op[0]; break;
- case 0x000f: dict->charset = (int)op[0]; break;
- case 0x0010: dict->encoding = (int)op[0]; break;
- case 0x0011: dict->charStrings = (int)op[0]; break;
- case 0x0012: dict->privateSize = (int)op[0];
- dict->privateOffset = (int)op[1]; break;
- case 0x0c1e: dict->registry = (int)op[0];
- dict->ordering = (int)op[1];
- dict->supplement = (int)op[2]; break;
- case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
- case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
- }
- i = 0;
- } else {
- x = getNum(&pos, &isFP);
- if (i < 48) {
- op[i] = x;
- fp[i++] = isFP;
- }
- }
- }
-}
-
-void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
- int offset, int size) {
- int pos;
- char eBuf[256];
- int key;
- double x;
- GBool isFP;
- int i;
-
- privateDict->dictData = new GString();
- privateDict->subrsOffset = 0;
- privateDict->defaultWidthX = 0;
- privateDict->defaultWidthXFP = gFalse;
- privateDict->nominalWidthX = 0;
- privateDict->nominalWidthXFP = gFalse;
- if (offset < 0 || offset + size > len) {
- return;
- }
- pos = offset;
- i = 0;
- while (pos < offset + size) {
- if (file[pos] <= 27 || file[pos] == 31) {
- key = file[pos++];
- if (key == 0x0c) {
- if (pos >= offset + size) {
- break;
- }
- key = (key << 8) | file[pos++];
- }
- switch (key) {
- case 0x0006:
- getDeltaInt(eBuf, "BlueValues", op, i);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0007:
- getDeltaInt(eBuf, "OtherBlues", op, i);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0008:
- getDeltaInt(eBuf, "FamilyBlues", op, i);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0009:
- getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c09:
- sprintf(eBuf, "/BlueScale %g def\n", op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c0a:
- sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c0b:
- sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x000a:
- sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x000b:
- sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c0c:
- getDeltaReal(eBuf, "StemSnapH", op, i);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c0d:
- getDeltaReal(eBuf, "StemSnapV", op, i);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c0e:
- sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c0f:
- sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c11:
- sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c12:
- sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
- privateDict->dictData->append(eBuf);
- break;
- case 0x0c13:
- error(-1, "Got Type 1C InitialRandomSeed");
- break;
- case 0x0013:
- privateDict->subrsOffset = offset + (int)op[0];
- break;
- case 0x0014:
- privateDict->defaultWidthX = op[0];
- privateDict->defaultWidthXFP = fp[0];
- break;
- case 0x0015:
- privateDict->nominalWidthX = op[0];
- privateDict->nominalWidthXFP = fp[0];
- break;
- default:
- error(-1, "Unknown Type 1C private dict entry %04x", key);
- break;
- }
- i = 0;
- } else {
- x = getNum(&pos, &isFP);
- if (i < 48) {
- op[i] = x;
- fp[i++] = isFP;
- }
- }
- }
-}
-
-Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
- Gushort *glyphNames;
- int pos;
- int charsetFormat, c;
- int nLeft, i, j;
-
- if (charset == 0) {
- glyphNames = type1CISOAdobeCharset;
- } else if (charset == 1) {
- glyphNames = type1CExpertCharset;
- } else if (charset == 2) {
- glyphNames = type1CExpertSubsetCharset;
- } else {
- glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
- for (i = 0; i < nGlyphs; ++i) {
- glyphNames[i] = 0;
- }
- pos = charset;
- if (pos < 0 || pos >= len) {
- goto err0;
- }
- charsetFormat = file[pos++];
- if (charsetFormat == 0) {
- if (pos + (nGlyphs - 1) * 2 >= len) {
- goto err0;
- }
- for (i = 1; i < nGlyphs; ++i) {
- glyphNames[i] = getWord(pos, 2);
- pos += 2;
- }
- } else if (charsetFormat == 1) {
- i = 1;
- while (i < nGlyphs) {
- if (pos + 3 > len) {
- goto err0;
- }
- c = getWord(pos, 2);
- pos += 2;
- nLeft = file[pos++];
- for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
- glyphNames[i++] = c++;
- }
- }
- } else if (charsetFormat == 2) {
- i = 1;
- while (i < nGlyphs) {
- if (pos + 4 > len) {
- goto err0;
- }
- c = getWord(pos, 2);
- pos += 2;
- nLeft = getWord(pos, 2);
- pos += 2;
- for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
- glyphNames[i++] = c++;
- }
- }
- }
- }
- err0:
- return glyphNames;
-}
-
-void Type1CFontFile::eexecWrite(char *s) {
- Guchar *p;
- Guchar x;
-
- for (p = (Guchar *)s; *p; ++p) {
- x = *p ^ (r1 >> 8);
- r1 = (x + r1) * 52845 + 22719;
- (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
- (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
- line += 2;
- if (line == 64) {
- (*outputFunc)(outputStream, "\n", 1);
- line = 0;
- }
- }
-}
-
-void Type1CFontFile::eexecCvtGlyph(char *glyphName, int pos, int n) {
- char eBuf[256];
-
- cvtGlyph(pos, n, gTrue);
- sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
- eexecWrite(eBuf);
- eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
- eexecWrite(" ND\n");
- delete charBuf;
-}
-
-void Type1CFontFile::cvtGlyph(int pos, int n, GBool top) {
- int x;
- int subrPos, subrLen;
- double d, dx, dy;
- GBool dFP;
- Gushort r2;
- Guchar byte;
- int i, k;
-
- if (pos < 0 || pos + n > len) {
- return;
- }
-
- if (top) {
- charBuf = new GString();
- charBuf->append((char)73);
- charBuf->append((char)58);
- charBuf->append((char)147);
- charBuf->append((char)134);
- nOps = 0;
- nHints = 0;
- firstOp = gTrue;
- }
-
- i = pos;
- while (i < pos + n) {
- if (file[i] == 12) {
- if (i + 2 > pos + n) {
- break;
- }
- switch (file[i+1]) {
- case 0: // dotsection (should be Type 1 only?)
- // ignored
- break;
- case 34: // hflex
- if (nOps != 7) {
- error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpNum(0, gFalse);
- eexecDumpOp1(8);
- eexecDumpNum(op[4], fp[4]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[5], fp[5]);
- eexecDumpNum(-op[2], fp[2]);
- eexecDumpNum(op[6], fp[6]);
- eexecDumpNum(0, gFalse);
- eexecDumpOp1(8);
- break;
- case 35: // flex
- if (nOps != 13) {
- error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpNum(op[4], fp[4]);
- eexecDumpNum(op[5], fp[5]);
- eexecDumpOp1(8);
- eexecDumpNum(op[6], fp[6]);
- eexecDumpNum(op[7], fp[7]);
- eexecDumpNum(op[8], fp[8]);
- eexecDumpNum(op[9], fp[9]);
- eexecDumpNum(op[10], fp[10]);
- eexecDumpNum(op[11], fp[11]);
- eexecDumpOp1(8);
- break;
- case 36: // hflex1
- if (nOps != 9) {
- error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpNum(op[4], fp[4]);
- eexecDumpNum(0, gFalse);
- eexecDumpOp1(8);
- eexecDumpNum(op[5], fp[5]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[6], fp[6]);
- eexecDumpNum(op[7], fp[7]);
- eexecDumpNum(op[8], fp[8]);
- eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
- eexecDumpOp1(8);
- break;
- case 37: // flex1
- if (nOps != 11) {
- error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpNum(op[4], fp[4]);
- eexecDumpNum(op[5], fp[5]);
- eexecDumpOp1(8);
- eexecDumpNum(op[6], fp[6]);
- eexecDumpNum(op[7], fp[7]);
- eexecDumpNum(op[8], fp[8]);
- eexecDumpNum(op[9], fp[9]);
- dx = op[0] + op[2] + op[4] + op[6] + op[8];
- dy = op[1] + op[3] + op[5] + op[7] + op[9];
- if (fabs(dx) > fabs(dy)) {
- eexecDumpNum(op[10], fp[10]);
- eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
- } else {
- eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
- eexecDumpNum(op[10], fp[10]);
- }
- eexecDumpOp1(8);
- break;
- case 3: // and
- case 4: // or
- case 5: // not
- case 8: // store
- case 9: // abs
- case 10: // add
- case 11: // sub
- case 12: // div
- case 13: // load
- case 14: // neg
- case 15: // eq
- case 18: // drop
- case 20: // put
- case 21: // get
- case 22: // ifelse
- case 23: // random
- case 24: // mul
- case 26: // sqrt
- case 27: // dup
- case 28: // exch
- case 29: // index
- case 30: // roll
- error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
- break;
- default:
- error(-1, "Illegal Type 2 charstring op: 12.%d", file[i+1]);
- break;
- }
- i += 2;
- nOps = 0;
- } else if (file[i] == 19) { // hintmask
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1);
- firstOp = gFalse;
- }
- if (nOps > 0) {
- if (nOps & 1) {
- error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
- nOps);
- }
- nHints += nOps / 2;
- }
- i += 1 + ((nHints + 7) >> 3);
- nOps = 0;
- } else if (file[i] == 20) { // cntrmask
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1);
- firstOp = gFalse;
- }
- if (nOps > 0) {
- if (nOps & 1) {
- error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
- nOps);
- }
- nHints += nOps / 2;
- }
- i += 1 + ((nHints + 7) >> 3);
- nOps = 0;
- } else if (file[i] == 28) {
- if (i + 3 > len) {
- break;
- }
- x = (file[i+1] << 8) + file[i+2];
- if (x & 0x8000) {
- x |= -1 << 15;
- }
- if (nOps < 48) {
- fp[nOps] = gFalse;
- op[nOps++] = x;
- }
- i += 3;
- } else if (file[i] == 10) { // callsubr
- if (nOps >= 1) {
- k = subrBias + (int)op[nOps - 1];
- --nOps;
- if ((subrPos = getIndexValPos(subrIdxPos, k, &subrLen)) >= 0) {
- cvtGlyph(subrPos, subrLen, gFalse);
- }
- } else {
- error(-1, "Too few args to Type 2 callsubr");
- }
- // don't clear the stack
- ++i;
- } else if (file[i] == 29) { // callgsubr
- if (nOps >= 1) {
- k = gsubrBias + (int)op[nOps - 1];
- --nOps;
- if ((subrPos = getIndexValPos(gsubrIdxPos, k, &subrLen)) >= 0) {
- cvtGlyph(subrPos, subrLen, gFalse);
- }
- } else {
- error(-1, "Too few args to Type 2 callgsubr");
- }
- // don't clear the stack
- ++i;
- } else if (file[i] == 11) { // return
- // don't clear the stack
- ++i;
- } else if (file[i] <= 31) {
- switch (file[i]) {
- case 4: // vmoveto
- if (firstOp) {
- cvtGlyphWidth(nOps == 2);
- firstOp = gFalse;
- }
- if (nOps != 1) {
- error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpOp1(4);
- break;
- case 5: // 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) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpOp1(5);
- }
- break;
- case 6: // hlineto
- if (nOps < 1) {
- error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
- }
- for (k = 0; k < nOps; ++k) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpOp1((k & 1) ? 7 : 6);
- }
- break;
- case 7: // vlineto
- if (nOps < 1) {
- error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
- }
- for (k = 0; k < nOps; ++k) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpOp1((k & 1) ? 6 : 7);
- }
- break;
- case 8: // 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) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpNum(op[k+4], fp[k+4]);
- eexecDumpNum(op[k+5], fp[k+5]);
- eexecDumpOp1(8);
- }
- break;
- case 14: // endchar / seac
- if (firstOp) {
- cvtGlyphWidth(nOps == 1 || nOps == 5);
- firstOp = gFalse;
- }
- if (nOps == 4) {
- eexecDumpNum(0, 0);
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpOp2(6);
- } else if (nOps == 0) {
- eexecDumpOp1(14);
- } else {
- error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
- }
- break;
- case 21: // rmoveto
- if (firstOp) {
- cvtGlyphWidth(nOps == 3);
- firstOp = gFalse;
- }
- if (nOps != 2) {
- error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpOp1(21);
- break;
- case 22: // hmoveto
- if (firstOp) {
- cvtGlyphWidth(nOps == 2);
- firstOp = gFalse;
- }
- if (nOps != 1) {
- error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
- }
- eexecDumpNum(op[0], fp[0]);
- eexecDumpOp1(22);
- break;
- case 24: // 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) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpNum(op[k+4], fp[k+4]);
- eexecDumpNum(op[k+5], fp[k+5]);
- eexecDumpOp1(8);
- }
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k]);
- eexecDumpOp1(5);
- break;
- case 25: // 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) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k]);
- eexecDumpOp1(5);
- }
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpNum(op[k+4], fp[k+4]);
- eexecDumpNum(op[k+5], fp[k+5]);
- eexecDumpOp1(8);
- break;
- case 26: // 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) {
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[4], fp[4]);
- eexecDumpOp1(8);
- k = 5;
- } else {
- k = 0;
- }
- for (; k < nOps; k += 4) {
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpOp1(8);
- }
- break;
- case 27: // 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) {
- eexecDumpNum(op[1], fp[1]);
- eexecDumpNum(op[0], fp[0]);
- eexecDumpNum(op[2], fp[2]);
- eexecDumpNum(op[3], fp[3]);
- eexecDumpNum(op[4], fp[4]);
- eexecDumpNum(0, gFalse);
- eexecDumpOp1(8);
- k = 5;
- } else {
- k = 0;
- }
- for (; k < nOps; k += 4) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpNum(0, gFalse);
- eexecDumpOp1(8);
- }
- break;
- case 30: // 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) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpOp1(30);
- } else {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpOp1(31);
- }
- }
- if (k == nOps-5) {
- if (k % 8 == 0) {
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpNum(op[k+4], fp[k+4]);
- } else {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+4], fp[k+4]);
- eexecDumpNum(op[k+3], fp[k+3]);
- }
- eexecDumpOp1(8);
- }
- break;
- case 31: // 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) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpOp1(31);
- } else {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpOp1(30);
- }
- }
- if (k == nOps-5) {
- if (k % 8 == 0) {
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+4], fp[k+4]);
- eexecDumpNum(op[k+3], fp[k+3]);
- } else {
- eexecDumpNum(0, gFalse);
- eexecDumpNum(op[k], fp[k]);
- eexecDumpNum(op[k+1], fp[k+1]);
- eexecDumpNum(op[k+2], fp[k+2]);
- eexecDumpNum(op[k+3], fp[k+3]);
- eexecDumpNum(op[k+4], fp[k+4]);
- }
- eexecDumpOp1(8);
- }
- break;
- case 1: // hstem
- if (firstOp) {
- cvtGlyphWidth(nOps & 1);
- 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 (op[k+1] < 0) {
- d += op[k] + op[k+1];
- dFP |= fp[k] | fp[k+1];
- eexecDumpNum(d, dFP);
- eexecDumpNum(-op[k+1], fp[k+1]);
- } else {
- d += op[k];
- dFP |= fp[k];
- eexecDumpNum(d, dFP);
- eexecDumpNum(op[k+1], fp[k+1]);
- d += op[k+1];
- dFP |= fp[k+1];
- }
- eexecDumpOp1(1);
- }
- nHints += nOps / 2;
- break;
- case 3: // vstem
- if (firstOp) {
- cvtGlyphWidth(nOps & 1);
- 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 (op[k+1] < 0) {
- d += op[k] + op[k+1];
- dFP |= fp[k] | fp[k+1];
- eexecDumpNum(d, dFP);
- eexecDumpNum(-op[k+1], fp[k+1]);
- } else {
- d += op[k];
- dFP |= fp[k];
- eexecDumpNum(d, dFP);
- eexecDumpNum(op[k+1], fp[k+1]);
- d += op[k+1];
- dFP |= fp[k+1];
- }
- eexecDumpOp1(3);
- }
- nHints += nOps / 2;
- break;
- case 15: // (obsolete)
- // this op is ignored, but we need the glyph width
- if (firstOp) {
- cvtGlyphWidth(nOps > 0);
- firstOp = gFalse;
- }
- break;
- case 18: // hstemhm
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1);
- firstOp = gFalse;
- }
- if (nOps & 1) {
- error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
- }
- nHints += nOps / 2;
- break;
- case 23: // vstemhm
- // ignored
- if (firstOp) {
- cvtGlyphWidth(nOps & 1);
- firstOp = gFalse;
- }
- if (nOps & 1) {
- error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
- }
- nHints += nOps / 2;
- break;
- case 16: // blend
- error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
- break;
- default:
- error(-1, "Illegal Type 2 charstring op: %d", file[i]);
- break;
- }
- ++i;
- nOps = 0;
- } else if (file[i] <= 246) {
- if (nOps < 48) {
- fp[nOps] = gFalse;
- op[nOps++] = (int)file[i] - 139;
- }
- ++i;
- } else if (file[i] <= 250) {
- if (i + 2 > len) {
- break;
- }
- if (nOps < 48) {
- fp[nOps] = gFalse;
- op[nOps++] = (((int)file[i] - 247) << 8) + (int)file[i+1] + 108;
- }
- i += 2;
- } else if (file[i] <= 254) {
- if (i + 2 > len) {
- break;
- }
- if (nOps < 48) {
- fp[nOps] = gFalse;
- op[nOps++] = -(((int)file[i] - 251) << 8) - (int)file[i+1] - 108;
- }
- i += 2;
- } else {
- if (i + 5 > len) {
- break;
- }
- x = (file[i+1] << 24) | (file[i+2] << 16) | (file[i+3] << 8) | file[i+4];
- if (x & 0x80000000) {
- x |= -1 << 31;
- }
- if (nOps < 48) {
- fp[nOps] = gTrue;
- op[nOps++] = (double)x / 65536.0;
- }
- i += 5;
- }
- }
-
- // charstring encryption
- if (top) {
- r2 = 4330;
- for (i = 0; i < charBuf->getLength(); ++i) {
- byte = charBuf->getChar(i) ^ (r2 >> 8);
- charBuf->setChar(i, byte);
- r2 = (byte + r2) * 52845 + 22719;
- }
- }
-}
-
-void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
- double w;
- GBool wFP;
- int i;
-
- if (useOp) {
- w = nominalWidthX + op[0];
- wFP = nominalWidthXFP | fp[0];
- for (i = 1; i < nOps; ++i) {
- op[i-1] = op[i];
- fp[i-1] = fp[i];
- }
- --nOps;
- } else {
- w = defaultWidthX;
- wFP = defaultWidthXFP;
- }
- eexecDumpNum(0, gFalse);
- eexecDumpNum(w, wFP);
- eexecDumpOp1(13);
-}
-
-void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
- Guchar buf[12];
- int y, n;
-
- n = 0;
- if (fpA) {
- 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 Type1CFontFile::eexecDumpOp1(int opA) {
- charBuf->append((char)opA);
-}
-
-void Type1CFontFile::eexecDumpOp2(int opA) {
- charBuf->append((char)12);
- charBuf->append((char)opA);
-}
-
-void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
- Guchar x;
- int i;
-
- // eexec encryption
- for (i = 0; i < n; ++i) {
- x = s[i] ^ (r1 >> 8);
- r1 = (x + r1) * 52845 + 22719;
- (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
- (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
- line += 2;
- if (line == 64) {
- (*outputFunc)(outputStream, "\n", 1);
- line = 0;
- }
- }
-}
-
-void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
- int n) {
- int x, i;
-
- sprintf(buf, "/%s [", key);
- buf += strlen(buf);
- x = 0;
- for (i = 0; i < n; ++i) {
- x += (int)opA[i];
- sprintf(buf, "%s%d", i > 0 ? " " : "", x);
- buf += strlen(buf);
- }
- sprintf(buf, "] def\n");
-}
-
-void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
- int n) {
- double x;
- int i;
-
- sprintf(buf, "/%s [", key);
- buf += strlen(buf);
- x = 0;
- for (i = 0; i < n; ++i) {
- x += opA[i];
- sprintf(buf, "%s%g", i > 0 ? " " : "", x);
- buf += strlen(buf);
- }
- sprintf(buf, "] def\n");
-}
-
-int Type1CFontFile::getIndexLen(int indexPos) {
- if (indexPos + 2 > len) {
- return -1;
- }
- return (int)getWord(indexPos, 2);
-}
-
-int Type1CFontFile::getIndexValPos(int indexPos, int i, int *valLen) {
- int n, offSize, idxStartPos;
- int pos0, pos1;
-
- if (indexPos < 0 || indexPos + 3 > len) {
- return -1;
- }
- n = (int)getWord(indexPos, 2);
- if (i >= n) {
- return -1;
- }
- offSize = file[indexPos + 2];
- if (offSize < 1 || offSize > 4) {
- return -1;
- }
- idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
- if (idxStartPos >= len) {
- return -1;
- }
- pos0 = idxStartPos + getWord(indexPos + 3 + i * offSize, offSize);
- pos1 = idxStartPos + getWord(indexPos + 3 + (i + 1) * offSize, offSize);
- if (pos0 < 0 || pos0 >= len || pos1 < pos0 || pos1 > len) {
- return -1;
- }
- *valLen = pos1 - pos0;
- return pos0;
-}
-
-int Type1CFontFile::getIndexEnd(int indexPos) {
- int n, offSize, idxStartPos;
-
- if (indexPos < 0 || indexPos + 3 > len) {
- return -1;
- }
- n = (int)getWord(indexPos, 2);
- offSize = file[indexPos + 2];
- idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
- if (idxStartPos >= len) {
- return -1;
- }
- return idxStartPos + getWord(indexPos + 3 + n * offSize, offSize);
-}
-
-Guint Type1CFontFile::getWord(int pos, int size) {
- Guint x;
- int i;
-
- if (pos < 0 || pos + size > len) {
- return 0;
- }
- x = 0;
- for (i = 0; i < size; ++i) {
- x = (x << 8) + file[pos + i];
- }
- return x;
-}
-
-double Type1CFontFile::getNum(int *pos, GBool *isFP) {
- static char nybChars[16] = "0123456789.ee -";
- int b0, b, nyb0, nyb1;
- double x;
- char buf[65];
- int i;
-
- x = 0;
- *isFP = gFalse;
- if (*pos >= len) {
- return 0;
- }
- b0 = file[*pos];
- if (b0 < 28) {
- x = 0;
- } else if (b0 == 28) {
- if (*pos + 3 <= len) {
- x = (file[*pos + 1] << 8) + file[*pos + 2];
- *pos += 3;
- }
- } else if (b0 == 29) {
- if (*pos + 5 <= len) {
- x = (file[*pos + 1] << 24) + (file[*pos + 2] << 16) +
- (file[*pos + 3] << 8) + file[*pos + 4];
- *pos += 5;
- }
- } else if (b0 == 30) {
- *pos += 1;
- i = 0;
- do {
- if (*pos >= len) {
- break;
- }
- b = file[(*pos)++];
- nyb0 = b >> 4;
- nyb1 = b & 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';
- {
- char *theLocale = setlocale(LC_NUMERIC, "C");
- x = atof(buf);
- setlocale(LC_NUMERIC, theLocale);
- }
- *isFP = gTrue;
- } else if (b0 == 31) {
- x = 0;
- } else if (b0 < 247) {
- x = b0 - 139;
- *pos += 1;
- } else if (b0 < 251) {
- if (*pos + 2 <= len) {
- x = ((b0 - 247) << 8) + file[*pos + 1] + 108;
- *pos += 2;
- }
- } else {
- if (*pos + 2 <= len) {
- x = -((b0 - 251) << 8) - file[*pos + 1] - 108;
- *pos += 2;
- }
- }
- return x;
-}
-
-char *Type1CFontFile::getString(int sid, char *buf) {
- int idxPos, n;
-
- if (sid < 391) {
- strcpy(buf, type1CStdStrings[sid]);
- } else {
- sid -= 391;
- idxPos = getIndexValPos(stringIdxPos, sid, &n);
- if (idxPos < 0 || n < 0 || n > 255 || idxPos + n > len) {
- buf[0] = '\0';
- } else {
- strncpy(buf, (char *)&file[idxPos], n);
- buf[n] = '\0';
- }
- }
- return buf;
-}
-
-//------------------------------------------------------------------------
-// TrueTypeFontFile
-//------------------------------------------------------------------------
-
-//
-// 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 = 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] = glyphIdx
-//
-// 'post' table: mapping from glyph index to glyph name
-//
-// post[glyphIdx] = 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] = glyphIdx
-//
-
-struct TTFontTableHdr {
- char tag[4];
- Guint checksum;
- Guint offset;
- Guint length;
-};
-
-struct T42Table {
- char *tag; // 4-byte tag
- GBool required; // required by the TrueType spec?
-};
-
-struct TTFontCmap {
- int platform;
- int encoding;
- int offset;
- int len;
- int fmt;
-};
-
-// 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 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"
-};
-
-struct TrueTypeLoca {
- int idx;
- int pos;
- int length;
-};
-
-TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
- int pos, pos2, i, idx, n, length;
- Guint size, startPos, endPos;
-
- file = fileA;
- len = lenA;
-
- encoding = NULL;
- cmaps = NULL;
- nCmaps = 0;
-
- // read table directory
- nTables = getUShort(4);
- tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
- pos = 12;
- for (i = 0; i < nTables; ++i) {
- tableHdrs[i].tag[0] = getByte(pos+0);
- tableHdrs[i].tag[1] = getByte(pos+1);
- tableHdrs[i].tag[2] = getByte(pos+2);
- tableHdrs[i].tag[3] = getByte(pos+3);
- tableHdrs[i].checksum = getULong(pos+4);
- tableHdrs[i].offset = getULong(pos+8);
- tableHdrs[i].length = getULong(pos+12);
- if (tableHdrs[i].offset + tableHdrs[i].length < tableHdrs[i].offset ||
- tableHdrs[i].offset + tableHdrs[i].length > (Guint)len) {
- tableHdrs[i].offset = (Guint)-1;
- }
- pos += 16;
- }
-
- // 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) {
- error(-1, "TrueType font file is missing a required table");
- return;
- }
-
- // some embedded TrueType fonts have an incorrect (too small) cmap
- // table size
- idx = seekTableIdx("cmap");
- if (idx >= 0) {
- pos = tableHdrs[idx].offset;
- n = getUShort(pos + 2);
- size = (Guint)(4 + 8 * n);
- for (i = 0; i < n; ++i) {
- startPos = getULong(pos + 4 + 8*i + 4);
- length = getUShort(pos + startPos + 2);
- endPos = startPos + length;
- if (endPos > size) {
- size = endPos;
- }
- }
- if ((mungedCmapSize = size > tableHdrs[idx].length)) {
-#if 0 // don't bother printing this error message - it's too common
- error(-1, "Bad cmap table size in TrueType font");
-#endif
- tableHdrs[idx].length = size;
- }
- } else {
- mungedCmapSize = gFalse;
- }
-
- // read the 'head' table
- pos = seekTable("head");
- bbox[0] = getShort(pos + 36);
- bbox[1] = getShort(pos + 38);
- bbox[2] = getShort(pos + 40);
- bbox[3] = getShort(pos + 42);
- locaFmt = getShort(pos + 50);
-
- // read the 'maxp' table
- pos = seekTable("maxp");
- nGlyphs = getUShort(pos + 4);
-
- // read the 'cmap' table
- if ((pos = seekTable("cmap")) >= 0) {
- pos2 = pos + 2;
- if ((nCmaps = getUShort(pos2)) > 0) {
- pos2 += 2;
- cmaps = (TTFontCmap *)gmalloc(nCmaps * sizeof(TTFontCmap));
- for (i = 0; i < nCmaps; ++i) {
- cmaps[i].platform = getUShort(pos2);
- cmaps[i].encoding = getUShort(pos2 + 2);
- cmaps[i].offset = pos + getULong(pos2 + 4);
- pos2 += 8;
- cmaps[i].fmt = getUShort(cmaps[i].offset);
- cmaps[i].len = getUShort(cmaps[i].offset + 2);
- }
- }
- }
-}
-
-TrueTypeFontFile::~TrueTypeFontFile() {
- int i;
-
- if (encoding) {
- for (i = 0; i < 256; ++i) {
- gfree(encoding[i]);
- }
- gfree(encoding);
- }
- if (cmaps) {
- gfree(cmaps);
- }
- gfree(tableHdrs);
-}
-
-char *TrueTypeFontFile::getName() {
- return NULL;
-}
-
-char **TrueTypeFontFile::getEncoding() {
- int i;
-
- if (!encoding) {
- encoding = (char **)gmalloc(256 * sizeof(char *));
- for (i = 0; i < 256; ++i) {
- encoding[i] = NULL;
- }
- }
- return encoding;
-}
-
-int TrueTypeFontFile::getNumCmaps() {
- return nCmaps;
-}
-
-int TrueTypeFontFile::getCmapPlatform(int i) {
- return cmaps[i].platform;
-}
-
-int TrueTypeFontFile::getCmapEncoding(int i) {
- return cmaps[i].encoding;
-}
-
-int TrueTypeFontFile::findCmap(int platform, int enc) {
- int i;
-
- for (i = 0; i < nCmaps; ++i) {
- if (cmaps[i].platform == platform && cmaps[i].encoding == enc) {
- return i;
- }
- }
- return -1;
-}
-
-Gushort TrueTypeFontFile::mapCodeToGID(int i, int c) {
- if (i < 0 || i >= nCmaps) {
- return 0;
- }
- return (Gushort)getCmapEntry(cmaps[i].fmt, cmaps[i].offset, c);
-}
-
-GHash *TrueTypeFontFile::getNameToGID() {
- GHash *nameToGID;
- Guint fmt;
- GString *s;
- int stringIdx, stringPos, pos, i, j, n;
-
- if ((pos = seekTable("post")) < 0) {
- return NULL;
- }
-
- fmt = getULong(pos);
- nameToGID = NULL;
-
- // Apple font
- if (fmt == 0x00010000) {
- nameToGID = new GHash(gTrue);
- for (i = 0; i < 258; ++i) {
- nameToGID->add(new GString(macGlyphNames[i]), (void *)i);
- }
-
- // Microsoft font
- } else if (fmt == 0x00020000) {
- nameToGID = new GHash(gTrue);
- n = getUShort(pos + 32);
- if (n > nGlyphs) {
- n = nGlyphs;
- }
- stringIdx = 0;
- stringPos = pos + 34 + 2*nGlyphs;
- for (i = 0; i < nGlyphs; ++i) {
- j = getUShort(pos + 34 + 2*i);
- if (j < 258) {
- nameToGID->remove(macGlyphNames[j]);
- nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
- } else {
- j -= 258;
- if (j != stringIdx) {
- for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
- stringIdx < j;
- ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
- }
- n = getByte(stringPos);
- if (stringPos >= 0 && stringPos + 1 + n <= len) {
- s = new GString(file + stringPos + 1, n);
- nameToGID->remove(s);
- nameToGID->add(s, (void *)i);
- }
- ++stringIdx;
- stringPos += 1 + n;
- }
- }
-
- // Apple subset
- } else if (fmt == 0x000280000) {
- nameToGID = new GHash(gTrue);
- for (i = 0; i < nGlyphs; ++i) {
- j = getByte(pos + 32 + i);
- if (j < 258) {
- nameToGID->remove(macGlyphNames[j]);
- nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
- }
- }
- }
-
- return nameToGID;
-}
-
-void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
- GBool pdfFontHasEncoding,
- Gushort *codeToGID,
- FontFileOutputFunc outputFunc,
- void *outputStream) {
- char buf[512];
-
- // write the header
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
- (*outputFunc)(outputStream, buf, strlen(buf));
-
- // begin the font dictionary
- (*outputFunc)(outputStream, "10 dict begin\n", 14);
- (*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, name, strlen(name));
- (*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(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
- cvtCharStrings(encodingA, pdfFontHasEncoding, codeToGID,
- outputFunc, outputStream);
- cvtSfnts(outputFunc, outputStream, NULL);
-
- // end the dictionary and define the font
- (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
-}
-
-void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
- int nCIDs,
- FontFileOutputFunc outputFunc,
- void *outputStream) {
- char buf[512];
- Gushort cid;
- int i, j, k;
-
- // write the header
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
- (*outputFunc)(outputStream, buf, strlen(buf));
-
- // begin the font dictionary
- (*outputFunc)(outputStream, "20 dict begin\n", 14);
- (*outputFunc)(outputStream, "/CIDFontName /", 14);
- (*outputFunc)(outputStream, name, strlen(name));
- (*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 TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
- int nCIDs,
- FontFileOutputFunc outputFunc,
- void *outputStream) {
- char buf[512];
- GString *sfntsName;
- int n, i, j;
-
- // write the Type 42 sfnts array
- sfntsName = (new GString(name))->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, name, strlen(name));
- 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, name, strlen(name));
- (*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, name, strlen(name));
- (*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, name, strlen(name));
- 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);
-}
-
-int TrueTypeFontFile::getByte(int pos) {
- if (pos < 0 || pos >= len) {
- return 0;
- }
- return file[pos] & 0xff;
-}
-
-int TrueTypeFontFile::getChar(int pos) {
- int x;
-
- if (pos < 0 || pos >= len) {
- return 0;
- }
- x = file[pos] & 0xff;
- if (x & 0x80)
- x |= 0xffffff00;
- return x;
-}
-
-int TrueTypeFontFile::getUShort(int pos) {
- int x;
-
- if (pos < 0 || pos+1 >= len) {
- return 0;
- }
- x = file[pos] & 0xff;
- x = (x << 8) + (file[pos+1] & 0xff);
- return x;
-}
-
-int TrueTypeFontFile::getShort(int pos) {
- int x;
-
- if (pos < 0 || pos+1 >= len) {
- return 0;
- }
- x = file[pos] & 0xff;
- x = (x << 8) + (file[pos+1] & 0xff);
- if (x & 0x8000)
- x |= 0xffff0000;
- return x;
-}
-
-Guint TrueTypeFontFile::getULong(int pos) {
- int x;
-
- if (pos < 0 || pos+3 >= len) {
- return 0;
- }
- x = file[pos] & 0xff;
- x = (x << 8) + (file[pos+1] & 0xff);
- x = (x << 8) + (file[pos+2] & 0xff);
- x = (x << 8) + (file[pos+3] & 0xff);
- return x;
-}
-
-double TrueTypeFontFile::getFixed(int pos) {
- int x, y;
-
- x = getShort(pos);
- y = getUShort(pos+2);
- return (double)x + (double)y / 65536;
-}
-
-int TrueTypeFontFile::seekTable(char *tag) {
- int i;
-
- for (i = 0; i < nTables; ++i) {
- if (!strncmp(tableHdrs[i].tag, tag, 4)) {
- return (int)tableHdrs[i].offset;
- }
- }
- return -1;
-}
-
-int TrueTypeFontFile::seekTableIdx(char *tag) {
- int i;
-
- for (i = 0; i < nTables; ++i) {
- if (!strncmp(tableHdrs[i].tag, tag, 4)) {
- if (tableHdrs[i].offset == (Guint)-1) {
- return -1;
- }
- return i;
- }
- }
- return -1;
-}
-
-void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
- FontFileOutputFunc outputFunc,
- void *outputStream) {
- char *name;
- char buf[64];
- int i;
-
- (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
- if (pdfFontHasEncoding) {
- for (i = 0; i < 256; ++i) {
- if (!(name = encodingA[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 TrueTypeFontFile::cvtCharStrings(char **encodingA,
- GBool pdfFontHasEncoding,
- Gushort *codeToGID,
- FontFileOutputFunc 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 (pdfFontHasEncoding) {
- name = encodingA[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);
-}
-
-int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
- int cmapLen, cmapFirst;
- int segCnt, segEnd, segStart, segDelta, segOffset;
- int a, b, m, i;
-
- switch (cmapFmt) {
- case 0: // byte encoding table (Apple standard)
- cmapLen = getUShort(pos + 2);
- if (code >= cmapLen) {
- return 0;
- }
- return getByte(pos + 6 + code);
-
- case 4: // segment mapping to delta values (Microsoft standard)
- segCnt = getUShort(pos + 6) / 2;
- a = -1;
- b = segCnt - 1;
- segEnd = getUShort(pos + 14 + 2*b);
- if (code > 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) {
- m = (a + b) / 2;
- segEnd = getUShort(pos + 14 + 2*m);
- if (segEnd < code) {
- a = m;
- } else {
- b = m;
- }
- }
- segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
- segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
- segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
- if (code < segStart) {
- return 0;
- }
- if (segOffset == 0) {
- i = (code + segDelta) & 0xffff;
- } else {
- i = getUShort(pos + 16 + 6*segCnt + 2*b +
- segOffset + 2 * (code - segStart));
- if (i != 0) {
- i = (i + segDelta) & 0xffff;
- }
- }
- return i;
-
- case 6: // trimmed table mapping
- cmapFirst = getUShort(pos + 6);
- cmapLen = getUShort(pos + 8);
- if (code < cmapFirst || code >= cmapFirst + cmapLen) {
- return 0;
- }
- return getUShort(pos + 10 + 2*(code - cmapFirst));
-
- default:
- // shouldn't happen - this is checked earlier
- break;
- }
- return 0;
-}
-
-static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
- return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
-}
-
-static int cmpTrueTypeLocaPos(const void *p1, const void *p2) {
- if (((TrueTypeLoca *)p1)->pos == ((TrueTypeLoca *)p2)->pos) {
- return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
- } else {
- return ((TrueTypeLoca *)p1)->pos - ((TrueTypeLoca *)p2)->pos;
- }
-}
-
-void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
- void *outputStream, GString *name) {
- TTFontTableHdr newTableHdrs[nT42Tables];
- char tableDir[12 + nT42Tables*16];
- char headTable[54];
- TrueTypeLoca *origLocaTable;
- char *locaTable;
- int nNewTables;
- Guint checksum;
- int pos, glyfPos, length, glyphLength, pad;
- int i, j, k;
-
- // construct the 'head' table, zero out the font checksum
- memcpy(headTable, file + seekTable("head"), 54);
- headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
-
- // read the original 'loca' table and sort it into proper order --
- // some (non-compliant) fonts have out-of-order loca tables; in
- // order to correctly handle the case where (compliant) fonts have
- // empty entries in the middle of the table, cmpTrueTypeLocaPos uses
- // pos as its primary sort key, and idx as its secondary key
- // (ensuring that adjacent entries with the same pos value remain in
- // the same order)
- origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
- sizeof(TrueTypeLoca));
- pos = seekTable("loca");
- for (i = 0; i <= nGlyphs; ++i) {
- origLocaTable[i].idx = i;
- if (locaFmt) {
- origLocaTable[i].pos = getULong(pos + 4*i);
- } else {
- origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
- }
- }
- qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaPos);
- for (i = 0; i < nGlyphs; ++i) {
- origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
- }
- origLocaTable[nGlyphs].length = 0;
- qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaIdx);
-
- // construct the new 'loca' table, padding each glyph out to a
- // multiple of 4 bytes
- locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
- pos = 0;
- for (i = 0; i <= nGlyphs; ++i) {
- if (locaFmt) {
- locaTable[4*i ] = (char)(pos >> 24);
- locaTable[4*i+1] = (char)(pos >> 16);
- locaTable[4*i+2] = (char)(pos >> 8);
- locaTable[4*i+3] = (char) pos;
- } else {
- locaTable[2*i ] = (char)(pos >> 9);
- locaTable[2*i+1] = (char)(pos >> 1);
- }
- length = origLocaTable[i].length;
- if (length & 3) {
- length += 4 - (length & 3);
- }
- pos += length;
- }
-
- // 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(headTable, 54);
- } else if (i == t42LocaTable) {
- length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
- checksum = computeTableChecksum(locaTable, length);
- } else if (i == t42GlyfTable) {
- length = 0;
- checksum = 0;
- glyfPos = seekTable("glyf");
- for (j = 0; j < nGlyphs; ++j) {
- glyphLength = origLocaTable[j].length;
- pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
- length += glyphLength + pad;
- if (glyphLength >= 0 &&
- glyfPos + origLocaTable[j].pos + glyphLength <= len) {
- checksum +=
- computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
- glyphLength);
- }
- }
- } else {
- if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
- length = tableHdrs[j].length;
- checksum = computeTableChecksum(file + tableHdrs[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) {
- strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
- newTableHdrs[k].checksum = checksum;
- newTableHdrs[k].offset = pos;
- newTableHdrs[k].length = length;
- pad = (length & 3) ? 4 - (length & 3) : 0;
- pos += length + pad;
- ++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] = (char)128;
- tableDir[8] = 0; // entrySelector
- tableDir[9] = 3;
- tableDir[10] = 0; // rangeShift
- tableDir[11] = (char)(16 * nNewTables - 128);
- pos = 12;
- for (i = 0; i < nNewTables; ++i) {
- tableDir[pos ] = newTableHdrs[i].tag[0];
- tableDir[pos+ 1] = newTableHdrs[i].tag[1];
- tableDir[pos+ 2] = newTableHdrs[i].tag[2];
- tableDir[pos+ 3] = newTableHdrs[i].tag[3];
- tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
- tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
- tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
- tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
- tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
- tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
- tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
- tableDir[pos+11] = (char) newTableHdrs[i].offset;
- tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
- tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
- tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
- tableDir[pos+15] = (char) newTableHdrs[i].length;
- pos += 16;
- }
-
- // compute the font checksum and store it in the head table
- checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
- for (i = 0; i < nNewTables; ++i) {
- checksum += newTableHdrs[i].checksum;
- }
- checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
- headTable[ 8] = (char)(checksum >> 24);
- headTable[ 9] = (char)(checksum >> 16);
- headTable[10] = (char)(checksum >> 8);
- headTable[11] = (char) 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(headTable, 54, outputFunc, outputStream);
- } else if (i == t42LocaTable) {
- length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
- dumpString(locaTable, length, outputFunc, outputStream);
- } else if (i == t42GlyfTable) {
- glyfPos = seekTable("glyf");
- for (j = 0; j < nGlyphs; ++j) {
- length = origLocaTable[j].length;
- if (length > 0 &&
- glyfPos + origLocaTable[j].pos + length <= len) {
- dumpString(file + glyfPos + origLocaTable[j].pos, length,
- 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 = newTableHdrs[i].length) > 0) {
- j = seekTable(t42Tables[i].tag);
- if (j >= 0) {
- dumpString(file + seekTable(t42Tables[i].tag), length,
- outputFunc, outputStream);
- }
- }
- }
- }
-
- // end the sfnts array
- (*outputFunc)(outputStream, "] def\n", 6);
-
- gfree(origLocaTable);
- gfree(locaTable);
-}
-
-void TrueTypeFontFile::dumpString(char *s, int length,
- FontFileOutputFunc 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 TrueTypeFontFile::computeTableChecksum(char *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 TrueTypeFontFile::writeTTF(FILE *out) {
- 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 haveCmap, haveName, havePost;
- GBool dirCmap, dirName, dirPost;
- GBool unsortedLoca;
- int nNewTables, nZeroLengthTables, nAllTables;
- TTFontTableHdr *newTableHdrs;
- char *tableDir;
- TrueTypeLoca *origLocaTable;
- char *locaTable;
- int length, glyfLength;
- Guint t, pos, pos2, pos3;
- int i, j, k;
-
- // check for missing/broken tables
- haveCmap = seekTable("cmap") >= 0;
- haveName = seekTable("name") >= 0;
- havePost = seekTable("post") >= 0;
- unsortedLoca = gFalse;
- pos = seekTable("loca");
- pos2 = 0;
- for (i = 0; i <= nGlyphs; ++i) {
- if (locaFmt) {
- pos3 = getULong(pos + 4*i);
- } else {
- pos3 = 2 * getUShort(pos + 2*i);
- }
- if (pos3 < pos2) {
- unsortedLoca = gTrue;
- break;
- }
- pos2 = pos3;
- }
- nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
- nZeroLengthTables = 0;
- for (i = 0; i < nTables; ++i) {
- if (tableHdrs[i].length == 0) {
- ++nZeroLengthTables;
- }
- }
- if (!nNewTables && !nZeroLengthTables && !mungedCmapSize && !unsortedLoca) {
- // nothing is broken - write the TTF file as is
- fwrite(file, 1, len, out);
- return;
- }
-
- // if the glyph data isn't sorted (as listed in the 'loca' table),
- // construct a new 'loca' table
- if (unsortedLoca) {
- origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
- sizeof(TrueTypeLoca));
- pos = seekTable("loca");
- for (i = 0; i <= nGlyphs; ++i) {
- origLocaTable[i].idx = i;
- if (locaFmt) {
- origLocaTable[i].pos = getULong(pos + 4*i);
- } else {
- origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
- }
- }
- qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
- &cmpTrueTypeLocaPos);
- for (i = 0; i < nGlyphs; ++i) {
- origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
- }
- origLocaTable[nGlyphs].length = 0;
- qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
- &cmpTrueTypeLocaIdx);
- locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
- pos = 0;
- for (i = 0; i <= nGlyphs; ++i) {
- if (locaFmt) {
- locaTable[4*i ] = (char)(pos >> 24);
- locaTable[4*i+1] = (char)(pos >> 16);
- locaTable[4*i+2] = (char)(pos >> 8);
- locaTable[4*i+3] = (char) pos;
- } else {
- locaTable[2*i ] = (char)(pos >> 9);
- locaTable[2*i+1] = (char)(pos >> 1);
- }
- length = origLocaTable[i].length;
- if (length & 3) {
- length += 4 - (length & 3);
- }
- pos += length;
- }
- glyfLength = pos;
- } else {
- origLocaTable = NULL; // make gcc happy
- locaTable = NULL; // make gcc happy
- glyfLength = 0; // make gcc happy
- }
-
- // construct the new table directory
- nAllTables = nTables - nZeroLengthTables + nNewTables;
- newTableHdrs = (TTFontTableHdr *)gmalloc(nAllTables *
- sizeof(TTFontTableHdr));
- dirCmap = haveCmap;
- dirName = haveName;
- dirPost = havePost;
- pos = 12 + nAllTables * 16;
- j = 0;
- for (i = 0; i < nTables; ++i) {
- if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
- memcpy(newTableHdrs[j].tag, "cmap", 4);
- newTableHdrs[j].checksum = 0; //~ should compute the checksum
- newTableHdrs[j].offset = pos;
- pos += newTableHdrs[j].length = sizeof(cmapTab);
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- dirCmap = gTrue;
- }
- if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
- memcpy(newTableHdrs[j].tag, "name", 4);
- newTableHdrs[j].checksum = 0; //~ should compute the checksum
- newTableHdrs[j].offset = pos;
- pos += newTableHdrs[j].length = sizeof(nameTab);
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- dirName = gTrue;
- }
- if (!dirPost && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
- memcpy(newTableHdrs[j].tag, "post", 4);
- newTableHdrs[j].checksum = 0; //~ should compute the checksum
- newTableHdrs[j].offset = pos;
- pos += newTableHdrs[j].length = sizeof(postTab);
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- dirPost = gTrue;
- }
- // throw away zero-length tables - they confuse FreeType
- if (tableHdrs[i].length > 0) {
- memcpy(newTableHdrs[j].tag, tableHdrs[i].tag, 4);
- newTableHdrs[j].checksum = tableHdrs[i].checksum;
- newTableHdrs[j].offset = pos;
- if (unsortedLoca && !strncmp(tableHdrs[i].tag, "loca", 4)) {
- newTableHdrs[j].length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
- } else if (unsortedLoca && !strncmp(tableHdrs[i].tag, "glyf", 4)) {
- newTableHdrs[j].length = glyfLength;
- } else {
- newTableHdrs[j].length = tableHdrs[i].length;
- }
- pos += newTableHdrs[j].length;
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- }
- }
- if (!dirCmap) {
- memcpy(newTableHdrs[j].tag, "cmap", 4);
- newTableHdrs[j].checksum = 0; //~ should compute the checksum
- newTableHdrs[j].offset = pos;
- pos += newTableHdrs[j].length = sizeof(cmapTab);
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- }
- if (!dirName) {
- memcpy(newTableHdrs[j].tag, "name", 4);
- newTableHdrs[j].checksum = 0; //~ should compute the checksum
- newTableHdrs[j].offset = pos;
- pos += newTableHdrs[j].length = sizeof(nameTab);
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- }
- if (!dirPost) {
- memcpy(newTableHdrs[j].tag, "post", 4);
- newTableHdrs[j].checksum = 0; //~ should compute the checksum
- newTableHdrs[j].offset = pos;
- pos += newTableHdrs[j].length = sizeof(postTab);
- if (pos & 3) {
- pos += 4 - (pos & 3);
- }
- ++j;
- }
- tableDir = (char *)gmalloc(12 + nAllTables * 16);
- tableDir[0] = 0x00; // sfnt version
- tableDir[1] = 0x01;
- tableDir[2] = 0x00;
- tableDir[3] = 0x00;
- tableDir[4] = (char)((nAllTables >> 8) & 0xff); // numTables
- tableDir[5] = (char)(nAllTables & 0xff);
- for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
- t = 1 << (4 + i);
- tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
- tableDir[7] = (char)(t & 0xff);
- tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
- tableDir[9] = (char)(i & 0xff);
- t = nAllTables * 16 - t;
- tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
- tableDir[11] = (char)(t & 0xff);
- pos = 12;
- for (i = 0; i < nAllTables; ++i) {
- tableDir[pos ] = newTableHdrs[i].tag[0];
- tableDir[pos+ 1] = newTableHdrs[i].tag[1];
- tableDir[pos+ 2] = newTableHdrs[i].tag[2];
- tableDir[pos+ 3] = newTableHdrs[i].tag[3];
- tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
- tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
- tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
- tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
- tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
- tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
- tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
- tableDir[pos+11] = (char) newTableHdrs[i].offset;
- tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
- tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
- tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
- tableDir[pos+15] = (char) newTableHdrs[i].length;
- pos += 16;
- }
-
- // write the table directory
- fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
-
- // write the tables
- for (i = 0; i < nAllTables; ++i) {
- if (!haveCmap && !strncmp(newTableHdrs[i].tag, "cmap", 4)) {
- fwrite(cmapTab, 1, newTableHdrs[i].length, out);
- } else if (!haveName && !strncmp(newTableHdrs[i].tag, "name", 4)) {
- fwrite(nameTab, 1, newTableHdrs[i].length, out);
- } else if (!havePost && !strncmp(newTableHdrs[i].tag, "post", 4)) {
- fwrite(postTab, 1, newTableHdrs[i].length, out);
- } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "loca", 4)) {
- fwrite(locaTable, 1, newTableHdrs[i].length, out);
- } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "glyf", 4)) {
- pos = seekTable("glyf");
- for (j = 0; j < nGlyphs; ++j) {
- length = origLocaTable[j].length;
- if (length > 0 &&
- pos + origLocaTable[j].pos + length <= (Guint)len) {
- fwrite(file + pos + origLocaTable[j].pos, 1, length, out);
- if ((k = length & 3)) {
- for (; k < 4; ++k) {
- fputc((char)0, out);
- }
- }
- }
- }
- } else {
- fwrite(file + seekTable(newTableHdrs[i].tag),
- 1, newTableHdrs[i].length, out);
- }
- if ((j = (newTableHdrs[i].length & 3))) {
- for (; j < 4; ++j) {
- fputc((char)0, out);
- }
- }
- }
-
- gfree(tableDir);
- gfree(newTableHdrs);
- if (unsortedLoca) {
- gfree(origLocaTable);
- gfree(locaTable);
- }
-}
diff --git a/pdf/xpdf/FontFile.h b/pdf/xpdf/FontFile.h
deleted file mode 100644
index 7aa5ba9..0000000
--- a/pdf/xpdf/FontFile.h
+++ /dev/null
@@ -1,261 +0,0 @@
-//========================================================================
-//
-// FontFile.h
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef FONTFILE_H
-#define FONTFILE_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "gtypes.h"
-#include "GString.h"
-#include "CharTypes.h"
-
-class GHash;
-class CharCodeToUnicode;
-
-//------------------------------------------------------------------------
-
-typedef void (*FontFileOutputFunc)(void *stream, char *data, int len);
-
-//------------------------------------------------------------------------
-// FontFile
-//------------------------------------------------------------------------
-
-class FontFile {
-public:
-
- FontFile();
- virtual ~FontFile();
-
- // Returns the font name, as specified internally by the font file.
- // Returns NULL if no name is available.
- virtual char *getName() = 0;
-
- // Returns the custom font encoding, or NULL if the encoding is not
- // available.
- virtual char **getEncoding() = 0;
-};
-
-//------------------------------------------------------------------------
-// Type1FontFile
-//------------------------------------------------------------------------
-
-class Type1FontFile: public FontFile {
-public:
-
- Type1FontFile(char *file, int len);
- virtual ~Type1FontFile();
- virtual char *getName() { return name; }
- virtual char **getEncoding() { return encoding; }
-
-private:
-
- char *name;
- char **encoding;
-};
-
-//------------------------------------------------------------------------
-// Type1CFontFile
-//------------------------------------------------------------------------
-
-struct Type1CTopDict;
-struct Type1CPrivateDict;
-
-class Type1CFontFile: public FontFile {
-public:
-
- Type1CFontFile(char *fileA, int lenA);
- virtual ~Type1CFontFile();
- GBool isOk() { return ok; }
-
- virtual char *getName();
- virtual char **getEncoding();
-
- // Convert to a Type 1 font, suitable for embedding in a PostScript
- // file. The name will be used as the PostScript font name.
- void convertToType1(FontFileOutputFunc outputFuncA, void *outputStreamA);
-
- // Convert to a Type 0 CIDFont, suitable for embedding in a
- // PostScript file. The name will be used as the PostScript font
- // name.
- void convertToCIDType0(char *psName,
- FontFileOutputFunc outputFuncA, void *outputStreamA);
-
- // Convert to a Type 0 (but non-CID) composite font, suitable for
- // embedding in a PostScript file. The name will be used as the
- // PostScript font name.
- void convertToType0(char *psName,
- FontFileOutputFunc outputFuncA, void *outputStreamA);
-
-private:
-
- void readEncoding();
- void readTopDict(Type1CTopDict *dict);
- void readPrivateDict(Type1CPrivateDict *privateDict,
- int offset, int size);
- Gushort *readCharset(int charset, int nGlyphs);
- void eexecWrite(char *s);
- void eexecCvtGlyph(char *glyphName, int pos, int n);
- void cvtGlyph(int pos, int n, GBool top);
- void cvtGlyphWidth(GBool useOp);
- void eexecDumpNum(double x, GBool fpA);
- void eexecDumpOp1(int opA);
- void eexecDumpOp2(int opA);
- void eexecWriteCharstring(Guchar *s, int n);
- void getDeltaInt(char *buf, char *key, double *opA, int n);
- void getDeltaReal(char *buf, char *key, double *opA, int n);
- int getIndexLen(int indexPos);
- int getIndexValPos(int indexPos, int i, int *valLen);
- int getIndexEnd(int indexPos);
- Guint getWord(int pos, int size);
- double getNum(int *pos, GBool *fp);
- char *getString(int sid, char *buf);
-
- Guchar *file;
- int len;
-
- GString *name;
- char **encoding;
-
- int topDictIdxPos;
- int stringIdxPos;
- int gsubrIdxPos;
- int subrIdxPos;
- int gsubrBias;
- int subrBias;
-
- FontFileOutputFunc outputFunc;
- void *outputStream;
- double op[48]; // operands
- GBool fp[48]; // true if operand is fixed point
- int nOps; // number of operands
- int nHints; // number of hints for the current glyph
- GBool firstOp; // true if we haven't hit the first op yet
- double defaultWidthX; // default glyph width
- double nominalWidthX; // nominal glyph width
- GBool defaultWidthXFP; // true if defaultWidthX is fixed point
- GBool nominalWidthXFP; // true if nominalWidthX is fixed point
- Gushort r1; // eexec encryption key
- GString *charBuf; // charstring output buffer
- int line; // number of eexec chars on current line
-
- GBool ok;
-};
-
-//------------------------------------------------------------------------
-// TrueTypeFontFile
-//------------------------------------------------------------------------
-
-struct TTFontTableHdr;
-struct TTFontCmap;
-
-class TrueTypeFontFile: public FontFile {
-public:
-
- TrueTypeFontFile(char *fileA, int lenA);
- ~TrueTypeFontFile();
-
- // This always returns NULL, since it's probably better to trust the
- // font name in the PDF file rather than the one in the TrueType
- // font file.
- virtual char *getName();
-
- virtual char **getEncoding();
-
- // 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 enc);
-
- // Return the GID corresponding to <c> according to the <i>th cmap.
- Gushort mapCodeToGID(int i, int c);
-
- // Return a name-to-GID mapping, constructed from the font's post
- // table. Returns NULL if there is no post table.
- GHash *getNameToGID();
-
- // Convert to a Type 42 font, suitable for embedding in a PostScript
- // file. The name will be used as the PostScript font name (so we
- // don't need to depend on the 'name' table in the font). The
- // encoding is needed because the PDF Font object can modify the
- // encoding.
- void convertToType42(char *name, char **encodingA,
- GBool pdfFontHasEncoding,
- Gushort *codeToGID,
- FontFileOutputFunc outputFunc, void *outputStream);
-
- // Convert to a Type 2 CIDFont, suitable for embedding in a
- // PostScript file. The name will be used as the PostScript font
- // name (so we don't need to depend on the 'name' table in the
- // font).
- void convertToCIDType2(char *name, Gushort *cidMap, int nCIDs,
- FontFileOutputFunc outputFunc, void *outputStream);
-
- // Convert to a Type 0 (but non-CID) composite font, suitable for
- // embedding in a PostScript file. The name will be used as the
- // PostScript font name (so we don't need to depend on the 'name'
- // table in the font).
- void convertToType0(char *name, Gushort *cidMap, int nCIDs,
- FontFileOutputFunc outputFunc, void *outputStream);
-
- // Write a TTF file, filling in any missing tables that are required
- // by the TrueType spec. If the font already has all the required
- // tables, it will be written unmodified.
- void writeTTF(FILE *out);
-
-private:
-
- char *file;
- int len;
-
- char **encoding;
-
- TTFontTableHdr *tableHdrs;
- int nTables;
- int bbox[4];
- int locaFmt;
- int nGlyphs;
- GBool mungedCmapSize;
- TTFontCmap *cmaps;
- int nCmaps;
-
- int getByte(int pos);
- int getChar(int pos);
- int getUShort(int pos);
- int getShort(int pos);
- Guint getULong(int pos);
- double getFixed(int pos);
- int seekTable(char *tag);
- int seekTableIdx(char *tag);
- void cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
- FontFileOutputFunc outputFunc, void *outputStream);
- void cvtCharStrings(char **encodingA, GBool pdfFontHasEncoding,
- Gushort *codeToGID,
- FontFileOutputFunc outputFunc, void *outputStream);
- int getCmapEntry(int cmapFmt, int pos, int code);
- void cvtSfnts(FontFileOutputFunc outputFunc, void *outputStream,
- GString *name);
- void dumpString(char *s, int length,
- FontFileOutputFunc outputFunc, void *outputStream);
- Guint computeTableChecksum(char *data, int length);
-};
-
-#endif
diff --git a/pdf/xpdf/Function.h b/pdf/xpdf/Function.h
index d795a51..0ceb035 100644
--- a/pdf/xpdf/Function.h
+++ b/pdf/xpdf/Function.h
@@ -27,8 +27,8 @@ class PSStack;
// Function
//------------------------------------------------------------------------
-#define funcMaxInputs 8
-#define funcMaxOutputs 8
+#define funcMaxInputs 8
+#define funcMaxOutputs 32
class Function {
public:
diff --git a/pdf/xpdf/Gfx.cc b/pdf/xpdf/Gfx.cc
index d108208..a52aa02 100644
--- a/pdf/xpdf/Gfx.cc
+++ b/pdf/xpdf/Gfx.cc
@@ -1254,6 +1254,7 @@ void Gfx::doPatternFill(GBool eoFill) {
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;
@@ -1303,6 +1304,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
// save current graphics state
+ savedPath = state->getPath()->copy();
saveState();
// set underlying color space (for uncolored tiling patterns); set
@@ -1378,17 +1380,17 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, 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];
}
for (yi = yi0; yi < yi1; ++yi) {
for (xi = xi0; xi < xi1; ++xi) {
- x = xi * xstep - tPat->getBBox()[0];
- y = yi * ystep - tPat->getBBox()[1];
+ x = xi * xstep;
+ y = yi * ystep;
m1[4] = x * m[0] + y * m[2] + m[4];
m1[5] = x * m[1] + y * m[3] + m[5];
doForm1(tPat->getContentStream(), tPat->getResDict(),
@@ -1398,10 +1400,12 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
// restore graphics 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;
@@ -1410,6 +1414,7 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
shading = sPat->getShading();
// save current graphics state
+ savedPath = state->getPath()->copy();
saveState();
// clip to bbox
@@ -1483,10 +1488,12 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
// 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()))) {
@@ -1494,6 +1501,7 @@ void Gfx::opShFill(Object args[], int numArgs) {
}
// save current graphics state
+ savedPath = state->getPath()->copy();
saveState();
// clip to bbox
@@ -1527,6 +1535,7 @@ void Gfx::opShFill(Object args[], int numArgs) {
// restore graphics state
restoreState();
+ state->setPath(savedPath);
delete shading;
}
@@ -2335,6 +2344,8 @@ 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();
@@ -2361,7 +2372,8 @@ void Gfx::doShowText(GString *s) {
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);
@@ -2970,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;
diff --git a/pdf/xpdf/Gfx.h b/pdf/xpdf/Gfx.h
index 20898ec..2069e97 100644
--- a/pdf/xpdf/Gfx.h
+++ b/pdf/xpdf/Gfx.h
@@ -35,7 +35,7 @@ class GfxFunctionShading;
class GfxAxialShading;
class GfxRadialShading;
class GfxState;
-class GfxColor;
+struct GfxColor;
class Gfx;
class PDFRectangle;
diff --git a/pdf/xpdf/GfxFont.cc b/pdf/xpdf/GfxFont.cc
index 6f83676..ed9f076 100644
--- a/pdf/xpdf/GfxFont.cc
+++ b/pdf/xpdf/GfxFont.cc
@@ -17,7 +17,6 @@
#include <string.h>
#include <ctype.h>
#include "gmem.h"
-#include "GHash.h"
#include "Error.h"
#include "Object.h"
#include "Dict.h"
@@ -26,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"
//------------------------------------------------------------------------
@@ -89,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" }
};
//------------------------------------------------------------------------
@@ -400,7 +404,8 @@ 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;
@@ -554,43 +559,51 @@ 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 (type == fontType1) {
- fontFile = new Type1FontFile(buf, len);
- } else {
- fontFile = new Type1CFontFile(buf, len);
- if (!((Type1CFontFile *)fontFile)->isOk()) {
- delete fontFile;
- fontFile = NULL;
+ if (ffT1) {
+ if (ffT1->getName()) {
+ if (embFontName) {
+ delete embFontName;
}
+ embFontName = new GString(ffT1->getName());
+ }
+ if (!baseEnc) {
+ baseEnc = ffT1->getEncoding();
+ baseEncFromFontFile = gTrue;
}
- if (fontFile && 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 (fontFile && !baseEnc) {
- baseEnc = fontFile->getEncoding();
+ if (!baseEnc) {
+ baseEnc = ffT1C->getEncoding();
baseEncFromFontFile = gTrue;
}
- gfree(buf);
}
}
+ if (buf) {
+ gfree(buf);
+ }
// get default base encoding
if (!baseEnc) {
@@ -612,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);
@@ -641,8 +668,11 @@ 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 -----
@@ -860,12 +890,11 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
return ctu;
}
-Gushort *Gfx8BitFont::getCodeToGIDMap(TrueTypeFontFile *ff) {
+Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
Gushort *map;
int cmapPlatform, cmapEncoding;
int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
GBool useMacRoman, useUnicode;
- GHash *nameToGID;
char *charName;
Unicode u;
int code, i, n;
@@ -966,13 +995,10 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(TrueTypeFontFile *ff) {
}
// try the TrueType 'post' table to handle any unmapped characters
- if ((nameToGID = ff->getNameToGID())) {
- for (i = 0; i < 256; ++i) {
- if (!map[i] && (charName = enc[i])) {
- map[i] = (Gushort)(int)nameToGID->lookup(charName);
- }
+ for (i = 0; i < 256; ++i) {
+ if (!map[i] && (charName = enc[i])) {
+ map[i] = (Gushort)(int)ff->mapNameToGID(charName);
}
- delete nameToGID;
}
return map;
@@ -983,7 +1009,7 @@ Dict *Gfx8BitFont::getCharProcs() {
}
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
- if (charProcs.isDict()) {
+ if (enc[code] && charProcs.isDict()) {
charProcs.dictLookup(enc[code], proc);
} else {
proc->initNull();
@@ -1406,7 +1432,9 @@ int GfxCIDFont::getWMode() {
}
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
- ctu->incRefCnt();
+ if (ctu) {
+ ctu->incRefCnt();
+ }
return ctu;
}
diff --git a/pdf/xpdf/GfxFont.h b/pdf/xpdf/GfxFont.h
index ddd88be..62dfd08 100644
--- a/pdf/xpdf/GfxFont.h
+++ b/pdf/xpdf/GfxFont.h
@@ -23,7 +23,7 @@
class Dict;
class CMap;
class CharCodeToUnicode;
-class TrueTypeFontFile;
+class FoFiTrueType;
struct GfxFontCIDWidths;
//------------------------------------------------------------------------
@@ -220,7 +220,7 @@ public:
// Return a char code-to-GID mapping for the provided font file.
// (This is only useful for TrueType fonts.)
- Gushort *getCodeToGIDMap(TrueTypeFontFile *ff);
+ Gushort *getCodeToGIDMap(FoFiTrueType *ff);
// Return the Type 3 CharProc dictionary, or NULL if none.
Dict *getCharProcs();
diff --git a/pdf/xpdf/GfxState.cc b/pdf/xpdf/GfxState.cc
index d202939..be60405 100644
--- a/pdf/xpdf/GfxState.cc
+++ b/pdf/xpdf/GfxState.cc
@@ -766,12 +766,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
}
//------------------------------------------------------------------------
@@ -1053,6 +1059,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)");
@@ -2030,13 +2041,18 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
colorSpace2 = indexedCS->getBase();
indexHigh = indexedCS->getIndexHigh();
nComps2 = colorSpace2->getNComps();
- lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
lookup2 = indexedCS->getLookup();
colorSpace2->getDefaultRanges(x, y, indexHigh);
- for (i = 0; i <= indexHigh; ++i) {
+ 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[j*nComps2 + k] = x[k] + (lookup2[i*nComps2 + k] / 255.0) * y[k];
+ lookup[i*nComps2 + k] = x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k];
}
}
} else if (colorSpace->getMode() == csSeparation) {
@@ -2079,17 +2095,15 @@ GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
nComps2 = colorMap->nComps2;
colorSpace2 = NULL;
lookup = NULL;
+ n = 1 << bits;
if (colorSpace->getMode() == csIndexed) {
colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
- n = ((GfxIndexedColorSpace *)colorSpace)->getIndexHigh();
- n = (n + 1) * nComps2 * sizeof(double);
+ n = n * nComps2 * sizeof(double);
} else if (colorSpace->getMode() == csSeparation) {
colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
- n = (1 << bits) - 1;
- n = (n + 1) * nComps2 * sizeof(double);
+ n = n * nComps2 * sizeof(double);
} else {
- n = (1 << bits) - 1;
- n = (n + 1) * nComps * sizeof(double);
+ n = n * nComps * sizeof(double);
}
lookup = (double *)gmalloc(n);
memcpy(lookup, colorMap->lookup, n);
@@ -2497,6 +2511,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/pdf/xpdf/GfxState.h b/pdf/xpdf/GfxState.h
index d072fd3..f747a83 100644
--- a/pdf/xpdf/GfxState.h
+++ b/pdf/xpdf/GfxState.h
@@ -429,7 +429,6 @@ private:
*names[gfxColorMaxComps];
GfxColorSpace *alt; // alternate color space
Function *func; // tint transform (into alternate color space)
-
};
//------------------------------------------------------------------------
@@ -910,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)
diff --git a/pdf/xpdf/GlobalParams.cc b/pdf/xpdf/GlobalParams.cc
index 9aa54e9..c125430 100644
--- a/pdf/xpdf/GlobalParams.cc
+++ b/pdf/xpdf/GlobalParams.cc
@@ -13,6 +13,7 @@
#endif
#include <string.h>
+#include <stdio.h>
#include <ctype.h>
#if HAVE_PAPER_H
#include <paper.h>
@@ -49,7 +50,6 @@
#include "NameToUnicodeTable.h"
#include "UnicodeMapTables.h"
-#include "DisplayFontTable.h"
#include "UTF8.h"
//------------------------------------------------------------------------
@@ -59,6 +59,36 @@
//------------------------------------------------------------------------
+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;
//------------------------------------------------------------------------
@@ -70,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;
@@ -83,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;
@@ -140,7 +151,6 @@ PSFontParam::~PSFontParam() {
GlobalParams::GlobalParams(char *cfgFileName) {
UnicodeMap *map;
- DisplayFontParam *dfp;
GString *fileName;
FILE *f;
int i;
@@ -190,6 +200,13 @@ GlobalParams::GlobalParams(char *cfgFileName) {
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;
@@ -214,8 +231,9 @@ GlobalParams::GlobalParams(char *cfgFileName) {
textKeepTinyChars = gFalse;
fontDirs = new GList();
initialZoom = new GString("125");
- t1libControl = fontRastAALow;
- freetypeControl = fontRastAALow;
+ enableT1lib = gTrue;
+ enableFreeType = gTrue;
+ antialias = gTrue;
urlCommand = NULL;
movieCommand = NULL;
mapNumericCharNames = gTrue;
@@ -251,14 +269,6 @@ GlobalParams::GlobalParams(char *cfgFileName) {
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;
@@ -356,18 +366,10 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
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("displayNamedCIDFontX")) {
- parseDisplayFont(tokens, displayNamedCIDFonts,
- displayFontX, fileName, line);
- } else if (!cmd->cmp("displayCIDFontX")) {
- parseDisplayFont(tokens, displayCIDFonts,
- displayFontX, fileName, line);
} else if (!cmd->cmp("displayNamedCIDFontT1")) {
parseDisplayFont(tokens, displayNamedCIDFonts,
displayFontT1, fileName, line);
@@ -391,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")) {
@@ -424,12 +437,12 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
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")) {
parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
} else if (!cmd->cmp("movieCommand")) {
@@ -441,12 +454,19 @@ void GlobalParams::parseFile(GString *fileName, FILE *f) {
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");
+ }
}
}
@@ -580,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;
@@ -629,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;
@@ -767,23 +796,6 @@ 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;
-
- 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);
- }
-}
-
void GlobalParams::parseCommand(char *cmdName, GString **val,
GList *tokens, GString *fileName, int line) {
if (tokens->getLength() != 2) {
@@ -807,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() {
@@ -870,6 +889,54 @@ GlobalParams::~GlobalParams() {
}
//------------------------------------------------------------------------
+
+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);
+ }
+}
+
+//------------------------------------------------------------------------
// accessors
//------------------------------------------------------------------------
@@ -1004,6 +1071,51 @@ int GlobalParams::getPSPaperHeight() {
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;
@@ -1185,22 +1297,32 @@ GString *GlobalParams::getInitialZoom() {
return s;
}
-FontRastControl GlobalParams::getT1libControl() {
- FontRastControl c;
+GBool GlobalParams::getEnableT1lib() {
+ GBool f;
+
+ lockGlobalParams;
+ f = enableT1lib;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getEnableFreeType() {
+ GBool f;
lockGlobalParams;
- c = t1libControl;
+ f = enableFreeType;
unlockGlobalParams;
- return c;
+ return f;
}
-FontRastControl GlobalParams::getFreeTypeControl() {
- FontRastControl c;
+
+GBool GlobalParams::getAntialias() {
+ GBool f;
lockGlobalParams;
- c = freetypeControl;
+ f = antialias;
unlockGlobalParams;
- return c;
+ return f;
}
GBool GlobalParams::getMapNumericCharNames() {
@@ -1345,6 +1467,9 @@ GBool GlobalParams::setPSPaperSize(char *size) {
unlockGlobalParams;
return gFalse;
}
+ psImageableLLX = psImageableLLY = 0;
+ psImageableURX = psPaperWidth;
+ psImageableURY = psPaperHeight;
unlockGlobalParams;
return gTrue;
}
@@ -1352,12 +1477,49 @@ GBool GlobalParams::setPSPaperSize(char *size) {
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;
}
@@ -1451,40 +1613,32 @@ void GlobalParams::setInitialZoom(char *s) {
unlockGlobalParams;
}
-GBool GlobalParams::setT1libControl(char *s) {
+GBool GlobalParams::setEnableT1lib(char *s) {
GBool ok;
lockGlobalParams;
- ok = setFontRastControl(&t1libControl, s);
+ ok = parseYesNo2(s, &enableT1lib);
unlockGlobalParams;
return ok;
}
-GBool GlobalParams::setFreeTypeControl(char *s) {
+GBool GlobalParams::setEnableFreeType(char *s) {
GBool ok;
lockGlobalParams;
- ok = setFontRastControl(&freetypeControl, s);
+ ok = parseYesNo2(s, &enableFreeType);
unlockGlobalParams;
return ok;
}
-GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
+
+GBool GlobalParams::setAntialias(char *s) {
+ GBool ok;
+
lockGlobalParams;
- 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 {
- unlockGlobalParams;
- return gFalse;
- }
+ ok = parseYesNo2(s, &antialias);
unlockGlobalParams;
- return gTrue;
+ return ok;
}
void GlobalParams::setMapNumericCharNames(GBool map) {
diff --git a/pdf/xpdf/GlobalParams.h b/pdf/xpdf/GlobalParams.h
index 472beed..93ec06a 100644
--- a/pdf/xpdf/GlobalParams.h
+++ b/pdf/xpdf/GlobalParams.h
@@ -43,7 +43,6 @@ extern GlobalParams *globalParams;
//------------------------------------------------------------------------
enum DisplayFontParamKind {
- displayFontX,
displayFontT1,
displayFontTT
};
@@ -57,10 +56,6 @@ public:
DisplayFontParamKind kind;
union {
struct {
- GString *xlfd;
- GString *encoding;
- } x;
- struct {
GString *fileName;
} t1;
struct {
@@ -69,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 {
@@ -129,6 +115,8 @@ public:
~GlobalParams();
+ void setupBaseFonts(char *dir);
+
//----- accessors
CharCode getMacRomanCharCode(char *charName);
@@ -143,7 +131,12 @@ public:
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);
@@ -159,8 +152,9 @@ public:
GBool getTextKeepTinyChars();
GString *findFontFile(GString *fontName, char **exts);
GString *getInitialZoom();
- FontRastControl getT1libControl();
- FontRastControl getFreeTypeControl();
+ GBool getEnableT1lib();
+ GBool getEnableFreeType();
+ GBool getAntialias();
GString *getURLCommand() { return urlCommand; }
GString *getMovieCommand() { return movieCommand; }
GBool getMapNumericCharNames();
@@ -180,7 +174,12 @@ public:
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);
@@ -193,8 +192,9 @@ public:
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);
@@ -213,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,
@@ -221,14 +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 parseCommand(char *cmdName, GString **val,
GList *tokens, GString *fileName, int line);
void parseYesNo(char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line);
+ GBool parseYesNo2(char *token, GBool *flag);
UnicodeMap *getUnicodeMap2(GString *encodingName);
- GBool setFontRastControl(FontRastControl *val, char *s);
//----- static tables
@@ -260,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
@@ -280,9 +287,9 @@ private:
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)?
diff --git a/pdf/xpdf/Makefile.am b/pdf/xpdf/Makefile.am
index 96d57ec..db62813 100644
--- a/pdf/xpdf/Makefile.am
+++ b/pdf/xpdf/Makefile.am
@@ -4,6 +4,8 @@ INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/goo \
-I$(top_srcdir)/lib/ggv-sidebar \
+ -I$(top_srcdir)/fofi \
+ -I$(top_srcdir)/splash \
-DDATADIR=\""$(datadir)"\" \
-DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DGNOMEICONDIR=\""$(datadir)/pixmaps"\" \
@@ -55,8 +57,6 @@ libxpdf_a_SOURCES = \
Error.h \
FontEncodingTables.cc \
FontEncodingTables.h \
- FontFile.cc \
- FontFile.h \
Function.cc \
Function.h \
Gfx.cc \
@@ -67,8 +67,12 @@ libxpdf_a_SOURCES = \
GfxState.h \
GlobalParams.cc \
GlobalParams.h \
+ JArithmeticDecoder.cc \
+ JArithmeticDecoder.h \
JBIG2Stream.cc \
JBIG2Stream.h \
+ JPXStream.cc \
+ JPXStream.h \
Lexer.cc \
Lexer.h \
Link.cc \
@@ -98,23 +102,15 @@ libxpdf_a_SOURCES = \
UnicodeMap.h \
UnicodeMapTables.h \
UnicodeTypeTable.cc \
+ UnicodeTypeTable.h \
XRef.cc \
XRef.h
common_sources = \
CharTypes.h \
CompactFontTables.h \
- DisplayFontTable.h \
ErrorCodes.h \
- FTFont.cc \
- FTFont.h \
NameToUnicodeTable.h \
- SFont.cc \
- SFont.h \
- T1Font.cc \
- T1Font.h \
- TTFont.cc \
- TTFont.h \
TextOutputDev.cc \
TextOutputDev.h \
UTF8.h
@@ -200,12 +196,15 @@ gnome_pdf_viewer_LDADD = \
libxpdf.a \
libgpdf.a \
$(top_builddir)/goo/libGoo.a \
+ $(top_builddir)/fofi/libfofi.a \
$(top_builddir)/lib/ggv-sidebar/libggv-sidebar.a \
$(EXTRA_GNOME_LIBS) \
$(libpaper_LIBS)
xpdf_SOURCES = \
$(common_sources) \
+ SplashOutputDev.cc \
+ SplashOutputDev.h \
XPDFApp.cc \
XPDFApp.h \
XPDFCore.cc \
@@ -214,10 +213,8 @@ xpdf_SOURCES = \
XPDFTree.h \
XPDFViewer.cc \
XPDFViewer.h \
- XOutputDev.cc \
- XOutputDev.h \
- XPixmapOutputDev.cc \
- XPixmapOutputDev.h \
+ XSplashOutputDev.cc \
+ XSplashOutputDev.h \
PSOutputDev.cc \
PSOutputDev.h \
xpdf.cc
@@ -254,16 +251,14 @@ xpdf_LDADD = \
# pdfinfo.cc
#pdfinfo_LDADD = ../goo/libGoo.a
-#pdftopbm_SOURCES =
+#pdftopüm_SOURCES =
# $(common_sources)
-# PBMOutputDev.cc
-# PBMOutputDev.h
# XOutputDev.cc
# XOutputDev.h
# XOutputFontInfo.h
# pdftopbm.cc
-#pdftopbm_LDADD = ../goo/libGoo.a $(EXTRA_GNOME_LIBS)
+#pdftoppm_LDADD = ../goo/libGoo.a $(EXTRA_GNOME_LIBS)
#bitmaps =
# about.xbm
diff --git a/pdf/xpdf/Object.cc b/pdf/xpdf/Object.cc
index b0976fd..ddd6da6 100644
--- a/pdf/xpdf/Object.cc
+++ b/pdf/xpdf/Object.cc
@@ -58,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/pdf/xpdf/Object.h b/pdf/xpdf/Object.h
index 8f0b370..8b1807c 100644
--- a/pdf/xpdf/Object.h
+++ b/pdf/xpdf/Object.h
@@ -95,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; }
diff --git a/pdf/xpdf/Outline.cc b/pdf/xpdf/Outline.cc
index 23efed1..b7e0645 100644
--- a/pdf/xpdf/Outline.cc
+++ b/pdf/xpdf/Outline.cc
@@ -22,15 +22,17 @@
//------------------------------------------------------------------------
Outline::Outline(Object *outlineObj, XRef *xref) {
- Object first;
+ 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() {
@@ -68,6 +70,8 @@ OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
}
}
+ } else {
+ titleLen = 0;
}
obj1.free();
@@ -82,6 +86,7 @@ OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
obj1.free();
dict->lookupNF("First", &firstRef);
+ dict->lookupNF("Last", &lastRef);
dict->lookupNF("Next", &nextRef);
startsOpen = gFalse;
@@ -102,17 +107,19 @@ OutlineItem::~OutlineItem() {
delete action;
}
firstRef.free();
+ lastRef.free();
nextRef.free();
}
-GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
+GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
+ XRef *xrefA) {
GList *items;
OutlineItem *item;
Object obj;
Object *p;
items = new GList();
- p = itemRef;
+ p = firstItemRef;
while (p->isRef()) {
if (!p->fetch(xrefA, &obj)->isDict()) {
obj.free();
@@ -121,6 +128,10 @@ GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
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;
@@ -128,7 +139,7 @@ GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
void OutlineItem::open() {
if (!kids) {
- kids = readItemList(&firstRef, xref);
+ kids = readItemList(&firstRef, &lastRef, xref);
}
}
diff --git a/pdf/xpdf/OutputDev.cc b/pdf/xpdf/OutputDev.cc
index cbb5df5..e83882d 100644
--- a/pdf/xpdf/OutputDev.cc
+++ b/pdf/xpdf/OutputDev.cc
@@ -60,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/pdf/xpdf/OutputDev.h b/pdf/xpdf/OutputDev.h
index 67737af..bbf8b69 100644
--- a/pdf/xpdf/OutputDev.h
+++ b/pdf/xpdf/OutputDev.h
@@ -126,7 +126,8 @@ 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) {}
diff --git a/pdf/xpdf/PBMOutputDev.cc b/pdf/xpdf/PBMOutputDev.cc
deleted file mode 100644
index dde860a..0000000
--- a/pdf/xpdf/PBMOutputDev.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-//========================================================================
-//
-// PBMOutputDev.cc
-//
-// Copyright 1998-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include "gmem.h"
-#include "GString.h"
-#include "Object.h"
-#include "Stream.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "Error.h"
-#include "PBMOutputDev.h"
-
-//------------------------------------------------------------------------
-
-PBMOutputDev *PBMOutputDev::makePBMOutputDev(char *displayName,
- char *fileRootA) {
- Display *displayA;
- Pixmap pixmapA;
- Window dummyWinA;
- int screenA;
- int invertA;
- unsigned long black, white;
- PBMOutputDev *out;
-
- if (!(displayA = XOpenDisplay(displayName))) {
- fprintf(stderr, "Couldn't open display '%s'\n", displayName);
- exit(1);
- }
- screenA = DefaultScreen(displayA);
-
- black = BlackPixel(displayA, screenA);
- white = WhitePixel(displayA, screenA);
- if ((black & 1) == (white & 1)) {
- fprintf(stderr, "Weird black/white pixel colors\n");
- XCloseDisplay(displayA);
- return NULL;
- }
- invertA = (white & 1) == 1 ? 0xff : 0x00;
-
- dummyWinA = XCreateSimpleWindow(displayA, RootWindow(displayA, screenA),
- 0, 0, 1, 1, 0,
- black, white);
- pixmapA = XCreatePixmap(displayA, dummyWinA, 1, 1, 1);
- out = new PBMOutputDev(displayA, screenA, pixmapA, dummyWinA,
- invertA, fileRootA);
- return out;
-}
-
-void PBMOutputDev::killPBMOutputDev(PBMOutputDev *out) {
- Display *displayA;
- Pixmap pixmapA;
- Window dummyWinA;
-
- displayA = out->display;
- pixmapA = out->pixmap;
- dummyWinA = out->dummyWin;
-
- delete out;
-
- // these have to be done *after* the XOutputDev (parent of the
- // PBMOutputDev) is deleted, since XOutputDev::~XOutputDev() needs
- // them
- XFreePixmap(displayA, pixmapA);
- XDestroyWindow(displayA, dummyWinA);
- XCloseDisplay(displayA);
-}
-
-PBMOutputDev::PBMOutputDev(Display *displayA, int screenA,
- Pixmap pixmapA, Window dummyWinA,
- int invertA, char *fileRootA):
- XOutputDev(displayA, screenA,
- DefaultVisual(displayA, screenA),
- DefaultColormap(displayA, screenA),
- gFalse,
- WhitePixel(displayA, DefaultScreen(displayA)),
- gFalse, 1, 1)
-{
- display = displayA;
- screen = screenA;
- pixmap = pixmapA;
- dummyWin = dummyWinA;
- invert = invertA;
- fileRoot = fileRootA;
- fileName = (char *)gmalloc(strlen(fileRoot) + 20);
-}
-
-PBMOutputDev::~PBMOutputDev() {
- gfree(fileName);
-}
-
-void PBMOutputDev::startPage(int pageNum, GfxState *state) {
- curPage = pageNum;
- width = (int)(state->getPageWidth() + 0.5);
- height = (int)(state->getPageHeight() + 0.5);
- XFreePixmap(display, pixmap);
- pixmap = XCreatePixmap(display, dummyWin, width, height, 1);
- setPixmap(pixmap, width, height);
- XOutputDev::startPage(pageNum, state);
-}
-
-void PBMOutputDev::endPage() {
- XImage *image;
- FILE *f;
- int p;
- int x, y, i;
-
- image = XCreateImage(display, DefaultVisual(display, screen),
- 1, ZPixmap, 0, NULL, width, height, 8, 0);
- image->data = (char *)gmalloc(height * image->bytes_per_line);
- XGetSubImage(display, pixmap, 0, 0, width, height, 1, ZPixmap,
- image, 0, 0);
-
- sprintf(fileName, "%s-%06d.pbm", fileRoot, curPage);
- if (!(f = fopen(fileName, "wb"))) {
- fprintf(stderr, "Couldn't open output file '%s'\n", fileName);
- goto err;
- }
- fprintf(f, "P4\n");
- fprintf(f, "%d %d\n", width, height);
-
- for (y = 0; y < height; ++y) {
- for (x = 0; x+8 <= width; x += 8) {
- p = 0;
- for (i = 0; i < 8; ++i)
- p = (p << 1) + (XGetPixel(image, x+i, y) & 1);
- p ^= invert;
- fputc((char)p, f);
- }
- if (width & 7) {
- p = 0;
- for (i = 0; i < (width & 7); ++i)
- p = (p << 1) + (XGetPixel(image, x+i, y) & 1);
- p <<= 8 - (width & 7);
- p ^= invert;
- fputc((char)p, f);
- }
- }
-
- fclose(f);
-
- err:
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
-
- XOutputDev::endPage();
-}
diff --git a/pdf/xpdf/PBMOutputDev.h b/pdf/xpdf/PBMOutputDev.h
deleted file mode 100644
index 9d1539d..0000000
--- a/pdf/xpdf/PBMOutputDev.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//========================================================================
-//
-// PBMOutputDev.h
-//
-// Copyright 1998-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef PBMOUTPUTDEV_H
-#define PBMOUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stddef.h>
-#include "config.h"
-#include "XOutputDev.h"
-
-//------------------------------------------------------------------------
-
-class PBMOutputDev: public XOutputDev {
-public:
-
- // NB: Users must use makePBMOutputDev and killPBMOutputDev rather
- // than the constructor and destructor. (This is due to some
- // constraints in the underlying XOutputDev object.)
-
- static PBMOutputDev *makePBMOutputDev(char *displayName,
- char *fileRootA);
-
- static void killPBMOutputDev(PBMOutputDev *out);
-
- virtual ~PBMOutputDev();
-
- //----- initialization and control
-
- // Start a page.
- virtual void startPage(int pageNum, GfxState *state);
-
- // End a page.
- virtual void endPage();
-
-private:
-
- PBMOutputDev(Display *displayA, int screenA,
- Pixmap pixmapA, Window dummyWinA,
- int invertA, char *fileRootA);
-
- char *fileRoot;
- char *fileName;
- int curPage;
-
- Display *display;
- int screen;
- Pixmap pixmap;
- Window dummyWin;
- int width, height;
- int invert;
-};
-
-#endif
diff --git a/pdf/xpdf/PDFDoc.cc b/pdf/xpdf/PDFDoc.cc
index c92048b..e156c3f 100644
--- a/pdf/xpdf/PDFDoc.cc
+++ b/pdf/xpdf/PDFDoc.cc
@@ -206,7 +206,7 @@ void PDFDoc::checkHeader() {
}
void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
- int rotate, GBool doLinks,
+ int rotate, GBool crop, GBool doLinks,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -223,18 +223,19 @@ void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
links = NULL;
}
getLinks(p);
- p->display(out, hDPI, vDPI, rotate, links, catalog,
+ p->display(out, hDPI, vDPI, rotate, crop, links, catalog,
abortCheckCbk, abortCheckCbkData,
annotDisplayDecideCbk, annotDisplayDecideCbkData);
} else {
- p->display(out, hDPI, vDPI, rotate, NULL, catalog,
+ p->display(out, hDPI, vDPI, rotate, crop, NULL, catalog,
abortCheckCbk, abortCheckCbkData,
annotDisplayDecideCbk, annotDisplayDecideCbkData);
}
}
void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
- double hDPI, double vDPI, int rotate, GBool doLinks,
+ double hDPI, double vDPI, int rotate,
+ GBool crop, GBool doLinks,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -242,7 +243,7 @@ void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
int page;
for (page = firstPage; page <= lastPage; ++page) {
- displayPage(out, page, hDPI, vDPI, rotate, doLinks,
+ displayPage(out, page, hDPI, vDPI, rotate, crop, doLinks,
abortCheckCbk, abortCheckCbkData,
annotDisplayDecideCbk, annotDisplayDecideCbkData);
}
@@ -250,8 +251,8 @@ void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
void PDFDoc::displayPageSlice(OutputDev *out, int page,
double hDPI, double vDPI,
- int rotate, int sliceX, int sliceY,
- int sliceW, int sliceH,
+ int rotate, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -259,7 +260,8 @@ void PDFDoc::displayPageSlice(OutputDev *out, int page,
Page *p;
p = catalog->getPage(page);
- p->displaySlice(out, hDPI, vDPI, rotate, sliceX, sliceY, sliceW, sliceH,
+ p->displaySlice(out, hDPI, vDPI, rotate, crop,
+ sliceX, sliceY, sliceW, sliceH,
NULL, catalog,
abortCheckCbk, abortCheckCbkData,
annotDisplayDecideCbk, annotDisplayDecideCbkData);
diff --git a/pdf/xpdf/PDFDoc.h b/pdf/xpdf/PDFDoc.h
index 2d060dc..57e37a2 100644
--- a/pdf/xpdf/PDFDoc.h
+++ b/pdf/xpdf/PDFDoc.h
@@ -81,7 +81,7 @@ public:
// Display a page.
void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
- int rotate, GBool doLinks,
+ int rotate, GBool crop, GBool doLinks,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -89,7 +89,8 @@ public:
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
- double hDPI, double vDPI, int rotate, GBool doLinks,
+ double hDPI, double vDPI, int rotate,
+ GBool crop, GBool doLinks,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -98,8 +99,8 @@ public:
// Display part of a page.
void displayPageSlice(OutputDev *out, int page,
double hDPI, double vDPI,
- int rotate, int sliceX, int sliceY,
- int sliceW, int sliceH,
+ int rotate, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
diff --git a/pdf/xpdf/PSOutputDev.cc b/pdf/xpdf/PSOutputDev.cc
index 34d7fdc..6170dfd 100644
--- a/pdf/xpdf/PSOutputDev.cc
+++ b/pdf/xpdf/PSOutputDev.cc
@@ -28,7 +28,8 @@
#include "GfxState.h"
#include "GfxFont.h"
#include "UnicodeMap.h"
-#include "FontFile.h"
+#include "FoFiType1C.h"
+#include "FoFiTrueType.h"
#include "Catalog.h"
#include "Page.h"
#include "Stream.h"
@@ -368,8 +369,9 @@ static char *prolog[] = {
" pdfTextMat dtransform rmoveto } def",
"/TJmV { pdfFontSize 0.001 mul mul neg 0 exch",
" pdfTextMat dtransform rmoveto } def",
- "/Tclip { pdfTextClipPath cvx exec clip",
+ "/Tclip { pdfTextClipPath cvx exec clip newpath",
" /pdfTextClipPath [] def } def",
+ "~1",
"% Level 1 image operators",
"/pdfIm1 {",
" /pdfImBuf1 4 index string def",
@@ -390,6 +392,11 @@ static char *prolog[] = {
" /pdfImBuf1 4 index 7 add 8 idiv string def",
" { currentfile pdfImBuf1 readhexstring pop } imagemask",
"} def",
+ "/pdfImM1a {",
+ " { 2 copy get exch 1 add exch } imagemask",
+ " pop pop",
+ "} def",
+ "~2",
"% Level 2 image operators",
"/pdfImBuf 100 string def",
"/pdfIm {",
@@ -422,6 +429,7 @@ static char *prolog[] = {
" not { pop exit } if",
" (%-EOD-) eq { exit } if } loop",
"} def",
+ "~a",
"end",
NULL
};
@@ -560,6 +568,87 @@ PSOutCustomColor::~PSOutCustomColor() {
}
//------------------------------------------------------------------------
+// DeviceNRecoder
+//------------------------------------------------------------------------
+
+class DeviceNRecoder: public FilterStream {
+public:
+
+ DeviceNRecoder(Stream *strA, int widthA, int heightA,
+ GfxImageColorMap *colorMapA);
+ virtual ~DeviceNRecoder();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar()
+ { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
+ virtual int lookChar()
+ { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
+ virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
+ virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+ GBool fillBuf();
+
+ int width, height;
+ GfxImageColorMap *colorMap;
+ Function *func;
+ ImageStream *imgStr;
+ int buf[gfxColorMaxComps];
+ int pixelIdx;
+ int bufIdx;
+ int bufSize;
+};
+
+DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA,
+ GfxImageColorMap *colorMapA):
+ FilterStream(strA) {
+ width = widthA;
+ height = heightA;
+ colorMap = colorMapA;
+ imgStr = NULL;
+ pixelIdx = 0;
+ bufIdx = gfxColorMaxComps;
+ bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
+ getAlt()->getNComps();
+ func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
+ getTintTransformFunc();
+}
+
+DeviceNRecoder::~DeviceNRecoder() {
+ if (imgStr) {
+ delete imgStr;
+ }
+}
+
+void DeviceNRecoder::reset() {
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+ colorMap->getBits());
+ imgStr->reset();
+}
+
+GBool DeviceNRecoder::fillBuf() {
+ Guchar pixBuf[gfxColorMaxComps];
+ GfxColor color;
+ double y[gfxColorMaxComps];
+ int i;
+
+ if (pixelIdx >= width * height) {
+ return gFalse;
+ }
+ imgStr->getPixel(pixBuf);
+ colorMap->getColor(pixBuf, &color);
+ func->transform(color.c, y);
+ for (i = 0; i < bufSize; ++i) {
+ buf[i] = (int)(y[i] * 255 + 0.5);
+ }
+ bufIdx = 0;
+ ++pixelIdx;
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
// PSOutputDev
//------------------------------------------------------------------------
@@ -573,7 +662,7 @@ static void outputToFile(void *stream, char *data, int len) {
PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA,
- int paperWidthA, int paperHeightA,
+ int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
GBool manualCtrlA) {
FILE *f;
PSFileType fileTypeA;
@@ -624,14 +713,19 @@ PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
init(outputToFile, f, fileTypeA,
xrefA, catalog, firstPage, lastPage, modeA,
- paperWidthA, paperHeightA, manualCtrlA);
+ imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA);
}
PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA,
- int paperWidthA, int paperHeightA,
+ int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
GBool manualCtrlA) {
+ underlayCbk = NULL;
+ underlayCbkData = NULL;
+ overlayCbk = NULL;
+ overlayCbkData = NULL;
+
fontIDs = NULL;
fontFileIDs = NULL;
fontFileNames = NULL;
@@ -644,15 +738,16 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
init(outputFuncA, outputStreamA, psGeneric,
xrefA, catalog, firstPage, lastPage, modeA,
- paperWidthA, paperHeightA, manualCtrlA);
+ imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA);
}
void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA,
- int paperWidthA, int paperHeightA,
+ int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
GBool manualCtrlA) {
Page *page;
+ PDFRectangle *box;
// initialize
ok = gTrue;
@@ -662,18 +757,28 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
xref = xrefA;
level = globalParams->getPSLevel();
mode = modeA;
- paperWidth = paperWidthA;
- paperHeight = paperHeightA;
- if (paperWidth == 0) {
- paperWidth = globalParams->getPSPaperWidth();
- }
- if (paperHeight == 0) {
- paperHeight = globalParams->getPSPaperHeight();
+ paperWidth = globalParams->getPSPaperWidth();
+ paperHeight = globalParams->getPSPaperHeight();
+ imgLLX = imgLLXA;
+ imgLLY = imgLLYA;
+ imgURX = imgURXA;
+ imgURY = imgURYA;
+ if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
+ globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY);
}
if (paperWidth < 0 || paperHeight < 0) {
- page = catalog->getPage(firstPage);
- paperWidth = (int)(page->getWidth() + 0.5);
- paperHeight = (int)(page->getHeight() + 0.5);
+ // this check is needed in case the document has zero pages
+ if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
+ page = catalog->getPage(firstPage);
+ paperWidth = (int)(page->getWidth() + 0.5);
+ paperHeight = (int)(page->getHeight() + 0.5);
+ } else {
+ paperWidth = 1;
+ paperHeight = 1;
+ }
+ imgLLX = imgLLY = 0;
+ imgURX = paperWidth;
+ imgURY = paperHeight;
}
manualCtrl = manualCtrlA;
if (mode == psModeForm) {
@@ -688,6 +793,12 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
opi20Nest = 0;
#endif
+ tx0 = ty0 = 0;
+ xScale0 = yScale0 = 1;
+ rotate0 = 0;
+ clipLLX0 = clipLLY0 = 0;
+ clipURX0 = clipURY0 = -1;
+
// initialize fontIDs, fontFileIDs, and fontFileNames lists
fontIDSize = 64;
fontIDLen = 0;
@@ -709,7 +820,16 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
embFontList = new GString();
if (!manualCtrl) {
- writeHeader(firstPage, lastPage, catalog->getPage(firstPage)->getBox());
+ // this check is needed in case the document has zero pages
+ if (firstPage > 0 && firstPage <= catalog->getNumPages()) {
+ writeHeader(firstPage, lastPage,
+ catalog->getPage(firstPage)->getBox(),
+ catalog->getPage(firstPage)->getCropBox());
+ } else {
+ box = new PDFRectangle(0, 0, 1, 1);
+ writeHeader(firstPage, lastPage, box, box);
+ delete box;
+ }
if (mode != psModeForm) {
writePS("%%BeginProlog\n");
}
@@ -786,7 +906,8 @@ PSOutputDev::~PSOutputDev() {
}
}
-void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
+void PSOutputDev::writeHeader(int firstPage, int lastPage,
+ PDFRectangle *mediaBox, PDFRectangle *cropBox) {
switch (mode) {
case psModePS:
writePS("%!PS-Adobe-3.0\n");
@@ -819,14 +940,14 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
writePS("%%DocumentCustomColors: (atend)\n");
}
writePSFmt("%%%%BoundingBox: %d %d %d %d\n",
- (int)floor(box->x1), (int)floor(box->y1),
- (int)ceil(box->x2), (int)ceil(box->y2));
- if (floor(box->x1) != ceil(box->x1) ||
- floor(box->y1) != ceil(box->y1) ||
- floor(box->x2) != ceil(box->x2) ||
- floor(box->y2) != ceil(box->y2)) {
+ (int)floor(cropBox->x1), (int)floor(cropBox->y1),
+ (int)ceil(cropBox->x2), (int)ceil(cropBox->y2));
+ if (floor(cropBox->x1) != ceil(cropBox->x1) ||
+ floor(cropBox->y1) != ceil(cropBox->y1) ||
+ floor(cropBox->x2) != ceil(cropBox->x2) ||
+ floor(cropBox->y2) != ceil(cropBox->y2)) {
writePSFmt("%%%%HiResBoundingBox: %g %g %g %g\n",
- box->x1, box->y1, box->x2, box->y2);
+ cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
}
writePS("%%DocumentSuppliedResources: (atend)\n");
writePS("%%EndComments\n");
@@ -845,7 +966,8 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
writePS("%%EndComments\n");
writePS("32 dict dup begin\n");
writePSFmt("/BBox [%d %d %d %d] def\n",
- (int)box->x1, (int)box->y1, (int)box->x2, (int)box->y2);
+ (int)floor(mediaBox->x1), (int)floor(mediaBox->y1),
+ (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2));
writePS("/FormType 1 def\n");
writePS("/Matrix [1 0 0 1 0 0] def\n");
break;
@@ -1044,8 +1166,9 @@ void PSOutputDev::setupFonts(Dict *resDict) {
}
if (gfxFontDict) {
for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
- font = gfxFontDict->getFont(i);
- setupFont(font, resDict);
+ if ((font = gfxFontDict->getFont(i))) {
+ setupFont(font, resDict);
+ }
}
delete gfxFontDict;
}
@@ -1455,7 +1578,7 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
GString *psName) {
char *fontBuf;
int fontLen;
- Type1CFontFile *t1cFile;
+ FoFiType1C *ffT1C;
int i;
// check if font is already embedded
@@ -1480,11 +1603,10 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
// convert it to a Type 1 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
- t1cFile = new Type1CFontFile(fontBuf, fontLen);
- if (t1cFile->isOk()) {
- t1cFile->convertToType1(outputFunc, outputStream);
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ ffT1C->convertToType1(NULL, gTrue, outputFunc, outputStream);
+ delete ffT1C;
}
- delete t1cFile;
gfree(fontBuf);
// ending comment
@@ -1496,7 +1618,7 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
char unique[32];
char *fontBuf;
int fontLen;
- TrueTypeFontFile *ttFile;
+ FoFiTrueType *ffTT;
Gushort *codeToGID;
int i;
@@ -1527,15 +1649,16 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
// convert it to a Type 42 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
- ttFile = new TrueTypeFontFile(fontBuf, fontLen);
- codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
- ttFile->convertToType42(psName->getCString(),
- ((Gfx8BitFont *)font)->getEncoding(),
- ((Gfx8BitFont *)font)->getHasEncoding(),
- codeToGID,
- outputFunc, outputStream);
- gfree(codeToGID);
- delete ttFile;
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+ ffTT->convertToType42(psName->getCString(),
+ ((Gfx8BitFont *)font)->getHasEncoding()
+ ? ((Gfx8BitFont *)font)->getEncoding()
+ : (char **)NULL,
+ codeToGID, outputFunc, outputStream);
+ gfree(codeToGID);
+ delete ffTT;
+ }
gfree(fontBuf);
// ending comment
@@ -1547,7 +1670,7 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
GString *fileName;
char *fontBuf;
int fontLen;
- TrueTypeFontFile *ttFile;
+ FoFiTrueType *ffTT;
Gushort *codeToGID;
int i;
@@ -1580,14 +1703,15 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
// convert it to a Type 42 font
fontBuf = font->readExtFontFile(&fontLen);
- ttFile = new TrueTypeFontFile(fontBuf, fontLen);
- codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
- ttFile->convertToType42(psName->getCString(),
- ((Gfx8BitFont *)font)->getEncoding(),
- ((Gfx8BitFont *)font)->getHasEncoding(),
- codeToGID,
- outputFunc, outputStream);
- delete ttFile;
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+ ffTT->convertToType42(psName->getCString(),
+ ((Gfx8BitFont *)font)->getHasEncoding()
+ ? ((Gfx8BitFont *)font)->getEncoding()
+ : (char **)NULL,
+ codeToGID, outputFunc, outputStream);
+ delete ffTT;
+ }
gfree(fontBuf);
// ending comment
@@ -1598,7 +1722,7 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
GString *psName) {
char *fontBuf;
int fontLen;
- Type1CFontFile *t1cFile;
+ FoFiType1C *ffT1C;
int i;
// check if font is already embedded
@@ -1623,18 +1747,16 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
// convert it to a Type 0 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
- t1cFile = new Type1CFontFile(fontBuf, fontLen);
- if (t1cFile->isOk()) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
if (globalParams->getPSLevel() >= psLevel3) {
// Level 3: use a CID font
- t1cFile->convertToCIDType0(psName->getCString(),
- outputFunc, outputStream);
+ ffT1C->convertToCIDType0(psName->getCString(), outputFunc, outputStream);
} else {
// otherwise: use a non-CID composite font
- t1cFile->convertToType0(psName->getCString(), outputFunc, outputStream);
+ ffT1C->convertToType0(psName->getCString(), outputFunc, outputStream);
}
+ delete ffT1C;
}
- delete t1cFile;
gfree(fontBuf);
// ending comment
@@ -1645,7 +1767,7 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
GString *psName) {
char *fontBuf;
int fontLen;
- TrueTypeFontFile *ttFile;
+ FoFiTrueType *ffTT;
int i;
// check if font is already embedded
@@ -1670,20 +1792,22 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
// convert it to a Type 0 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
- ttFile = new TrueTypeFontFile(fontBuf, fontLen);
- if (globalParams->getPSLevel() >= psLevel3) {
- ttFile->convertToCIDType2(psName->getCString(),
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType2(psName->getCString(),
((GfxCIDFont *)font)->getCIDToGID(),
((GfxCIDFont *)font)->getCIDToGIDLen(),
outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ttFile->convertToType0(psName->getCString(),
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->getCString(),
((GfxCIDFont *)font)->getCIDToGID(),
((GfxCIDFont *)font)->getCIDToGIDLen(),
outputFunc, outputStream);
+ }
+ delete ffTT;
}
- delete ttFile;
gfree(fontBuf);
// ending comment
@@ -1717,7 +1841,7 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
embFontList->append("\n");
// font dictionary
- writePS("7 dict begin\n");
+ writePS("8 dict begin\n");
writePS("/FontType 3 def\n");
m = font->getFontMatrix();
writePSFmt("/FontMatrix [%g %g %g %g %g %g] def\n",
@@ -1811,11 +1935,14 @@ void PSOutputDev::setupImages(Dict *resDict) {
}
void PSOutputDev::setupImage(Ref id, Stream *str) {
+ GBool useASCIIHex;
int c;
int size, line, col, i;
// construct an encoder stream
- if (globalParams->getPSASCIIHex()) {
+ useASCIIHex = level == psLevel1 || level == psLevel1Sep ||
+ globalParams->getPSASCIIHex();
+ if (useASCIIHex) {
str = new ASCIIHexEncoder(str);
} else {
str = new ASCII85Encoder(str);
@@ -1828,18 +1955,18 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
do {
c = str->getChar();
} while (c == '\n' || c == '\r');
- if (c == '~' || c == EOF) {
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
break;
}
if (c == 'z') {
++col;
} else {
++col;
- for (i = 1; i <= 4; ++i) {
+ for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
do {
c = str->getChar();
} while (c == '\n' || c == '\r');
- if (c == '~' || c == EOF) {
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
break;
}
++col;
@@ -1849,7 +1976,7 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
++size;
col = 0;
}
- } while (c != '~' && c != EOF);
+ } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
++size;
writePSFmt("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
str->close();
@@ -1857,12 +1984,12 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
// write the data into the array
str->reset();
line = col = 0;
- writePS("dup 0 <~");
+ writePS((char *)(useASCIIHex ? "dup 0 <" : "dup 0 <~"));
do {
do {
c = str->getChar();
} while (c == '\n' || c == '\r');
- if (c == '~' || c == EOF) {
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
break;
}
if (c == 'z') {
@@ -1871,11 +1998,11 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
} else {
writePSChar(c);
++col;
- for (i = 1; i <= 4; ++i) {
+ for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
do {
c = str->getChar();
} while (c == '\n' || c == '\r');
- if (c == '~' || c == EOF) {
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
break;
}
writePSChar(c);
@@ -1887,13 +2014,13 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
// chunks are 1 or 4 bytes each, so we have to stop at 232
// but make it 225 just to be safe
if (col > 225) {
- writePS("~> put\n");
+ writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n"));
++line;
- writePSFmt("dup %d <~", line);
+ writePSFmt((char *)(useASCIIHex ? "dup %d <" : "dup %d <~"), line);
col = 0;
}
- } while (c != '~' && c != EOF);
- writePS("~> put\n");
+ } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
+ writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n"));
writePS("pop\n");
str->close();
@@ -1901,7 +2028,8 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
}
void PSOutputDev::startPage(int pageNum, GfxState *state) {
- int x1, y1, x2, y2, width, height, paperWidth2, paperHeight2;
+ int x1, y1, x2, y2, width, height;
+ int imgWidth, imgHeight, imgWidth2, imgHeight2;
switch (mode) {
@@ -1911,53 +2039,70 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
writePS("%%BeginPageSetup\n");
// rotate, translate, and scale page
+ imgWidth = imgURX - imgLLX;
+ imgHeight = imgURY - imgLLY;
x1 = (int)(state->getX1() + 0.5);
y1 = (int)(state->getY1() + 0.5);
x2 = (int)(state->getX2() + 0.5);
y2 = (int)(state->getY2() + 0.5);
width = x2 - x1;
height = y2 - y1;
- if (width > height && width > paperWidth) {
- landscape = gTrue;
+ tx = ty = 0;
+ // portrait or landscape
+ if (width > height && width > imgWidth) {
+ rotate = 90;
writePSFmt("%%%%PageOrientation: %s\n",
state->getCTM()[0] ? "Landscape" : "Portrait");
writePS("pdfStartPage\n");
writePS("90 rotate\n");
- tx = -x1;
- ty = -(y1 + paperWidth);
- paperWidth2 = paperHeight;
- paperHeight2 = paperWidth;
+ ty = -imgWidth;
+ imgWidth2 = imgHeight;
+ imgHeight2 = imgWidth;
} else {
- landscape = gFalse;
+ rotate = 0;
writePSFmt("%%%%PageOrientation: %s\n",
state->getCTM()[0] ? "Portrait" : "Landscape");
writePS("pdfStartPage\n");
- tx = -x1;
- ty = -y1;
- paperWidth2 = paperWidth;
- paperHeight2 = paperHeight;
- }
- if (width < paperWidth2) {
- tx += (paperWidth2 - width) / 2;
- }
- if (height < paperHeight2) {
- ty += (paperHeight2 - height) / 2;
- }
- if (tx != 0 || ty != 0) {
- writePSFmt("%g %g translate\n", tx, ty);
- }
- if (width > paperWidth2 || height > paperHeight2) {
- xScale = (double)paperWidth2 / (double)width;
- yScale = (double)paperHeight2 / (double)height;
+ imgWidth2 = imgWidth;
+ imgHeight2 = imgHeight;
+ }
+ // shrink or expand
+ if ((globalParams->getPSShrinkLarger() &&
+ (width > imgWidth2 || height > imgHeight2)) ||
+ (globalParams->getPSExpandSmaller() &&
+ (width < imgWidth2 && height < imgHeight2))) {
+ xScale = (double)imgWidth2 / (double)width;
+ yScale = (double)imgHeight2 / (double)height;
if (yScale < xScale) {
xScale = yScale;
} else {
yScale = xScale;
}
- writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
} else {
xScale = yScale = 1;
}
+ // deal with odd bounding boxes
+ tx -= xScale * x1;
+ ty -= yScale * y1;
+ // center
+ if (globalParams->getPSCenter()) {
+ tx += (imgWidth2 - xScale * width) / 2;
+ ty += (imgHeight2 - yScale * height) / 2;
+ }
+ tx += imgLLX + tx0;
+ ty += imgLLY + ty0;
+ xScale *= xScale0;
+ yScale *= yScale0;
+ if (tx != 0 || ty != 0) {
+ writePSFmt("%g %g translate\n", tx, ty);
+ }
+ if (xScale != 1 || yScale != 1) {
+ writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
+ }
+ if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
+ writePSFmt("%g %g %g %g re W\n",
+ clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0);
+ }
writePS("%%EndPageSetup\n");
++seqPage;
@@ -1967,7 +2112,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
writePS("pdfStartPage\n");
tx = ty = 0;
xScale = yScale = 1;
- landscape = gFalse;
+ rotate = 0;
break;
case psModeForm:
@@ -1976,7 +2121,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
writePS("pdfStartPage\n");
tx = ty = 0;
xScale = yScale = 1;
- landscape = gFalse;
+ rotate = 0;
break;
}
@@ -2229,7 +2374,12 @@ void PSOutputDev::updateWordSpace(GfxState *state) {
}
void PSOutputDev::updateHorizScaling(GfxState *state) {
- writePSFmt("%g Tz\n", state->getHorizScaling());
+ double h;
+
+ if ((h = state->getHorizScaling()) < 0.01) {
+ h = 0.01;
+ }
+ writePSFmt("%g Tz\n", h);
}
void PSOutputDev::updateTextPos(GfxState *state) {
@@ -2451,7 +2601,7 @@ void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
len = height * ((width + 7) / 8);
if (level == psLevel1 || level == psLevel1Sep) {
- doImageL1(NULL, invert, inlineImg, str, width, height, len);
+ doImageL1(ref, NULL, invert, inlineImg, str, width, height, len);
} else {
doImageL2(ref, NULL, invert, inlineImg, str, width, height, len);
}
@@ -2466,7 +2616,7 @@ void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
colorMap->getBits() + 7) / 8);
switch (level) {
case psLevel1:
- doImageL1(colorMap, gFalse, inlineImg, str, width, height, len);
+ doImageL1(ref, colorMap, gFalse, inlineImg, str, width, height, len);
break;
case psLevel1Sep:
//~ handle indexed, separation, ... color spaces
@@ -2482,16 +2632,56 @@ void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
t3Cacheable = gFalse;
}
-void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
+void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap,
GBool invert, GBool inlineImg,
Stream *str, int width, int height, int len) {
ImageStream *imgStr;
Guchar pixBuf[gfxColorMaxComps];
double gray;
- int x, y, i;
+ int col, x, y, c, i;
- // width, height, matrix, bits per component
- if (colorMap) {
+ if (inType3Char && !colorMap) {
+ if (inlineImg) {
+ // create an array
+ str = new FixedLengthEncoder(str, len);
+ str = new ASCIIHexEncoder(str);
+ str->reset();
+ col = 0;
+ writePS("[<");
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '>' || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ // each line is: "<...data...><eol>"
+ // so max data length = 255 - 4 = 251
+ // but make it 240 just to be safe
+ // chunks are 2 bytes each, so we need to stop on an even col number
+ if (col == 240) {
+ writePS(">\n<");
+ col = 0;
+ }
+ } while (c != '>' && c != EOF);
+ writePS(">]\n");
+ writePS("0\n");
+ str->close();
+ delete str;
+ } else {
+ // set up to use the array already created by setupImages()
+ writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
+ }
+ }
+
+ // image/imagemask command
+ if (inType3Char && !colorMap) {
+ writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1a\n",
+ width, height, invert ? "true" : "false",
+ width, -height, height);
+ } else if (colorMap) {
writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
width, height,
width, -height, height);
@@ -2501,51 +2691,54 @@ void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
width, -height, height);
}
- // image
- if (colorMap) {
+ // image data
+ if (!(inType3Char && !colorMap)) {
- // set up to process the data stream
- imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgStr->reset();
+ if (colorMap) {
- // process the data stream
- i = 0;
- for (y = 0; y < height; ++y) {
+ // set up to process the data stream
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+ colorMap->getBits());
+ imgStr->reset();
- // write the line
- for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getGray(pixBuf, &gray);
- writePSFmt("%02x", (int)(gray * 255 + 0.5));
- if (++i == 32) {
- writePSChar('\n');
- i = 0;
+ // process the data stream
+ i = 0;
+ for (y = 0; y < height; ++y) {
+
+ // write the line
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getGray(pixBuf, &gray);
+ writePSFmt("%02x", (int)(gray * 255 + 0.5));
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
}
}
- }
- if (i != 0) {
- writePSChar('\n');
- }
- delete imgStr;
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ delete imgStr;
- // imagemask
- } else {
- str->reset();
- i = 0;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; x += 8) {
- writePSFmt("%02x", str->getChar() & 0xff);
- if (++i == 32) {
- writePSChar('\n');
- i = 0;
+ // imagemask
+ } else {
+ str->reset();
+ i = 0;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; x += 8) {
+ writePSFmt("%02x", str->getChar() & 0xff);
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
}
}
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ str->close();
}
- if (i != 0) {
- writePSChar('\n');
- }
- str->close();
}
}
@@ -2611,12 +2804,12 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
Stream *str, int width, int height, int len) {
GString *s;
int n, numComps;
- GBool useRLE, useASCII, useCompressed;
+ GBool useRLE, useASCII, useASCIIHex, useCompressed;
GfxSeparationColorSpace *sepCS;
GfxColor color;
GfxCMYK cmyk;
int c;
- int line, col, i;
+ int col, i;
// color space
if (colorMap) {
@@ -2624,24 +2817,26 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
writePS(" setcolorspace\n");
}
+ useASCIIHex = globalParams->getPSASCIIHex();
+
// set up the image data
if (mode == psModeForm || inType3Char) {
if (inlineImg) {
// create an array
str = new FixedLengthEncoder(str, len);
- if (globalParams->getPSASCIIHex()) {
+ if (useASCIIHex) {
str = new ASCIIHexEncoder(str);
} else {
str = new ASCII85Encoder(str);
}
str->reset();
- line = col = 0;
- writePS("[<~");
+ col = 0;
+ writePS((char *)(useASCIIHex ? "[<" : "[<~"));
do {
do {
c = str->getChar();
} while (c == '\n' || c == '\r');
- if (c == '~' || c == EOF) {
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
break;
}
if (c == 'z') {
@@ -2650,29 +2845,27 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
} else {
writePSChar(c);
++col;
- for (i = 1; i <= 4; ++i) {
+ for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) {
do {
c = str->getChar();
} while (c == '\n' || c == '\r');
- if (c == '~' || c == EOF) {
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
break;
}
writePSChar(c);
++col;
}
}
- // each line is: "dup nnnnn <~...data...~> put<eol>"
- // so max data length = 255 - 20 = 235
- // chunks are 1 or 4 bytes each, so we have to stop at 232
- // but make it 225 just to be safe
- if (col > 225) {
- writePS("~>\n");
- ++line;
- writePSFmt("<~", line);
+ // each line is: "<~...data...~><eol>"
+ // so max data length = 255 - 6 = 249
+ // chunks are 1 or 5 bytes each, so we have to stop at 245
+ // but make it 240 just to be safe
+ if (col > 240) {
+ writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~"));
col = 0;
}
- } while (c != '~' && c != EOF);
- writePS("~>]\n");
+ } while (c != (useASCIIHex ? '>' : '~') && c != EOF);
+ writePS((char *)(useASCIIHex ? ">]\n" : "~>]\n"));
writePS("0\n");
str->close();
delete str;
@@ -2689,8 +2882,12 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
writePSFmt(" /Width %d\n", width);
writePSFmt(" /Height %d\n", height);
writePSFmt(" /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height);
- writePSFmt(" /BitsPerComponent %d\n",
- colorMap ? colorMap->getBits() : 1);
+ if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
+ writePSFmt(" /BitsPerComponent 8\n");
+ } else {
+ writePSFmt(" /BitsPerComponent %d\n",
+ colorMap ? colorMap->getBits() : 1);
+ }
// decode
if (colorMap) {
@@ -2700,6 +2897,16 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
n = (1 << colorMap->getBits()) - 1;
writePSFmt("%g %g", colorMap->getDecodeLow(0) * n,
colorMap->getDecodeHigh(0) * n);
+ } else if (colorMap->getColorSpace()->getMode() == csDeviceN) {
+ numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->
+ getAlt()->getNComps();
+ for (i = 0; i < numComps; ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePSFmt("0 1", colorMap->getDecodeLow(i),
+ colorMap->getDecodeHigh(i));
+ }
} else {
numComps = colorMap->getNumPixelComps();
for (i = 0; i < numComps; ++i) {
@@ -2732,7 +2939,8 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
writePS(" /DataSource currentfile\n");
s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
" ");
- if (inlineImg || !s) {
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
+ inlineImg || !s) {
useRLE = gTrue;
useASCII = gTrue;
useCompressed = gFalse;
@@ -2743,7 +2951,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
}
if (useASCII) {
writePSFmt(" /ASCII%sDecode filter\n",
- globalParams->getPSASCIIHex() ? "Hex" : "85");
+ useASCIIHex ? "Hex" : "85");
}
if (useRLE) {
writePS(" /RunLengthDecode filter\n");
@@ -2762,12 +2970,17 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
str = str->getBaseStream();
}
+ // recode DeviceN data
+ if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) {
+ str = new DeviceNRecoder(str, width, height, colorMap);
+ }
+
// add RunLengthEncode and ASCIIHex/85 encode filters
if (useRLE) {
str = new RunLengthEncoder(str);
}
if (useASCII) {
- if (globalParams->getPSASCIIHex()) {
+ if (useASCIIHex) {
str = new ASCIIHexEncoder(str);
} else {
str = new ASCII85Encoder(str);
@@ -2932,6 +3145,8 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
break;
case csICCBased:
+ // there is no transform function to the alternate color space, so
+ // we can use it directly
dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt());
break;
@@ -3380,10 +3595,17 @@ void PSOutputDev::opiTransform(GfxState *state, double x0, double y0,
state->transform(x0, y0, x1, y1);
*x1 += tx;
*y1 += ty;
- if (landscape) {
+ if (rotate == 90) {
t = *x1;
*x1 = -*y1;
*y1 = t;
+ } else if (rotate == 180) {
+ *x1 = -*x1;
+ *y1 = -*y1;
+ } else if (rotate == 270) {
+ t = *x1;
+ *x1 = *y1;
+ *y1 = -t;
}
*x1 *= xScale;
*y1 *= yScale;
diff --git a/pdf/xpdf/PSOutputDev.h b/pdf/xpdf/PSOutputDev.h
index 06130fb..6c379a9 100644
--- a/pdf/xpdf/PSOutputDev.h
+++ b/pdf/xpdf/PSOutputDev.h
@@ -54,14 +54,16 @@ public:
// Open a PostScript output file, and write the prolog.
PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA,
- int paperWidthA = 0, int paperHeightA = 0,
+ int imgLLXA = 0, int imgLLYA = 0,
+ int imgURXA = 0, int imgURYA = 0,
GBool manualCtrlA = gFalse);
// Open a PSOutputDev that will write to a generic stream.
PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA,
- int paperWidthA = 0, int paperHeightA = 0,
+ int imgLLXA = 0, int imgLLYA = 0,
+ int imgURXA = 0, int imgURYA = 0,
GBool manualCtrlA = gFalse);
// Destructor -- writes the trailer and closes the file.
@@ -86,7 +88,8 @@ public:
//----- header/trailer (used only if manualCtrl is true)
// Write the document-level header.
- void writeHeader(int firstPage, int lastPage, PDFRectangle *box);
+ void writeHeader(int firstPage, int lastPage,
+ PDFRectangle *mediaBox, PDFRectangle *cropBox);
// Write the Xpdf procset.
void writeXpdfProcset();
@@ -174,6 +177,14 @@ public:
virtual void psXObject(Stream *psStream, Stream *level1Stream);
//----- miscellaneous
+ void setOffset(double x, double y)
+ { tx0 = x; ty0 = y; }
+ void setScale(double x, double y)
+ { xScale0 = x; yScale0 = y; }
+ void setRotate(int rotateA)
+ { rotate0 = rotateA; }
+ void setClip(double llx, double lly, double urx, double ury)
+ { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; }
void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data),
void *data)
{ underlayCbk = cbk; underlayCbkData = data; }
@@ -186,7 +197,7 @@ private:
void init(PSOutputFunc outputFuncA, void *outputStreamA,
PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA,
- int paperWidthA, int paperHeightA,
+ int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
GBool manualCtrlA);
void setupResources(Dict *resDict);
void setupFonts(Dict *resDict);
@@ -204,7 +215,7 @@ private:
void addProcessColor(double c, double m, double y, double k);
void addCustomColor(GfxSeparationColorSpace *sepCS);
void doPath(GfxPath *path);
- void doImageL1(GfxImageColorMap *colorMap,
+ void doImageL1(Object *ref, GfxImageColorMap *colorMap,
GBool invert, GBool inlineImg,
Stream *str, int width, int height, int len);
void doImageL1Sep(GfxImageColorMap *colorMap,
@@ -232,6 +243,8 @@ private:
PSOutMode mode; // PostScript mode (PS, EPS, form)
int paperWidth; // width of paper, in pts
int paperHeight; // height of paper, in pts
+ int imgLLX, imgLLY, // imageable area, in pts
+ imgURX, imgURY;
PSOutputFunc outputFunc;
void *outputStream;
@@ -263,9 +276,14 @@ private:
// processed
int numSaves; // current number of gsaves
- double tx, ty; // global translation
- double xScale, yScale; // global scaling
- GBool landscape; // true for landscape, false for portrait
+ double tx0, ty0; // global translation
+ double xScale0, yScale0; // global scaling
+ int rotate0; // rotation angle (0, 90, 180, 270)
+ double clipLLX0, clipLLY0,
+ clipURX0, clipURY0;
+ double tx, ty; // global translation for current page
+ double xScale, yScale; // global scaling for current page
+ int rotate; // rotation angle for current page
GString *embFontList; // resource comments for embedded fonts
diff --git a/pdf/xpdf/Page.cc b/pdf/xpdf/Page.cc
index e12e65c..817e1d5 100644
--- a/pdf/xpdf/Page.cc
+++ b/pdf/xpdf/Page.cc
@@ -226,18 +226,20 @@ Page::~Page() {
contents.free();
}
-void Page::display(OutputDev *out, double hDPI, double vDPI, int rotate,
+void Page::display(OutputDev *out, double hDPI, double vDPI,
+ int rotate, GBool crop,
Links *links, Catalog *catalog,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData,
GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
void *annotDisplayDecideCbkData) {
- displaySlice(out, hDPI, vDPI, rotate, -1, -1, -1, -1, links, catalog,
+ displaySlice(out, hDPI, vDPI, rotate, crop, -1, -1, -1, -1, links, catalog,
abortCheckCbk, abortCheckCbkData,
annotDisplayDecideCbk, annotDisplayDecideCbkData);
}
-void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
+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),
@@ -322,7 +324,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
}
gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
- hDPI, vDPI, &box, isCropped(), cropBox, rotate,
+ hDPI, vDPI, &box, crop && isCropped(), cropBox, rotate,
abortCheckCbk, abortCheckCbkData);
contents.fetch(xref, &obj);
if (!obj.isNull()) {
diff --git a/pdf/xpdf/Page.h b/pdf/xpdf/Page.h
index 8fa1ef6..ab6442c 100644
--- a/pdf/xpdf/Page.h
+++ b/pdf/xpdf/Page.h
@@ -146,7 +146,8 @@ public:
Object *getThumb(Object *obj) { return thumb.fetch(xref, obj); }
// Display a page.
- void display(OutputDev *out, double hDPI, double vDPI, int rotate,
+ void display(OutputDev *out, double hDPI, double vDPI,
+ int rotate, GBool crop,
Links *links, Catalog *catalog,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL,
@@ -154,7 +155,8 @@ public:
void *annotDisplayDecideCbkData = NULL);
// Display part of a page.
- void displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
+ 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,
diff --git a/pdf/xpdf/Parser.cc b/pdf/xpdf/Parser.cc
index 2f881d4..0aa66d3 100644
--- a/pdf/xpdf/Parser.cc
+++ b/pdf/xpdf/Parser.cc
@@ -176,7 +176,7 @@ 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;
}
diff --git a/pdf/xpdf/SFont.cc b/pdf/xpdf/SFont.cc
deleted file mode 100644
index 1f421dd..0000000
--- a/pdf/xpdf/SFont.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-//========================================================================
-//
-// SFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "SFont.h"
-
-//------------------------------------------------------------------------
-
-SFontEngine::SFontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA) {
- display = displayA;
- visual = visualA;
- depth = depthA;
- colormap = colormapA;
-}
-
-SFontEngine::~SFontEngine() {
-}
-
-void SFontEngine::useTrueColor(int rMaxA, int rShiftA, int gMaxA, int gShiftA,
- int bMaxA, int bShiftA) {
- trueColor = gTrue;
- rMax = rMaxA;
- rShift = rShiftA;
- gMax = gMaxA;
- gShift = gShiftA;
- bMax = bMaxA;
- bShift = bShiftA;
-}
-
-void SFontEngine::useColorCube(Gulong *colorsA, int nRGBA) {
- trueColor = gFalse;
- colors = colorsA;
- nRGB = nRGBA;
- rMax = gMax = bMax = nRGB - 1;
-}
-
-Gulong SFontEngine::findColor(int r, int g, int b) {
- int r1, g1, b1;
- Gulong pix;
-
- r1 = ((r & 0xffff) * rMax) / 0xffff;
- g1 = ((g & 0xffff) * gMax) / 0xffff;
- b1 = ((b & 0xffff) * bMax) / 0xffff;
- if (trueColor) {
- pix = (r1 << rShift) + (g1 << gShift) + (b1 << bShift);
- } else {
- pix = colors[(r1 * nRGB + g1) * nRGB + b1];
- }
- return pix;
-}
-
-//------------------------------------------------------------------------
-
-SFontFile::SFontFile() {
-}
-
-SFontFile::~SFontFile() {
-}
-
-//------------------------------------------------------------------------
-
-SFont::SFont() {
-}
-
-SFont::~SFont() {
-}
-
-GBool SFont::getCharPath(CharCode c, Unicode u, GfxState *state) {
- return gFalse;
-}
diff --git a/pdf/xpdf/SFont.h b/pdf/xpdf/SFont.h
deleted file mode 100644
index aadf991..0000000
--- a/pdf/xpdf/SFont.h
+++ /dev/null
@@ -1,142 +0,0 @@
-//========================================================================
-//
-// SFont.h
-//
-// Base class for font rasterizers.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef SFONT_H
-#define SFONT_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include "gtypes.h"
-#include "CharTypes.h"
-
-class GfxState;
-
-//------------------------------------------------------------------------
-
-class SFontEngine {
-public:
-
- SFontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA);
- virtual ~SFontEngine();
-
- // Use a TrueColor visual. Pixel values are computed as:
- //
- // (r << rShift) + (g << gShift) + (b << bShift)
- //
- // where r, g, and b are scaled to the ranges [0,rMax], [0,gMax],
- // and [0,bMax], respectively.
- virtual void useTrueColor(int rMaxA, int rShiftA, int gMaxA, int gShiftA,
- int bMaxA, int bShiftA);
-
- // Use an RGB color cube. <colors> is an array containing
- // <nRGB>*<nRGB>*<nRGB> pixel values in red,green,blue order, e.g.,
- // for <nRGB>=2, there will be 8 entries:
- //
- // |--- colors[i] ---|
- // i red green blue
- // - ----- ----- -----
- // 0 0000 0000 0000
- // 1 0000 0000 ffff
- // 2 0000 ffff 0000
- // 3 0000 ffff ffff
- // 4 ffff 0000 0000
- // 5 ffff 0000 ffff
- // 6 ffff ffff 0000
- // 7 ffff ffff ffff
- //
- // The <colors> array is not copied and must remain valid for the
- // lifetime of this SFont object.
- virtual void useColorCube(Gulong *colorsA, int nRGBA);
-
-protected:
-
- // Find the closest match to (<r>,<g>,<b>).
- Gulong findColor(int r, int g, int b);
-
- //----- X parameters
- Display *display;
- Visual *visual;
- int depth;
- Colormap colormap;
-
- GBool trueColor; // true for TrueColor, false for RGB cube
-
- //----- TrueColor parameters
- int rMax, gMax, bMax;
- int rShift, gShift, bShift;
-
- //----- RGB color cube parameters
- Gulong *colors;
- int nRGB;
-};
-
-//------------------------------------------------------------------------
-
-class SFontFile {
-public:
-
- // A typical subclass will provide a constructor along the lines of:
- //
- // SomeFontFile(SomeFontEngine *engine, char *fontFileName);
- SFontFile();
-
- virtual ~SFontFile();
-
-private:
-};
-
-//------------------------------------------------------------------------
-
-class SFont {
-public:
-
- // A typical subclass will provide a constructor along the lines of:
- //
- // SomeFont(SomeFontFile *fontFile, double *m);
- //
- // where <m> is a transform matrix consisting of four elements,
- // using the PostScript ordering conventions (without any
- // translation):
- //
- // [x' y'] = [x y] * [m0 m1]
- // [m2 m3]
- //
- // This is the level at which fonts are cached, and so the font
- // cannot be transformed after it is created.
- SFont();
-
- virtual ~SFont();
-
- // Draw a character <c>/<u> at <x>,<y> in color (<r>,<g>,<b>). The
- // RGB values should each be in the range [0,65535]. Draws into
- // <d>, clipped to the rectangle (0,0)-(<w>-1,<h>-1). Returns true
- // if the character was drawn successfully.
- virtual GBool drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u) = 0;
-
- // Add the outline of the specified character to the current path by
- // calling state->moveTo, lineTo, and curveTo. Returns true if
- // successful. If this SFont subclass doesn't implement character
- // paths, returns false immediately without modifying the current
- // path.
- virtual GBool getCharPath(CharCode c, Unicode u, GfxState *state);
-
-protected:
-};
-
-#endif
diff --git a/pdf/xpdf/Stream.cc b/pdf/xpdf/Stream.cc
index e770b61..49bbb46 100644
--- a/pdf/xpdf/Stream.cc
+++ b/pdf/xpdf/Stream.cc
@@ -30,6 +30,7 @@
#endif
#include "Stream.h"
#include "JBIG2Stream.h"
+#include "JPXStream.h"
#include "Stream-CCITT.h"
#ifdef __DJGPP__
@@ -256,6 +257,8 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
}
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);
@@ -450,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;
}
@@ -784,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");
}
@@ -1263,7 +1284,7 @@ CCITTFaxStream::~CCITTFaxStream() {
}
void CCITTFaxStream::reset() {
- int n;
+ short code1;
str->reset();
eof = gFalse;
@@ -1275,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);
@@ -1295,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;
@@ -1308,9 +1323,7 @@ int CCITTFaxStream::lookChar() {
}
// read the next row
-#if 0
err = gFalse;
-#endif
if (codingLine[a0] >= columns) {
// 2-D encoding
@@ -1412,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);
@@ -1447,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
@@ -1505,14 +1516,11 @@ 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;
@@ -1522,13 +1530,11 @@ int CCITTFaxStream::lookChar() {
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];
@@ -3747,6 +3753,10 @@ int FixedLengthEncoder::lookChar() {
return str->getChar();
}
+GBool FixedLengthEncoder::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
//------------------------------------------------------------------------
// ASCIIHexEncoder
//------------------------------------------------------------------------
diff --git a/pdf/xpdf/Stream.h b/pdf/xpdf/Stream.h
index 0121df1..0b70afa 100644
--- a/pdf/xpdf/Stream.h
+++ b/pdf/xpdf/Stream.h
@@ -36,6 +36,7 @@ enum StreamKind {
strDCT,
strFlate,
strJBIG2,
+ strJPX,
strWeird // internal-use stream types
};
@@ -92,7 +93,7 @@ public:
// 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.
@@ -131,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(); }
@@ -273,7 +275,6 @@ 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);
@@ -314,7 +315,6 @@ public:
{ return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
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 start; }
virtual void moveStart(int delta);
#ifndef NO_DECRYPTION
@@ -345,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;
};
//------------------------------------------------------------------------
@@ -740,7 +741,7 @@ public:
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isBinary(GBool last = gTrue);
virtual GBool isEncoder() { return gTrue; }
private:
@@ -825,7 +826,7 @@ public:
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
private:
diff --git a/pdf/xpdf/T1Font.cc b/pdf/xpdf/T1Font.cc
deleted file mode 100644
index a03351d..0000000
--- a/pdf/xpdf/T1Font.cc
+++ /dev/null
@@ -1,566 +0,0 @@
-//========================================================================
-//
-// T1Font.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#if HAVE_T1LIB_H
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <math.h>
-#include <string.h>
-#include <X11/Xlib.h>
-#include "gmem.h"
-#include "GfxState.h"
-#include "T1Font.h"
-
-//------------------------------------------------------------------------
-
-int T1FontEngine::t1libInitCount = 0;
-
-//------------------------------------------------------------------------
-
-T1FontEngine::T1FontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA, GBool aaA, GBool aaHighA):
- SFontEngine(displayA, visualA, depthA, colormapA)
-{
- static unsigned long grayVals[17] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
- };
-
- ok = gFalse;
- aa = aaA;
- aaHigh = aaHighA;
- //~ for multithreading: need a mutex here
- if (t1libInitCount == 0) {
- T1_SetBitmapPad(8);
- if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
- T1_NO_AFM)) {
- return;
- }
- if (aa) {
- T1_AASetBitsPerPixel(8);
- if (aaHigh) {
- T1_AASetLevel(T1_AA_HIGH);
- T1_AAHSetGrayValues(grayVals);
- } else {
- T1_AASetLevel(T1_AA_LOW);
- T1_AASetGrayValues(0, 1, 2, 3, 4);
- }
- } else {
- T1_AANSetGrayValues(0, 1);
- }
- }
- ++t1libInitCount;
- ok = gTrue;
-}
-
-T1FontEngine::~T1FontEngine() {
- //~ for multithreading: need a mutex here
- if (--t1libInitCount == 0) {
- T1_CloseLib();
- }
-}
-
-//------------------------------------------------------------------------
-
-T1FontFile::T1FontFile(T1FontEngine *engineA, char *fontFileName,
- char **fontEnc, double *bboxA) {
- int encStrSize;
- char *encPtr;
- int i;
-
- ok = gFalse;
- engine = engineA;
- enc = NULL;
- encStr = NULL;
- for (i = 0; i < 4; ++i) {
- bbox[i] = bboxA[i];
- }
-
- // load the font file
- if ((id = T1_AddFont(fontFileName)) < 0) {
- return;
- }
- T1_LoadFont(id);
-
- // reencode it
- encStrSize = 0;
- for (i = 0; i < 256; ++i) {
- if (fontEnc[i]) {
- encStrSize += strlen(fontEnc[i]) + 1;
- }
- }
- enc = (char **)gmalloc(257 * sizeof(char *));
- encStr = (char *)gmalloc(encStrSize * sizeof(char));
- encPtr = encStr;
- for (i = 0; i < 256; ++i) {
- if (fontEnc[i]) {
- strcpy(encPtr, fontEnc[i]);
- enc[i] = encPtr;
- encPtr += strlen(encPtr) + 1;
- } else {
- enc[i] = ".notdef";
- }
- }
- enc[256] = "custom";
- T1_ReencodeFont(id, enc);
-
- ok = gTrue;
-}
-
-T1FontFile::~T1FontFile() {
- gfree(enc);
- gfree(encStr);
- if (id >= 0) {
- T1_DeleteFont(id);
- }
-}
-
-//------------------------------------------------------------------------
-
-T1Font::T1Font(T1FontFile *fontFileA, double *m) {
- T1FontEngine *engine;
- T1_TMATRIX matrix;
- BBox bbox;
- double bbx0, bby0, bbx1, bby1;
- int x, y, xMin, xMax, yMin, yMax;
- int i;
-
- ok = gFalse;
- fontFile = fontFileA;
- engine = fontFile->engine;
-
- id = T1_CopyFont(fontFile->id);
-
- // compute font size
- size = (float)sqrt(m[2]*m[2] + m[3]*m[3]);
-
- // transform the four corners of the font bounding box -- the min
- // and max values form the bounding box of the transformed font
- bbx0 = fontFile->bbox[0];
- bby0 = fontFile->bbox[1];
- bbx1 = fontFile->bbox[2];
- bby1 = fontFile->bbox[3];
- // some fonts in PDF files have bboxes which are just plain wrong,
- // so we check the font file's bbox too
- bbox = T1_GetFontBBox(id);
- if (0.001 * bbox.llx < bbx0) {
- bbx0 = 0.001 * bbox.llx;
- }
- if (0.001 * bbox.lly < bby0) {
- bby0 = 0.001 * bbox.lly;
- }
- if (0.001 * bbox.urx > bbx1) {
- bbx1 = 0.001 * bbox.urx;
- }
- if (0.001 * bbox.ury > bby1) {
- bby1 = 0.001 * bbox.ury;
- }
- // some fonts are completely broken, so we fake it (with values
- // large enough that most glyphs should fit)
- if (bbx0 == 0 && bby0 == 0 && bbx1 == 0 && bby1 == 0) {
- bbx0 = bby0 = -0.5;
- bbx1 = bby1 = 1.5;
- }
- x = (int)(m[0] * bbx0 + m[2] * bby0);
- xMin = xMax = x;
- y = (int)(m[1] * bbx0 + m[3] * bby0);
- yMin = yMax = y;
- x = (int)(m[0] * bbx0 + m[2] * bby1);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)(m[1] * bbx0 + m[3] * bby1);
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- x = (int)(m[0] * bbx1 + m[2] * bby0);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)(m[1] * bbx1 + m[3] * bby0);
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- x = (int)(m[0] * bbx1 + m[2] * bby1);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)(m[1] * bbx1 + m[3] * bby1);
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- // This is a kludge: some buggy PDF generators embed fonts with
- // zero bounding boxes.
- if (xMax == xMin) {
- xMin = 0;
- xMax = (int)size;
- }
- if (yMax == yMin) {
- yMin = 0;
- yMax = (int)(1.2 * size);
- }
- // Another kludge: an unusually large xMin or yMin coordinate is
- // probably wrong.
- if (xMin > 0) {
- xMin = 0;
- }
- if (yMin > 0) {
- yMin = 0;
- }
- // Another kludge: t1lib doesn't correctly handle fonts with
- // real (non-integer) bounding box coordinates.
- if (xMax - xMin > 5000) {
- xMin = 0;
- xMax = (int)size;
- }
- if (yMax - yMin > 5000) {
- yMin = 0;
- yMax = (int)(1.2 * size);
- }
- // this should be (max - min + 1), but we add some padding to
- // deal with rounding errors
- glyphW = xMax - xMin + 3;
- glyphH = yMax - yMin + 3;
- if (engine->aa) {
- glyphSize = glyphW * glyphH;
- } else {
- glyphSize = ((glyphW + 7) >> 3) * glyphH;
- }
-
- // set up the glyph pixmap cache
- cacheAssoc = 8;
- if (glyphSize <= 256) {
- cacheSets = 8;
- } else if (glyphSize <= 512) {
- cacheSets = 4;
- } else if (glyphSize <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
- cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
- cacheTags = (T1FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
- sizeof(T1FontCacheTag));
- for (i = 0; i < cacheSets * cacheAssoc; ++i) {
- cacheTags[i].mru = i & (cacheAssoc - 1);
- }
-
- // create the XImage
- if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
- ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
- return;
- }
- image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
-
- // transform the font
- matrix.cxx = m[0] / size;
- matrix.cxy = m[1] / size;
- matrix.cyx = m[2] / size;
- matrix.cyy = m[3] / size;
- T1_TransformFont(id, &matrix);
-
- ok = gTrue;
-}
-
-T1Font::~T1Font() {
- gfree(cacheTags);
- gfree(cache);
- if (image) {
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
- }
- T1_DeleteFont(id);
-}
-
-GBool T1Font::drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u) {
- T1FontEngine *engine;
- XColor xcolor;
- int bgR, bgG, bgB;
- Gulong colors[17];
- Guchar *bitmap, *p;
- GBool tempBitmap;
- XImage *img;
- int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
- int xx, yy, xx1;
- Guchar pix, mPix;
- int i;
-
- engine = fontFile->engine;
-
- // generate the glyph pixmap
- if (!(bitmap = getGlyphPixmap(c, &xOffset, &yOffset, &gw, &gh,
- &tempBitmap))) {
- return gFalse;
- }
-
- // compute: (x0,y0) = position in destination drawable
- // (x1,y1) = position in glyph image
- // (w0,h0) = size of image transfer
- x0 = x - xOffset;
- y0 = y - yOffset;
- x1 = 0;
- y1 = 0;
- w0 = gw;
- h0 = gh;
- if (x0 < 0) {
- x1 = -x0;
- w0 += x0;
- x0 = 0;
- }
- if (x0 + w0 > w) {
- w0 = w - x0;
- }
- if (w0 < 0) {
- goto done;
- }
- if (y0 < 0) {
- y1 = -y0;
- h0 += y0;
- y0 = 0;
- }
- if (y0 + h0 > h) {
- h0 = h - y0;
- }
- if (h0 < 0) {
- goto done;
- }
-
- // getGlyphPixmap may have returned a larger-than-cache-entry
- // bitmap, in which case we need to allocate a temporary XImage here
- if (tempBitmap) {
- if (!(img = XCreateImage(engine->display, engine->visual, engine->depth,
- ZPixmap, 0, NULL, gw, gh, 8, 0))) {
- goto done;
- }
- img->data = (char *)gmalloc(gh * img->bytes_per_line);
- } else {
- img = image;
- }
-
- // read the X image
- XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
- ZPixmap, img, x1, y1);
-
- if (engine->aa) {
-
- // compute the colors
- xcolor.pixel = XGetPixel(img, x1 + w0/2, y1 + h0/2);
- XQueryColor(engine->display, engine->colormap, &xcolor);
- bgR = xcolor.red;
- bgG = xcolor.green;
- bgB = xcolor.blue;
- if (engine->aaHigh) {
- mPix = 16;
- for (i = 1; i <= 16; ++i) {
- colors[i] = engine->findColor((i * r + (16 - i) * bgR) / 16,
- (i * g + (16 - i) * bgG) / 16,
- (i * b + (16 - i) * bgB) / 16);
- }
- } else {
- mPix = 4;
- colors[1] = engine->findColor((r + 3*bgR) / 4,
- (g + 3*bgG) / 4,
- (b + 3*bgB) / 4);
- colors[2] = engine->findColor((r + bgR) / 2,
- (g + bgG) / 2,
- (b + bgB) / 2);
- colors[3] = engine->findColor((3*r + bgR) / 4,
- (3*g + bgG) / 4,
- (3*b + bgB) / 4);
- colors[4] = engine->findColor(r, g, b);
- }
-
- // stuff the glyph pixmap into the X image
- p = bitmap;
- for (yy = 0; yy < gh; ++yy) {
- for (xx = 0; xx < gw; ++xx) {
- pix = *p++;
- if (pix > 0) {
- if (pix > mPix) {
- pix = mPix;
- }
- XPutPixel(img, xx, yy, colors[pix]);
- }
- }
- }
-
- } else {
-
- // one color
- colors[1] = engine->findColor(r, g, b);
-
- // stuff the glyph bitmap into the X image
- p = bitmap;
- for (yy = 0; yy < gh; ++yy) {
- for (xx = 0; xx < gw; xx += 8) {
- pix = *p++;
- for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
- if (pix & 0x01) {
- XPutPixel(img, xx1, yy, colors[1]);
- }
- pix >>= 1;
- }
- }
- }
-
- }
-
- // draw the X image
- XPutImage(engine->display, d, gc, img, x1, y1, x0, y0, w0, h0);
-
- if (tempBitmap) {
- gfree(img->data);
- img->data = NULL;
- XDestroyImage(img);
- }
- done:
- if (tempBitmap) {
- gfree(bitmap);
- }
- return gTrue;
-}
-
-Guchar *T1Font::getGlyphPixmap(CharCode c, int *x, int *y, int *w, int *h,
- GBool *tempBitmap) {
- T1FontEngine *engine;
- GLYPH *glyph;
- int gSize;
- int i, j, k;
- Guchar *ret;
-
- engine = fontFile->engine;
-
- // check the cache
- i = (c & (cacheSets - 1)) * cacheAssoc;
- for (j = 0; j < cacheAssoc; ++j) {
- if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
- *x = cacheTags[i+j].x;
- *y = cacheTags[i+j].y;
- *w = cacheTags[i+j].w;
- *h = cacheTags[i+j].h;
- for (k = 0; k < cacheAssoc; ++k) {
- if (k != j &&
- (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
- ++cacheTags[i+k].mru;
- }
- }
- cacheTags[i+j].mru = 0x8000;
- *tempBitmap = gFalse;
- return cache + (i+j) * glyphSize;
- }
- }
-
- // generate the glyph pixmap
- if (engine->aa) {
- glyph = T1_AASetChar(id, c, size, NULL);
- } else {
- glyph = T1_SetChar(id, c, size, NULL);
- }
- if (!glyph) {
- return NULL;
- }
-
- // copy the glyph into the cache or a temporary bitmap
- *x = -glyph->metrics.leftSideBearing;
- *y = glyph->metrics.ascent;
- *w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing;
- *h = glyph->metrics.ascent - glyph->metrics.descent;
- if (engine->aa) {
- gSize = *w * *h;
- } else {
- gSize = ((*w + 7) >> 3) * *h;
- }
- if (*w > glyphW || *h > glyphH) {
- // the glyph doesn't fit in the bounding box -- return a
- // temporary, uncached bitmap (this shouldn't happen but some
- // fonts have incorrect bboxes)
- ret = (Guchar *)gmalloc(gSize);
- *tempBitmap = gTrue;
- } else {
- // store glyph pixmap in cache
- ret = NULL; // make gcc happy
- for (j = 0; j < cacheAssoc; ++j) {
- if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
- cacheTags[i+j].mru = 0x8000;
- cacheTags[i+j].code = c;
- cacheTags[i+j].x = *x;
- cacheTags[i+j].y = *y;
- cacheTags[i+j].w = *w;
- cacheTags[i+j].h = *h;
- ret = cache + (i+j) * glyphSize;
- } else {
- ++cacheTags[i+j].mru;
- }
- }
- *tempBitmap = gFalse;
- }
- if (glyph->bits) {
- memcpy(ret, glyph->bits, gSize);
- } else {
- memset(ret, 0, gSize);
- }
- return ret;
-}
-
-GBool T1Font::getCharPath(CharCode c, Unicode u, GfxState *state) {
- T1_OUTLINE *outline;
- T1_PATHSEGMENT *seg;
- T1_BEZIERSEGMENT *bez;
- double x, y, x1, y1;
-
- outline = T1_GetCharOutline(id, c, size, NULL);
- x = 0;
- y = 0;
- for (seg = outline; seg; seg = seg->link) {
- switch (seg->type) {
- case T1_PATHTYPE_MOVE:
- x += seg->dest.x / 65536.0;
- y += seg->dest.y / 65536.0;
- state->moveTo(x, y);
- break;
- case T1_PATHTYPE_LINE:
- x += seg->dest.x / 65536.0;
- y += seg->dest.y / 65536.0;
- state->lineTo(x, y);
- break;
- case T1_PATHTYPE_BEZIER:
- bez = (T1_BEZIERSEGMENT *)seg;
- x1 = x + bez->dest.x / 65536.0;
- y1 = y + bez->dest.y / 65536.0;
- state->curveTo(x + bez->B.x / 65536.0, y + bez->B.y / 65536.0,
- x + bez->C.x / 65536.0, y + bez->C.y / 65536.0,
- x1, y1);
- x = x1;
- y = y1;
- break;
- }
- }
- T1_FreeOutline(outline);
- return gTrue;
-}
-
-#endif // HAVE_T1LIB_H
diff --git a/pdf/xpdf/T1Font.h b/pdf/xpdf/T1Font.h
deleted file mode 100644
index 416f533..0000000
--- a/pdf/xpdf/T1Font.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//========================================================================
-//
-// T1Font.h
-//
-// An X wrapper for the t1lib Type 1 font rasterizer.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef T1FONT_H
-#define T1FONT_H
-
-#include <aconf.h>
-
-#if HAVE_T1LIB_H
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <X11/Xlib.h>
-#include <t1lib.h>
-#include "SFont.h"
-
-class GfxState;
-
-//------------------------------------------------------------------------
-
-class T1FontEngine: public SFontEngine {
-public:
-
- T1FontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA, GBool aaA, GBool aaHighA);
- GBool isOk() { return ok; }
- virtual ~T1FontEngine();
-
-private:
-
- GBool aa; // use anti-aliasing?
- GBool aaHigh; // use high-res anti-aliasing?
- GBool ok;
-
- static int t1libInitCount;
-
- friend class T1FontFile;
- friend class T1Font;
-};
-
-//------------------------------------------------------------------------
-
-class T1FontFile: public SFontFile {
-public:
-
- T1FontFile(T1FontEngine *engineA, char *fontFileName,
- char **fontEnc, double *bboxA);
- GBool isOk() { return ok; }
- virtual ~T1FontFile();
-
-private:
-
- T1FontEngine *engine;
- int id; // t1lib font ID
- char **enc;
- char *encStr;
- double bbox[4];
- GBool ok;
-
- friend class T1Font;
-};
-
-//------------------------------------------------------------------------
-
-struct T1FontCacheTag {
- Gushort code;
- Gushort mru; // valid bit (0x8000) and MRU index
- int x, y, w, h; // offset and size of glyph
-};
-
-class T1Font: public SFont {
-public:
-
- T1Font(T1FontFile *fontFileA, double *m);
- GBool isOk() { return ok; }
- virtual ~T1Font();
- virtual GBool drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u);
- virtual GBool getCharPath(CharCode c, Unicode u, GfxState *state);
-
-private:
-
- Guchar *getGlyphPixmap(CharCode c, int *x, int *y, int *w, int *h,
- GBool *tempBitmap);
-
- T1FontFile *fontFile;
- int id;
- float size;
- XImage *image;
- int glyphW, glyphH; // size of glyph pixmaps
- int glyphSize; // size of glyph pixmaps, in bytes
- Guchar *cache; // glyph pixmap cache
- T1FontCacheTag *cacheTags; // cache tags, i.e., char codes
- int cacheSets; // number of sets in cache
- int cacheAssoc; // cache associativity (glyphs per set)
- GBool ok;
-};
-
-#endif // HAVE_T1LIB_H
-
-#endif
diff --git a/pdf/xpdf/TTFont.cc b/pdf/xpdf/TTFont.cc
deleted file mode 100644
index c499cf1..0000000
--- a/pdf/xpdf/TTFont.cc
+++ /dev/null
@@ -1,485 +0,0 @@
-//========================================================================
-//
-// TTFont.cc
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <string.h>
-#include "gmem.h"
-#include "GlobalParams.h"
-#include "TTFont.h"
-
-//------------------------------------------------------------------------
-
-TTFontEngine::TTFontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA, GBool aaA):
- SFontEngine(displayA, visualA, depthA, colormapA) {
- static TT_Byte ttPalette[5] = {0, 1, 2, 3, 4};
-
- ok = gFalse;
- if (TT_Init_FreeType(&engine)) {
- return;
- }
- aa = aaA;
- if (aa) {
- if (TT_Set_Raster_Gray_Palette(engine, ttPalette)) {
- return;
- }
- }
- ok = gTrue;
-}
-
-TTFontEngine::~TTFontEngine() {
- TT_Done_FreeType(engine);
-}
-
-//------------------------------------------------------------------------
-
-TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName,
- char **fontEnc, GBool pdfFontHasEncoding) {
- TT_Face_Properties props;
- TT_UShort unicodeCmap, macRomanCmap, msSymbolCmap;
- TT_UShort platform, encoding, i;
- int j;
-
- ok = gFalse;
- engine = engineA;
- codeMap = NULL;
- if (TT_Open_Face(engine->engine, fontFileName, &face)) {
- return;
- }
- if (TT_Get_Face_Properties(face, &props)) {
- return;
- }
-
- // 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 = 0xffff;
- for (i = 0; i < props.num_CharMaps; ++i) {
- if (!TT_Get_CharMap_ID(face, i, &platform, &encoding)) {
- if ((platform == 3 && encoding == 1) || platform == 0) {
- unicodeCmap = i;
- } else if (platform == 1 && encoding == 0) {
- macRomanCmap = i;
- } else if (platform == 3 && encoding == 0) {
- msSymbolCmap = i;
- }
- }
- }
- i = 0;
- mode = ttFontModeCharCode;
- if (pdfFontHasEncoding) {
- if (unicodeCmap != 0xffff) {
- i = unicodeCmap;
- mode = ttFontModeUnicode;
- } else if (macRomanCmap != 0xffff) {
- i = macRomanCmap;
- mode = ttFontModeCodeMap;
- codeMap = (Guchar *)gmalloc(256 * sizeof(Guchar));
- for (j = 0; j < 256; ++j) {
- if (fontEnc[j]) {
- codeMap[j] = (Guchar)globalParams->getMacRomanCharCode(fontEnc[j]);
- } else {
- codeMap[j] = 0;
- }
- }
- }
- } else {
- if (macRomanCmap != 0xffff) {
- i = macRomanCmap;
- mode = ttFontModeCharCode;
- } else if (msSymbolCmap != 0xffff) {
- i = msSymbolCmap;
- mode = ttFontModeCharCode;
- }
- }
- TT_Get_CharMap(face, i, &charMap);
-
- ok = gTrue;
-}
-
-TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName,
- Gushort *cidToGIDA, int cidToGIDLenA) {
- ok = gFalse;
- engine = engineA;
- codeMap = NULL;
- cidToGID = cidToGIDA;
- cidToGIDLen = cidToGIDLenA;
- if (TT_Open_Face(engine->engine, fontFileName, &face)) {
- return;
- }
- mode = ttFontModeCIDToGIDMap;
- ok = gTrue;
-}
-
-TTFontFile::~TTFontFile() {
- TT_Close_Face(face);
- if (codeMap) {
- gfree(codeMap);
- }
-}
-
-//------------------------------------------------------------------------
-
-TTFont::TTFont(TTFontFile *fontFileA, double *m) {
- TTFontEngine *engine;
- TT_Face_Properties props;
- TT_Instance_Metrics metrics;
- int x, xMin, xMax;
- int y, yMin, yMax;
- int i;
-
- ok = gFalse;
- fontFile = fontFileA;
- engine = fontFile->engine;
- if (TT_New_Instance(fontFile->face, &instance) ||
- TT_Set_Instance_Resolutions(instance, 72, 72) ||
- TT_Set_Instance_CharSize(instance, 1000 * 64) ||
- TT_New_Glyph(fontFile->face, &glyph) ||
- TT_Get_Face_Properties(fontFile->face, &props) ||
- TT_Get_Instance_Metrics(instance, &metrics)) {
- return;
- }
-
- // transform the four corners of the font bounding box -- the min
- // and max values form the bounding box of the transformed font
- x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMin) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- xMin = xMax = x;
- y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMin) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- yMin = yMax = y;
- x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMax) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMax) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMin) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMin) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMax) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- if (x < xMin) {
- xMin = x;
- } else if (x > xMax) {
- xMax = x;
- }
- y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMax) *
- 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
- if (y < yMin) {
- yMin = y;
- } else if (y > yMax) {
- yMax = y;
- }
- xOffset = -xMin;
- yOffset = -yMin;
- ras.width = xMax - xMin + 1;
- ras.rows = yMax - yMin + 1;
-
- // set up the Raster_Map structure
- if (engine->aa) {
- ras.width = (ras.width + 3) & ~3;
- ras.cols = ras.width;
- } else {
- ras.width = (ras.width + 7) & ~7;
- ras.cols = ras.width >> 3;
- }
- ras.flow = TT_Flow_Down;
- ras.size = ras.rows * ras.cols;
- ras.bitmap = gmalloc(ras.size);
-
- // set up the glyph pixmap cache
- cacheAssoc = 8;
- if (ras.size <= 256) {
- cacheSets = 8;
- } else if (ras.size <= 512) {
- cacheSets = 4;
- } else if (ras.size <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
- cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * ras.size);
- cacheTags = (TTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
- sizeof(TTFontCacheTag));
- for (i = 0; i < cacheSets * cacheAssoc; ++i) {
- cacheTags[i].mru = i & (cacheAssoc - 1);
- }
-
- // create the XImage
- if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
- ZPixmap, 0, NULL, ras.width, ras.rows, 8, 0))) {
- return;
- }
- image->data = (char *)gmalloc(ras.rows * image->bytes_per_line);
-
- // compute the transform matrix
- matrix.xx = (TT_Fixed)(m[0] * 65.536);
- matrix.yx = (TT_Fixed)(m[1] * 65.536);
- matrix.xy = (TT_Fixed)(m[2] * 65.536);
- matrix.yy = (TT_Fixed)(m[3] * 65.536);
-
- ok = gTrue;
-}
-
-TTFont::~TTFont() {
- gfree(cacheTags);
- gfree(cache);
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
- gfree(ras.bitmap);
- TT_Done_Glyph(glyph);
- TT_Done_Instance(instance);
-}
-
-GBool TTFont::drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u) {
- TTFontEngine *engine;
- XColor xcolor;
- int bgR, bgG, bgB;
- Gulong colors[5];
- TT_Byte *p;
- TT_Byte pix;
- int xx, yy, xx1;
- int x0, y0, x1, y1, w0, h0;
-
- engine = fontFile->engine;
-
- // compute: (x0,y0) = position in destination drawable
- // (x1,y1) = position in glyph image
- // (w0,h0) = size of image transfer
- x0 = x - xOffset;
- y0 = y - (ras.rows - yOffset);
- x1 = 0;
- y1 = 0;
- w0 = ras.width;
- h0 = ras.rows;
- if (x0 < 0) {
- x1 = -x0;
- w0 += x0;
- x0 = 0;
- }
- if (x0 + w0 > w) {
- w0 = w - x0;
- }
- if (w0 < 0) {
- return gTrue;
- }
- if (y0 < 0) {
- y1 = -y0;
- h0 += y0;
- y0 = 0;
- }
- if (y0 + h0 > h) {
- h0 = h - y0;
- }
- if (h0 < 0) {
- return gTrue;
- }
-
- // read the X image
- XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
- ZPixmap, image, x1, y1);
-
- // generate the glyph pixmap
- if (!getGlyphPixmap(c, u)) {
- return gFalse;
- }
-
- if (engine->aa) {
-
- // compute the colors
- xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2);
- XQueryColor(engine->display, engine->colormap, &xcolor);
- bgR = xcolor.red;
- bgG = xcolor.green;
- bgB = xcolor.blue;
- colors[1] = engine->findColor((r + 3*bgR) / 4,
- (g + 3*bgG) / 4,
- (b + 3*bgB) / 4);
- colors[2] = engine->findColor((r + bgR) / 2,
- (g + bgG) / 2,
- (b + bgB) / 2);
- colors[3] = engine->findColor((3*r + bgR) / 4,
- (3*g + bgG) / 4,
- (3*b + bgB) / 4);
- colors[4] = engine->findColor(r, g, b);
-
- // stuff the glyph pixmap into the X image
- p = (TT_Byte *)ras.bitmap;
- for (yy = 0; yy < ras.rows; ++yy) {
- for (xx = 0; xx < ras.width; ++xx) {
- pix = *p++;
- if (pix > 0) {
- if (pix > 4) {
- pix = 4;
- }
- XPutPixel(image, xx, yy, colors[pix]);
- }
- }
- }
-
- } else {
-
- // one color
- colors[1] = engine->findColor(r, g, b);
-
- // stuff the glyph bitmap into the X image
- p = (TT_Byte *)ras.bitmap;
- for (yy = 0; yy < ras.rows; ++yy) {
- for (xx = 0; xx < ras.width; xx += 8) {
- pix = *p++;
- for (xx1 = xx; xx1 < xx + 8 && xx1 < ras.width; ++xx1) {
- if (pix & 0x80) {
- XPutPixel(image, xx1, yy, colors[1]);
- }
- pix <<= 1;
- }
- }
- }
-
- }
-
- // draw the X image
- XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
-
- return gTrue;
-}
-
-GBool TTFont::getGlyphPixmap(CharCode c, Unicode u) {
- TT_UShort idx;
- TT_Outline outline;
- int i, j, k;
-
- // check the cache
- i = (c & (cacheSets - 1)) * cacheAssoc;
- for (j = 0; j < cacheAssoc; ++j) {
- if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
- memcpy(ras.bitmap, cache + (i+j) * ras.size, ras.size);
- for (k = 0; k < cacheAssoc; ++k) {
- if (k != j &&
- (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
- ++cacheTags[i+k].mru;
- }
- }
- cacheTags[i+j].mru = 0x8000;
- return gTrue;
- }
- }
-
- // generate the glyph pixmap or bitmap
- idx = 0; // make gcc happy
- switch (fontFile->mode) {
- case ttFontModeUnicode:
- idx = TT_Char_Index(fontFile->charMap, (TT_UShort)u);
- break;
- case ttFontModeCharCode:
- if ((idx = TT_Char_Index(fontFile->charMap, (TT_UShort)c)) == 0) {
- idx = TT_Char_Index(fontFile->charMap, (TT_UShort)(0xf000 + c));
- }
- break;
- case ttFontModeCodeMap:
- if (c <= 0xff) {
- idx = TT_Char_Index(fontFile->charMap,
- (TT_UShort)(fontFile->codeMap[c] & 0xff));
- } else {
- idx = 0;
- }
- break;
- case ttFontModeCIDToGIDMap:
- if (fontFile->cidToGIDLen) {
- if ((int)c < fontFile->cidToGIDLen) {
- idx = (TT_UShort)fontFile->cidToGID[c];
- } else {
- idx = (TT_UShort)0;
- }
- } else {
- idx = (TT_UShort)c;
- }
- break;
- }
- if (TT_Load_Glyph(instance, glyph, idx, TTLOAD_DEFAULT) ||
- TT_Get_Glyph_Outline(glyph, &outline)) {
- return gFalse;
- }
- TT_Transform_Outline(&outline, &matrix);
- memset(ras.bitmap, 0, ras.size);
- if (fontFile->engine->aa) {
- if (TT_Get_Glyph_Pixmap(glyph, &ras, xOffset * 64, yOffset * 64)) {
- return gFalse;
- }
- } else {
- if (TT_Get_Glyph_Bitmap(glyph, &ras, xOffset * 64, yOffset * 64)) {
- return gFalse;
- }
- }
-
- // store glyph pixmap in cache
- for (j = 0; j < cacheAssoc; ++j) {
- if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
- cacheTags[i+j].mru = 0x8000;
- cacheTags[i+j].code = c;
- memcpy(cache + (i+j) * ras.size, ras.bitmap, ras.size);
- } else {
- ++cacheTags[i+j].mru;
- }
- }
-
- return gTrue;
-}
-
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
diff --git a/pdf/xpdf/TTFont.h b/pdf/xpdf/TTFont.h
deleted file mode 100644
index e4740ea..0000000
--- a/pdf/xpdf/TTFont.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//========================================================================
-//
-// TTFont.h
-//
-// An X wrapper for the FreeType TrueType font rasterizer.
-//
-// Copyright 2001-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef TTFONT_H
-#define TTFONT_H
-
-#include <aconf.h>
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#if HAVE_FREETYPE_FREETYPE_H
-#include <freetype/freetype.h>
-#include <freetype/ftxpost.h>
-#else
-#include <freetype.h>
-#include <ftxpost.h>
-#endif
-#include "gtypes.h"
-#include "SFont.h"
-
-//------------------------------------------------------------------------
-
-class TTFontEngine: public SFontEngine {
-public:
-
- TTFontEngine(Display *displayA, Visual *visualA, int depthA,
- Colormap colormapA, GBool aaA);
- GBool isOk() { return ok; }
- virtual ~TTFontEngine();
-
-private:
-
- TT_Engine engine;
- GBool aa;
- Gulong palette[5];
- GBool ok;
-
- friend class TTFontFile;
- friend class TTFont;
-};
-
-//------------------------------------------------------------------------
-
-enum TTFontIndexMode {
- ttFontModeUnicode,
- ttFontModeCharCode,
- ttFontModeCodeMap,
- ttFontModeCIDToGIDMap
-};
-
-class TTFontFile: public SFontFile {
-public:
-
- // 8-bit font, TrueType or Type 1/1C
- TTFontFile(TTFontEngine *engineA, char *fontFileName,
- char **fontEnc, GBool pdfFontHasEncoding);
-
- // CID font, TrueType
- TTFontFile(TTFontEngine *engineA, char *fontFileName,
- Gushort *cidToGIDA, int cidToGIDLenA);
-
- GBool isOk() { return ok; }
- virtual ~TTFontFile();
-
-private:
-
- TTFontEngine *engine;
- TT_Face face;
- TT_CharMap charMap;
- TTFontIndexMode mode;
- Guchar *codeMap;
- Gushort *cidToGID;
- int cidToGIDLen;
- GBool ok;
-
- friend class TTFont;
-};
-
-//------------------------------------------------------------------------
-
-struct TTFontCacheTag {
- Gushort code;
- Gushort mru; // valid bit (0x8000) and MRU index
-};
-
-class TTFont: public SFont {
-public:
-
- TTFont(TTFontFile *fontFileA, double *m);
- GBool isOk() { return ok; }
- virtual ~TTFont();
- virtual GBool drawChar(Drawable d, int w, int h, GC gc,
- int x, int y, int r, int g, int b,
- CharCode c, Unicode u);
-
-private:
-
- GBool getGlyphPixmap(CharCode c, Unicode u);
-
- TTFontFile *fontFile;
- TT_Instance instance;
- TT_Glyph glyph;
- TT_Raster_Map ras;
- XImage *image;
- TT_Matrix matrix;
- TT_F26Dot6 xOffset, yOffset;
- Guchar *cache; // glyph pixmap cache
- TTFontCacheTag *cacheTags; // cache tags, i.e., char codes
- int cacheSets; // number of sets in cache
- int cacheAssoc; // cache associativity (glyphs per set)
- GBool ok;
-};
-
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#endif
diff --git a/pdf/xpdf/TextOutputDev.cc b/pdf/xpdf/TextOutputDev.cc
index aeee59c..c6fdfb9 100644
--- a/pdf/xpdf/TextOutputDev.cc
+++ b/pdf/xpdf/TextOutputDev.cc
@@ -45,9 +45,13 @@
// this many points.
#define textPoolStep 4
-// Inter-character space width which will cause addChar to break up a
-// text string.
-#define defaultSpaceWidth 0.25
+// Inter-character space width which will cause addChar to start a new
+// word.
+#define minWordBreakSpace 0.1
+
+// Negative inter-character space width, i.e., overlap, which will
+// cause addChar to start a new word.
+#define minDupBreakOverlap 0.2
// Max distance between baselines of two lines within a block, as a
// fraction of the font size.
@@ -72,13 +76,17 @@
// Minimum inter-word spacing, as a fraction of the font size. (Only
// used for raw ordering.)
-#define minWordSpacing 0.2
+#define minWordSpacing 0.15
// Maximum inter-word spacing, as a fraction of the font size.
#define maxWordSpacing 1.5
+// Maximum horizontal spacing which will allow a word to be pulled
+// into a block.
+#define minColSpacing1 0.3
+
// Minimum spacing between columns, as a fraction of the font size.
-#define minColSpacing 1.0
+#define minColSpacing2 1.0
// Maximum vertical spacing between blocks within a flow, as a
// multiple of the font size.
@@ -1591,6 +1599,7 @@ TextPage::TextPage(GBool rawOrderA) {
curFontSize = 0;
nest = 0;
nTinyChars = 0;
+ lastCharOverlap = gFalse;
if (!rawOrder) {
for (rot = 0; rot < 4; ++rot) {
pools[rot] = new TextPool();
@@ -1627,6 +1636,12 @@ void TextPage::startPage(GfxState *state) {
}
}
+void TextPage::endPage() {
+ if (curWord) {
+ endWord();
+ }
+}
+
void TextPage::clear() {
int rot;
TextFlow *flow;
@@ -1748,7 +1763,7 @@ void TextPage::beginWord(GfxState *state, double x0, double y0) {
// This check is needed because Type 3 characters can contain
// text-drawing operations (when TextPage is being used via
- // XOutputDev rather than TextOutputDev).
+ // {X,Win}SplashOutputDev rather than TextOutputDev).
if (curWord) {
++nest;
return;
@@ -1784,8 +1799,8 @@ void TextPage::beginWord(GfxState *state, double x0, double y0) {
void TextPage::addChar(GfxState *state, double x, double y,
double dx, double dy,
CharCode c, Unicode *u, int uLen) {
- double x1, y1, w1, h1, dx2, dy2, sp;
- int n, i;
+ double x1, y1, w1, h1, dx2, dy2, base, sp;
+ int i;
// if the previous char was a space, addChar will have called
// endWord, so we need to start a new word
@@ -1826,21 +1841,46 @@ void TextPage::addChar(GfxState *state, double x, double y,
return;
}
- // large char spacing is sometimes used to move text around -- in
- // this case, break text into individual chars and let the coalesce
- // function deal with it later
- n = curWord->len;
- if (n > 0) {
+ // start a new word if:
+ // (1) this character's baseline doesn't match the current word's
+ // baseline, or
+ // (2) there is space between the end of the current word and this
+ // character, or
+ // (3) this character overlaps the previous one (duplicated text), or
+ // (4) the previous character was an overlap (we want each duplicated
+ // characters to be in a word by itself)
+ base = sp = 0; // make gcc happy
+ if (curWord->len > 0) {
switch (curWord->rot) {
- case 0: sp = x1 - curWord->xMax; break;
- case 1: sp = y1 - curWord->yMax; break;
- case 2: sp = curWord->xMin - x1; break;
- case 3: sp = curWord->yMin - y1; break;
+ case 0:
+ base = y1;
+ sp = x1 - curWord->xMax;
+ break;
+ case 1:
+ base = x1;
+ sp = y1 - curWord->yMax;
+ break;
+ case 2:
+ base = y1;
+ sp = curWord->xMin - x1;
+ break;
+ case 3:
+ base = x1;
+ sp = curWord->yMin - y1;
+ break;
}
- if (sp > defaultSpaceWidth * curWord->fontSize) {
+ if (fabs(base - curWord->base) > 0.5 ||
+ sp > minWordBreakSpace * curWord->fontSize ||
+ sp < -minDupBreakOverlap * curWord->fontSize ||
+ lastCharOverlap) {
+ lastCharOverlap = gTrue;
endWord();
beginWord(state, x, y);
+ } else {
+ lastCharOverlap = gFalse;
}
+ } else {
+ lastCharOverlap = gFalse;
}
// page rotation and/or transform matrices can cause text to be
@@ -1873,7 +1913,7 @@ void TextPage::addChar(GfxState *state, double x, double y,
void TextPage::endWord() {
// This check is needed because Type 3 characters can contain
// text-drawing operations (when TextPage is being used via
- // XOutputDev rather than TextOutputDev).
+ // {X,Win}SplashOutputDev rather than TextOutputDev).
if (nest > 0) {
--nest;
return;
@@ -1915,7 +1955,7 @@ void TextPage::coalesce(GBool physLayout) {
TextFlow *flow, *lastFlow;
int rot, poolMinBaseIdx, baseIdx, startBaseIdx;
double minBase, maxBase, newMinBase, newMaxBase;
- double fontSize, colSpace, lineSpace, intraLineSpace, blkSpace;
+ double fontSize, colSpace1, colSpace2, lineSpace, intraLineSpace, blkSpace;
GBool found;
int count[4];
int lrCount;
@@ -2000,7 +2040,8 @@ void TextPage::coalesce(GBool physLayout) {
fontSize = word0->fontSize;
minBase = maxBase = word0->base;
- colSpace = minColSpacing * fontSize;
+ colSpace1 = minColSpacing1 * fontSize;
+ colSpace2 = minColSpacing2 * fontSize;
lineSpace = maxLineSpacingDelta * fontSize;
intraLineSpace = maxIntraLineDelta * fontSize;
@@ -2089,8 +2130,10 @@ void TextPage::coalesce(GBool physLayout) {
if (word1->base >= minBase - intraLineSpace &&
word1->base <= maxBase + intraLineSpace &&
((rot == 0 || rot == 2)
- ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin)
- : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) &&
+ ? (word1->xMin < blk->xMax + colSpace1 &&
+ word1->xMax > blk->xMin - colSpace1)
+ : (word1->yMin < blk->yMax + colSpace1 &&
+ word1->yMax > blk->yMin - colSpace1)) &&
fabs(word1->fontSize - fontSize) <
maxBlockFontSizeDelta2 * fontSize) {
word2 = word1;
@@ -2129,9 +2172,9 @@ void TextPage::coalesce(GBool physLayout) {
word1->base <= maxBase + intraLineSpace &&
((rot == 0 || rot == 2)
? (word1->xMax <= blk->xMin &&
- word1->xMax > blk->xMin - colSpace)
+ word1->xMax > blk->xMin - colSpace2)
: (word1->yMax <= blk->yMin &&
- word1->yMax > blk->yMin - colSpace)) &&
+ word1->yMax > blk->yMin - colSpace2)) &&
fabs(word1->fontSize - fontSize) <
maxBlockFontSizeDelta3 * fontSize) {
++n;
@@ -2151,9 +2194,9 @@ void TextPage::coalesce(GBool physLayout) {
word1->base <= maxBase + intraLineSpace &&
((rot == 0 || rot == 2)
? (word1->xMax <= blk->xMin &&
- word1->xMax > blk->xMin - colSpace)
+ word1->xMax > blk->xMin - colSpace2)
: (word1->yMax <= blk->yMin &&
- word1->yMax > blk->yMin - colSpace)) &&
+ word1->yMax > blk->yMin - colSpace2)) &&
fabs(word1->fontSize - fontSize) <
maxBlockFontSizeDelta3 * fontSize) {
word2 = word1;
@@ -2193,9 +2236,9 @@ void TextPage::coalesce(GBool physLayout) {
word1->base <= maxBase + intraLineSpace &&
((rot == 0 || rot == 2)
? (word1->xMin >= blk->xMax &&
- word1->xMin < blk->xMax + colSpace)
+ word1->xMin < blk->xMax + colSpace2)
: (word1->yMin >= blk->yMax &&
- word1->yMin < blk->yMax + colSpace)) &&
+ word1->yMin < blk->yMax + colSpace2)) &&
fabs(word1->fontSize - fontSize) <
maxBlockFontSizeDelta3 * fontSize) {
++n;
@@ -2215,9 +2258,9 @@ void TextPage::coalesce(GBool physLayout) {
word1->base <= maxBase + intraLineSpace &&
((rot == 0 || rot == 2)
? (word1->xMin >= blk->xMax &&
- word1->xMin < blk->xMax + colSpace)
+ word1->xMin < blk->xMax + colSpace2)
: (word1->yMin >= blk->yMax &&
- word1->yMin < blk->yMax + colSpace)) &&
+ word1->yMin < blk->yMax + colSpace2)) &&
fabs(word1->fontSize - fontSize) <
maxBlockFontSizeDelta3 * fontSize) {
word2 = word1;
@@ -3435,6 +3478,7 @@ void TextOutputDev::startPage(int pageNum, GfxState *state) {
}
void TextOutputDev::endPage() {
+ text->endPage();
text->coalesce(physLayout);
if (outputStream) {
text->dump(outputStream, outputFunc, physLayout);
@@ -3446,11 +3490,9 @@ void TextOutputDev::updateFont(GfxState *state) {
}
void TextOutputDev::beginString(GfxState *state, GString *s) {
- text->beginWord(state, state->getCurX(), state->getCurY());
}
void TextOutputDev::endString(GfxState *state) {
- text->endWord();
}
void TextOutputDev::drawChar(GfxState *state, double x, double y,
diff --git a/pdf/xpdf/TextOutputDev.h b/pdf/xpdf/TextOutputDev.h
index b501907..2c62237 100644
--- a/pdf/xpdf/TextOutputDev.h
+++ b/pdf/xpdf/TextOutputDev.h
@@ -354,6 +354,9 @@ public:
// Start a new page.
void startPage(GfxState *state);
+ // End the current page.
+ void endPage();
+
// Update the current font.
void updateFont(GfxState *state);
@@ -426,6 +429,8 @@ private:
double curFontSize; // current font size
int nest; // current nesting level (for Type 3 fonts)
int nTinyChars; // number of "tiny" chars seen so far
+ GBool lastCharOverlap; // set if the last added char overlapped the
+ // previous char
TextPool *pools[4]; // a "pool" of TextWords for each rotation
TextFlow *flows; // linked list of flows
diff --git a/pdf/xpdf/XOutputDev.cc b/pdf/xpdf/XOutputDev.cc
deleted file mode 100644
index a156b55..0000000
--- a/pdf/xpdf/XOutputDev.cc
+++ /dev/null
@@ -1,3986 +0,0 @@
-//========================================================================
-//
-// XOutputDev.cc
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include "gmem.h"
-#include "gfile.h"
-#include "GString.h"
-#include "GList.h"
-#include "Object.h"
-#include "Stream.h"
-#include "Link.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "UnicodeMap.h"
-#include "CharCodeToUnicode.h"
-#include "FontFile.h"
-#include "Error.h"
-#include "TextOutputDev.h"
-#include "XOutputDev.h"
-#if HAVE_T1LIB_H
-#include "T1Font.h"
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-#include "FTFont.h"
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-#include "TTFont.h"
-#endif
-
-#ifdef VMS
-#if (__VMS_VER < 70000000)
-extern "C" int unlink(char *filename);
-#endif
-#endif
-
-#ifdef XlibSpecificationRelease
-#if XlibSpecificationRelease < 5
-typedef char *XPointer;
-#endif
-#else
-typedef char *XPointer;
-#endif
-
-//------------------------------------------------------------------------
-// Constants and macros
-//------------------------------------------------------------------------
-
-#define xoutRound(x) ((int)(x + 0.5))
-
-#define maxCurveSplits 6 // max number of splits when recursively
- // drawing Bezier curves
-
-//------------------------------------------------------------------------
-// Font substitutions
-//------------------------------------------------------------------------
-
-struct XOutFontSubst {
- char *name;
- double mWidth;
-};
-
-// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
-static XOutFontSubst xOutSubstFonts[16] = {
- {"Helvetica", 0.833},
- {"Helvetica-Oblique", 0.833},
- {"Helvetica-Bold", 0.889},
- {"Helvetica-BoldOblique", 0.889},
- {"Times-Roman", 0.788},
- {"Times-Italic", 0.722},
- {"Times-Bold", 0.833},
- {"Times-BoldItalic", 0.778},
- {"Courier", 0.600},
- {"Courier-Oblique", 0.600},
- {"Courier-Bold", 0.600},
- {"Courier-BoldOblique", 0.600},
- {"Symbol", 0.576},
- {"Symbol", 0.576},
- {"Symbol", 0.576},
- {"Symbol", 0.576}
-};
-
-//------------------------------------------------------------------------
-
-static void outputToFile(void *stream, char *data, int len) {
- fwrite(data, 1, len, (FILE *)stream);
-}
-
-//------------------------------------------------------------------------
-// XOutputFont
-//------------------------------------------------------------------------
-
-XOutputFont::XOutputFont(Ref *idA, double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A, double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA) {
- id = *idA;
- display = displayA;
- xOut = xOutA;
- m11Orig = m11OrigA;
- m12Orig = m12OrigA;
- m21Orig = m21OrigA;
- m22Orig = m22OrigA;
- m11 = m11A;
- m12 = m12A;
- m21 = m21A;
- m22 = m22A;
-}
-
-XOutputFont::~XOutputFont() {
-}
-
-void XOutputFont::getCharPath(GfxState *state,
- CharCode c, Unicode *u, int ulen) {
-}
-
-#if HAVE_T1LIB_H
-//------------------------------------------------------------------------
-// XOutputT1Font
-//------------------------------------------------------------------------
-
-XOutputT1Font::XOutputT1Font(Ref *idA, T1FontFile *fontFileA,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA):
- XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
- m11A, m12A, m21A, m22A, displayA, xOutA)
-{
- double matrix[4];
-
- fontFile = fontFileA;
-
- // create the transformed instance
- matrix[0] = m11;
- matrix[1] = -m12;
- matrix[2] = m21;
- matrix[3] = -m22;
- font = new T1Font(fontFile, matrix);
-}
-
-XOutputT1Font::~XOutputT1Font() {
- if (font) {
- delete font;
- }
-}
-
-GBool XOutputT1Font::isOk() {
- return font != NULL;
-}
-
-void XOutputT1Font::updateGC(GC gc) {
-}
-
-void XOutputT1Font::drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen) {
- font->drawChar(pixmap, w, h, gc, xoutRound(x), xoutRound(y),
- (int)(rgb->r * 65535), (int)(rgb->g * 65535),
- (int)(rgb->b * 65535), c, u[0]);
-}
-
-void XOutputT1Font::getCharPath(GfxState *state,
- CharCode c, Unicode *u, int uLen) {
- font->getCharPath(c, u[0], state);
-}
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputFTFont
-//------------------------------------------------------------------------
-
-XOutputFTFont::XOutputFTFont(Ref *idA, FTFontFile *fontFileA,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA):
- XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
- m11A, m12A, m21A, m22A, displayA, xOutA)
-{
- double matrix[4];
-
- fontFile = fontFileA;
-
- // create the transformed instance
- matrix[0] = m11;
- matrix[1] = -m12;
- matrix[2] = m21;
- matrix[3] = -m22;
- font = new FTFont(fontFile, matrix);
-}
-
-XOutputFTFont::~XOutputFTFont() {
- if (font) {
- delete font;
- }
-}
-
-GBool XOutputFTFont::isOk() {
- return font != NULL;
-}
-
-void XOutputFTFont::updateGC(GC gc) {
-}
-
-void XOutputFTFont::drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen) {
- font->drawChar(pixmap, w, h, gc, xoutRound(x), xoutRound(y),
- (int)(rgb->r * 65535), (int)(rgb->g * 65535),
- (int)(rgb->b * 65535), c, uLen > 0 ? u[0] : 0);
-}
-
-void XOutputFTFont::getCharPath(GfxState *state,
- CharCode c, Unicode *u, int uLen) {
- font->getCharPath(c, u[0], state);
-}
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputTTFont
-//------------------------------------------------------------------------
-
-XOutputTTFont::XOutputTTFont(Ref *idA, TTFontFile *fontFileA,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA):
- XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
- m11A, m12A, m21A, m22A, displayA, xOutA)
-{
- double matrix[4];
-
- fontFile = fontFileA;
-
- // create the transformed instance
- matrix[0] = m11;
- matrix[1] = -m12;
- matrix[2] = m21;
- matrix[3] = -m22;
- font = new TTFont(fontFile, matrix);
-}
-
-XOutputTTFont::~XOutputTTFont() {
- if (font) {
- delete font;
- }
-}
-
-GBool XOutputTTFont::isOk() {
- return font != NULL;
-}
-
-void XOutputTTFont::updateGC(GC gc) {
-}
-
-void XOutputTTFont::drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen) {
- font->drawChar(pixmap, w, h, gc, xoutRound(x), xoutRound(y),
- (int)(rgb->r * 65535), (int)(rgb->g * 65535),
- (int)(rgb->b * 65535), c, u[0]);
-}
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-//------------------------------------------------------------------------
-// XOutputServer8BitFont
-//------------------------------------------------------------------------
-
-// Copy <fmt>, substituting <val> for one occurrence of "%s", into
-// <buf>.
-static void stringSubst(char *buf, int bufSize, char *fmt, char *val) {
- char *p, *q;
- int i;
-
- i = 0;
- p = fmt;
- while (*p) {
- if (p[0] == '%' && p[1] == 's') {
- q = val;
- while (*q && i < bufSize - 1) {
- buf[i++] = *q++;
- }
- p += 2;
- } else {
- if (i < bufSize - 1) {
- buf[i++] = *p;
- }
- ++p;
- }
- }
- buf[i] = '\0';
-}
-
-XOutputServer8BitFont::XOutputServer8BitFont(Ref *idA, GString *xlfdFmt,
- UnicodeMap *xUMapA,
- CharCodeToUnicode *fontUMap,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA,
- XOutputDev *xOutA):
- XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
- m11A, m12A, m21A, m22A, displayA, xOutA)
-{
- double size, ntm11, ntm12, ntm21, ntm22;
- GBool rotated;
- int startSize, sz;
- char fontName[500], fontSize[100];
- Unicode u;
- char buf;
- int i;
-
- // compute size and normalized transform matrix
- size = sqrt(m21*m21 + m22*m22);
- ntm11 = m11 / size;
- ntm12 = -m12 / size;
- ntm21 = m21 / size;
- ntm22 = -m22 / size;
-
- // try to get a rotated font?
- rotated = !(ntm11 > 0 && ntm22 > 0 &&
- fabs(ntm11 / ntm22 - 1) < 0.2 &&
- fabs(ntm12) < 0.01 &&
- fabs(ntm21) < 0.01);
-
- // open X font -- if font is not found (which means the server can't
- // scale fonts), try progressively smaller and then larger sizes
- startSize = (int)size;
- if (rotated) {
- sprintf(fontSize, "[%s%0.2f %s%0.2f %s%0.2f %s%0.2f]",
- ntm11<0 ? "~" : "", fabs(ntm11 * size),
- ntm12<0 ? "~" : "", fabs(ntm12 * size),
- ntm21<0 ? "~" : "", fabs(ntm21 * size),
- ntm22<0 ? "~" : "", fabs(ntm22 * size));
- } else {
- sprintf(fontSize, "%d", startSize);
- }
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
- xFont = XLoadQueryFont(display, fontName);
- if (!xFont) {
- for (sz = startSize; sz >= startSize/2 && sz >= 1; --sz) {
- sprintf(fontSize, "%d", sz);
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
- if ((xFont = XLoadQueryFont(display, fontName)))
- break;
- }
- if (!xFont) {
- for (sz = startSize + 1; sz < startSize + 10; ++sz) {
- sprintf(fontSize, "%d", sz);
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
- fontSize);
- if ((xFont = XLoadQueryFont(display, fontName))) {
- break;
- }
- }
- if (!xFont) {
- sprintf(fontSize, "%d", startSize);
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
- fontSize);
- error(-1, "Failed to open font: '%s'", fontName);
- return;
- }
- }
- }
-
- // Construct char code map.
- xUMap = xUMapA;
- for (i = 0; i < 256; ++i) {
- if (fontUMap->mapToUnicode((CID)i, &u, 1) == 1 &&
- xUMap->mapUnicode(u, &buf, 1) == 1) {
- map[i] = buf & 0xff;
- } else {
- map[i] = 0;
- }
- }
-}
-
-XOutputServer8BitFont::~XOutputServer8BitFont() {
- if (xFont) {
- XFreeFont(display, xFont);
- }
-}
-
-GBool XOutputServer8BitFont::isOk() {
- return xFont != NULL;
-}
-
-void XOutputServer8BitFont::updateGC(GC gc) {
- XSetFont(display, gc, xFont->fid);
-}
-
-void XOutputServer8BitFont::drawChar(GfxState *state, Pixmap pixmap,
- int w, int h, GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen) {
- Gushort c1;
- char buf[8];
- double dx1, dy1;
- int m, n, i, j, k;
-
- c1 = map[c];
- if (c1 > 0) {
- buf[0] = (char)c1;
- XDrawString(display, pixmap, gc, xoutRound(x), xoutRound(y), buf, 1);
- } else {
- // substituted character, using more than one character
- n = 0;
- for (i = 0; i < uLen; ++i) {
- n += xUMap->mapUnicode(u[i], buf, sizeof(buf));
- }
- if (n > 0) {
- dx1 = dx / n;
- dy1 = dy / n;
- k = 0;
- for (i = 0; i < uLen; ++i) {
- m = xUMap->mapUnicode(u[i], buf, sizeof(buf));
- for (j = 0; j < m; ++j) {
- XDrawString(display, pixmap, gc,
- xoutRound(x + k*dx1), xoutRound(y + k*dy1),
- buf + j, 1);
- ++k;
- }
- }
- }
- }
-}
-
-//------------------------------------------------------------------------
-// XOutputServer16BitFont
-//------------------------------------------------------------------------
-
-XOutputServer16BitFont::XOutputServer16BitFont(Ref *idA, GString *xlfdFmt,
- UnicodeMap *xUMapA,
- CharCodeToUnicode *fontUMap,
- double m11OrigA,
- double m12OrigA,
- double m21OrigA,
- double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA,
- XOutputDev *xOutA):
- XOutputFont(idA, m11OrigA, m12OrigA, m21OrigA, m22OrigA,
- m11A, m12A, m21A, m22A, displayA, xOutA)
-{
- double size, ntm11, ntm12, ntm21, ntm22;
- GBool rotated;
- int startSize, sz;
- char fontName[500], fontSize[100];
-
- xUMap = xUMapA;
- xUMap->incRefCnt();
-
- // compute size and normalized transform matrix
- size = sqrt(m21*m21 + m22*m22);
- ntm11 = m11 / size;
- ntm12 = -m12 / size;
- ntm21 = m21 / size;
- ntm22 = -m22 / size;
-
- // try to get a rotated font?
- rotated = !(ntm11 > 0 && ntm22 > 0 &&
- fabs(ntm11 / ntm22 - 1) < 0.2 &&
- fabs(ntm12) < 0.01 &&
- fabs(ntm21) < 0.01);
-
- // open X font -- if font is not found (which means the server can't
- // scale fonts), try progressively smaller and then larger sizes
- startSize = (int)size;
- if (rotated) {
- sprintf(fontSize, "[%s%0.2f %s%0.2f %s%0.2f %s%0.2f]",
- ntm11<0 ? "~" : "", fabs(ntm11 * size),
- ntm12<0 ? "~" : "", fabs(ntm12 * size),
- ntm21<0 ? "~" : "", fabs(ntm21 * size),
- ntm22<0 ? "~" : "", fabs(ntm22 * size));
- } else {
- sprintf(fontSize, "%d", startSize);
- }
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
- xFont = XLoadQueryFont(display, fontName);
- if (!xFont) {
- for (sz = startSize; sz >= startSize/2 && sz >= 1; --sz) {
- sprintf(fontSize, "%d", sz);
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(), fontSize);
- if ((xFont = XLoadQueryFont(display, fontName)))
- break;
- }
- if (!xFont) {
- for (sz = startSize + 1; sz < startSize + 10; ++sz) {
- sprintf(fontSize, "%d", sz);
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
- fontSize);
- if ((xFont = XLoadQueryFont(display, fontName))) {
- break;
- }
- }
- if (!xFont) {
- sprintf(fontSize, "%d", startSize);
- stringSubst(fontName, sizeof(fontName), xlfdFmt->getCString(),
- fontSize);
- error(-1, "Failed to open font: '%s'", fontName);
- return;
- }
- }
- }
-}
-
-XOutputServer16BitFont::~XOutputServer16BitFont() {
- xUMap->decRefCnt();
- if (xFont) {
- XFreeFont(display, xFont);
- }
-}
-
-GBool XOutputServer16BitFont::isOk() {
- return xFont != NULL;
-}
-
-void XOutputServer16BitFont::updateGC(GC gc) {
- XSetFont(display, gc, xFont->fid);
-}
-
-void XOutputServer16BitFont::drawChar(GfxState *state, Pixmap pixmap,
- int w, int h, GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen) {
- char buf[16];
- XChar2b c1;
- double dx1, dy1;
- int m, n, i, j, k;
-
- n = 0;
- for (i = 0; i < uLen; ++i) {
- n += xUMap->mapUnicode(u[i], buf, sizeof(buf));
- }
- if (n > 0) {
- dx1 = dx / n;
- dy1 = dy / n;
- k = 0;
- for (i = 0; i < uLen; ++i) {
- m = xUMap->mapUnicode(u[i], buf, sizeof(buf));
- for (j = 0; j+1 < m; j += 2) {
- c1.byte1 = buf[j];
- c1.byte2 = buf[j+1];
- XDrawString16(display, pixmap, gc,
- xoutRound(x + k*dx1), xoutRound(y + k*dy1),
- &c1, 1);
- ++k;
- }
- }
- } else if (c != 0) {
- // some PDF files use CID 0, which is .notdef, so just ignore it
- error(-1, "Unknown character (CID=%d Unicode=%04x)",
- c, uLen > 0 ? u[0] : (Unicode)0);
- }
-}
-
-//------------------------------------------------------------------------
-// XOutputFontCache
-//------------------------------------------------------------------------
-
-#if HAVE_T1LIB_H
-XOutputT1FontFile::~XOutputT1FontFile() {
- delete fontFile;
- if (tmpFileName) {
- unlink(tmpFileName->getCString());
- delete tmpFileName;
- }
-}
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputFTFontFile::~XOutputFTFontFile() {
- delete fontFile;
- if (tmpFileName) {
- unlink(tmpFileName->getCString());
- delete tmpFileName;
- }
-}
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputTTFontFile::~XOutputTTFontFile() {
- delete fontFile;
- if (tmpFileName) {
- unlink(tmpFileName->getCString());
- delete tmpFileName;
- }
-}
-#endif
-
-XOutputFontCache::XOutputFontCache(Display *displayA, Guint depthA,
- XOutputDev *xOutA,
- FontRastControl t1libControlA,
- FontRastControl freetypeControlA) {
- display = displayA;
- depth = depthA;
- xOut = xOutA;
-
-#if HAVE_T1LIB_H
- t1libControl = t1libControlA;
- t1Engine = NULL;
- t1FontFiles = NULL;
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- freetypeControl = freetypeControlA;
- ftEngine = NULL;
- ftFontFiles = NULL;
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- freetypeControl = freetypeControlA;
- ttEngine = NULL;
- ttFontFiles = NULL;
-#endif
-
- clear();
-}
-
-XOutputFontCache::~XOutputFontCache() {
- delFonts();
-}
-
-void XOutputFontCache::startDoc(int screenNum, Visual *visual,
- Colormap colormap, GBool trueColor,
- int rMul, int gMul, int bMul,
- int rShift, int gShift, int bShift,
- Gulong *colors, int numColors) {
- delFonts();
- clear();
-
-#if HAVE_T1LIB_H
- if (t1libControl != fontRastNone) {
- t1Engine = new T1FontEngine(display, visual, depth, colormap,
- t1libControl == fontRastAALow ||
- t1libControl == fontRastAAHigh,
- t1libControl == fontRastAAHigh);
- if (t1Engine->isOk()) {
- if (trueColor) {
- t1Engine->useTrueColor(rMul, rShift, gMul, gShift, bMul, bShift);
- } else {
- t1Engine->useColorCube(colors, numColors);
- }
- } else {
- delete t1Engine;
- t1Engine = NULL;
- }
- }
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- ftEngine = new FTFontEngine(display, visual, depth, colormap,
- freetypeControl == fontRastAALow ||
- freetypeControl == fontRastAAHigh);
- if (ftEngine->isOk()) {
- if (trueColor) {
- ftEngine->useTrueColor(rMul, rShift, gMul, gShift, bMul, bShift);
- } else {
- ftEngine->useColorCube(colors, numColors);
- }
- } else {
- delete ftEngine;
- ftEngine = NULL;
- }
- }
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- ttEngine = new TTFontEngine(display, visual, depth, colormap,
- freetypeControl == fontRastAALow ||
- freetypeControl == fontRastAAHigh);
- if (ttEngine->isOk()) {
- if (trueColor) {
- ttEngine->useTrueColor(rMul, rShift, gMul, gShift, bMul, bShift);
- } else {
- ttEngine->useColorCube(colors, numColors);
- }
- } else {
- delete ttEngine;
- ttEngine = NULL;
- }
- }
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-}
-
-void XOutputFontCache::delFonts() {
- int i;
-
- for (i = 0; i < nFonts; ++i) {
- delete fonts[i];
- }
-
-#if HAVE_T1LIB_H
- // delete Type 1 font files
- if (t1FontFiles) {
- deleteGList(t1FontFiles, XOutputT1FontFile);
- t1FontFiles = NULL;
- }
- if (t1Engine) {
- delete t1Engine;
- t1Engine = NULL;
- }
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- // delete FreeType font files
- if (ftFontFiles) {
- deleteGList(ftFontFiles, XOutputFTFontFile);
- ftFontFiles = NULL;
- }
- if (ftEngine) {
- delete ftEngine;
- ftEngine = NULL;
- }
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- // delete TrueType fonts
- if (ttFontFiles) {
- deleteGList(ttFontFiles, XOutputTTFontFile);
- ttFontFiles = NULL;
- }
- if (ttEngine) {
- delete ttEngine;
- ttEngine = NULL;
- }
-#endif
-}
-
-void XOutputFontCache::clear() {
- int i;
-
- for (i = 0; i < xOutFontCacheSize; ++i) {
- fonts[i] = NULL;
- }
- nFonts = 0;
-
-#if HAVE_T1LIB_H
- // clear Type 1 font files
- t1FontFiles = new GList();
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- // clear FreeType font cache
- ftFontFiles = new GList();
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- // clear TrueType font cache
- ttFontFiles = new GList();
-#endif
-}
-
-XOutputFont *XOutputFontCache::getFont(XRef *xref, GfxFont *gfxFont,
- double m11, double m12,
- double m21, double m22) {
- XOutputFont *font;
- DisplayFontParam *dfp;
- GString *substName;
- double m11New, m12New, m21New, m22New;
- double w1, w2, v;
- double *fm;
- char *name;
- int index;
- int code;
- int i, j;
-
- // is it the most recently used font?
- if (nFonts > 0 && fonts[0]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
- return fonts[0];
- }
-
- // is it in the cache?
- for (i = 1; i < nFonts; ++i) {
- if (fonts[i]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
- font = fonts[i];
- for (j = i; j > 0; --j) {
- fonts[j] = fonts[j-1];
- }
- fonts[0] = font;
- return font;
- }
- }
-
- // try for a cached FontFile, an embedded font, or an external font
- // file
- font = NULL;
- switch (gfxFont->getType()) {
- case fontType1:
- case fontType1C:
-#if HAVE_T1LIB_H
- if (t1libControl != fontRastNone) {
- font = tryGetT1Font(xref, gfxFont, m11, m12, m21, m22);
- }
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (!font) {
- if (freetypeControl != fontRastNone) {
- font = tryGetFTFont(xref, gfxFont, m11, m12, m21, m22);
- }
- }
-#endif
- break;
- case fontTrueType:
- case fontCIDType2:
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- font = tryGetFTFont(xref, gfxFont, m11, m12, m21, m22);
- }
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- font = tryGetTTFont(xref, gfxFont, m11, m12, m21, m22);
- }
-#endif
- break;
- case fontCIDType0:
- case fontCIDType0C:
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- font = tryGetFTFont(xref, gfxFont, m11, m12, m21, m22);
- }
-#endif
- break;
- default:
- break;
- }
-
- if (!font) {
-
- // search for a display font mapping
- dfp = NULL;
- if (gfxFont->isCIDFont()) {
- if (((GfxCIDFont *)gfxFont)->getCollection()) {
- dfp = globalParams->
- getDisplayCIDFont(gfxFont->getName(),
- ((GfxCIDFont *)gfxFont)->getCollection());
- } else {
- // this error (no CMap file) was already reported by GfxFont
- return NULL;
- }
- } else {
- if (gfxFont->getName()) {
- dfp = globalParams->getDisplayFont(gfxFont->getName());
- }
- }
- if (dfp) {
- font = tryGetFont(xref, dfp, gfxFont, m11, m12, m21, m22,
- m11, m12, m21, m22, gFalse);
- }
-
- // substitute a font (8-bit fonts only)
- if (!font && !gfxFont->isCIDFont()) {
-
- // choose a substitute font
- if (gfxFont->isFixedWidth()) {
- index = 8;
- } else if (gfxFont->isSerif()) {
- index = 4;
- } else {
- index = 0;
- }
- if (gfxFont->isBold()) {
- index += 2;
- }
- if (gfxFont->isItalic()) {
- index += 1;
- }
- substName = new GString(xOutSubstFonts[index].name);
-
- // adjust the font matrix -- compare the width of 'm' in the
- // original font and the substituted font
- m11New = m11;
- m12New = m12;
- m21New = m21;
- m22New = m22;
- for (code = 0; code < 256; ++code) {
- if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
- name[0] == 'm' && name[1] == '\0') {
- break;
- }
- }
- if (code < 256) {
- w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
- w2 = xOutSubstFonts[index].mWidth;
- if (gfxFont->getType() == fontType3) {
- // This is a hack which makes it possible to substitute for some
- // Type 3 fonts. The problem is that it's impossible to know what
- // the base coordinate system used in the font is without actually
- // rendering the font. This code tries to guess by looking at the
- // width of the character 'm' (which breaks if the font is a
- // subset that doesn't contain 'm').
- if (w1 > 0 && (w1 > 1.1 * w2 || w1 < 0.9 * w2)) {
- w1 /= w2;
- m11New *= w1;
- m12New *= w1;
- m21New *= w1;
- m22New *= w1;
- }
- fm = gfxFont->getFontMatrix();
- v = (fm[0] == 0) ? 1 : (fm[3] / fm[0]);
- m21New *= v;
- m22New *= v;
- } else if (!gfxFont->isSymbolic()) {
- // if real font is substantially narrower than substituted
- // font, reduce the font size accordingly
- if (w1 > 0.01 && w1 < 0.9 * w2) {
- w1 /= w2;
- m11New *= w1;
- m21New *= w1;
- }
- }
- }
-
- // get the font
- dfp = globalParams->getDisplayFont(substName);
- delete substName;
- if (!dfp) {
- // this should never happen since GlobalParams sets up default
- // mappings for the Base-14 fonts
- error(-1, "Couldn't find a font for '%s'",
- gfxFont->getName()->getCString());
- return NULL;
- }
- font = tryGetFont(xref, dfp, gfxFont, m11, m12, m21, m22,
- m11New, m12New, m21New, m22New, gTrue);
- }
- }
-
- // check for error
- if (!font) {
- // This will happen if the user specifies a bogus font in the
- // config file (a non-existent font file or a font that requires a
- // rasterizer that is disabled or wasn't built in), or if a CID
- // font has no associated font in the config file.
- if (gfxFont->isCIDFont()) {
- error(-1, "Couldn't find a font for the '%s' character collection",
- ((GfxCIDFont *)gfxFont)->getCollection()->getCString());
- } else {
- error(-1, "Couldn't find a font for '%s'",
- gfxFont->getName() ?
- gfxFont->getName()->getCString() : "[unnamed]");
- }
- return NULL;
- }
-
- // insert font in cache
- if (nFonts == xOutFontCacheSize) {
- --nFonts;
- delete fonts[nFonts];
- }
- for (j = nFonts; j > 0; --j) {
- fonts[j] = fonts[j-1];
- }
- fonts[0] = font;
- ++nFonts;
-
- return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetFont(XRef *xref, DisplayFontParam *dfp,
- GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12,
- double m21, double m22,
- GBool subst) {
- XOutputFont *font;
-
- font = NULL;
-
- // create the new font
- switch (dfp->kind) {
-
- case displayFontX:
- font = tryGetServerFont(dfp->x.xlfd, dfp->x.encoding, gfxFont,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22);
- break;
-
- case displayFontT1:
-#if HAVE_T1LIB_H
- if (t1libControl != fontRastNone && !gfxFont->isCIDFont()) {
- font = tryGetT1FontFromFile(xref, dfp->t1.fileName, gFalse, gfxFont,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, subst);
- }
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (!font) {
- if (freetypeControl != fontRastNone) {
- font = tryGetFTFontFromFile(xref, dfp->t1.fileName, gFalse, gfxFont,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, gFalse, subst);
- }
- }
-#endif
-#if !((FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)) || defined(HAVE_T1LIB_H))
- error(-1, "Config file specifies a Type 1 font,");
- error(-1, "but xpdf was not built with t1lib or FreeType2 support");
-#endif
- break;
-
- case displayFontTT:
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- font = tryGetFTFontFromFile(xref, dfp->tt.fileName, gFalse, gfxFont,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, gFalse, subst);
- }
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- if (freetypeControl != fontRastNone) {
- font = tryGetTTFontFromFile(xref, dfp->tt.fileName, gFalse, gfxFont,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, subst);
- }
-#endif
-#if !(HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- error(-1, "Config file specifies a TrueType font,");
- error(-1, "but xpdf was not built with FreeType support");
- dfp = NULL;
-#endif
- break;
- }
-
- return font;
-}
-
-#if HAVE_T1LIB_H
-XOutputFont *XOutputFontCache::tryGetT1Font(XRef *xref,
- GfxFont *gfxFont,
- double m11, double m12,
- double m21, double m22) {
- Ref *id;
- XOutputT1FontFile *xFontFile;
- XOutputFont *font;
- Ref embRef;
- GString *fileName;
- FILE *f;
- char *fontBuf;
- int fontLen;
- Type1CFontFile *ff;
- Object refObj, strObj;
- int c;
- int i;
-
- // check the already available font files
- id = gfxFont->getID();
- for (i = 0; i < t1FontFiles->getLength(); ++i) {
- xFontFile = (XOutputT1FontFile *)t1FontFiles->get(i);
- if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
- !xFontFile->subst) {
- font = new XOutputT1Font(id, xFontFile->fontFile,
- m11, m12, m21, m22,
- m11, m12, m21, m22, display, xOut);
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
- }
- }
-
- // check for an embedded font
- if (gfxFont->getEmbeddedFontID(&embRef)) {
-
- // create the font file
- fileName = NULL;
- if (!openTempFile(&fileName, &f, "wb", NULL)) {
- error(-1, "Couldn't create temporary Type 1 font file");
- return NULL;
- }
- if (gfxFont->getType() == fontType1C) {
- if (!(fontBuf = gfxFont->readEmbFontFile(xref, &fontLen))) {
- fclose(f);
- unlink(fileName->getCString());
- delete fileName;
- return NULL;
- }
- ff = new Type1CFontFile(fontBuf, fontLen);
- if (!ff->isOk()) {
- delete ff;
- gfree(fontBuf);
- unlink(fileName->getCString());
- delete fileName;
- return NULL;
- }
- ff->convertToType1(outputToFile, f);
- delete ff;
- gfree(fontBuf);
- } else { // fontType1
- refObj.initRef(embRef.num, embRef.gen);
- refObj.fetch(xref, &strObj);
- refObj.free();
- strObj.streamReset();
- while ((c = strObj.streamGetChar()) != EOF) {
- fputc(c, f);
- }
- strObj.streamClose();
- strObj.free();
- }
- fclose(f);
-
- // create the Font
- font = tryGetT1FontFromFile(xref, fileName, gTrue, gfxFont,
- m11, m12, m21, m22,
- m11, m12, m21, m22, gFalse);
-
- // on systems with Unix hard link semantics, this will remove the
- // last link to the temp file
- unlink(fileName->getCString());
-
- delete fileName;
-
- // check for an external font file
- } else if ((fileName = gfxFont->getExtFontFile())) {
- font = tryGetT1FontFromFile(xref, fileName, gFalse, gfxFont,
- m11, m12, m21, m22,
- m11, m12, m21, m22, gFalse);
-
- } else {
- font = NULL;
- }
-
- return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetT1FontFromFile(XRef *xref,
- GString *fileName,
- GBool deleteFile,
- GfxFont *gfxFont,
- double m11Orig,
- double m12Orig,
- double m21Orig,
- double m22Orig,
- double m11, double m12,
- double m21, double m22,
- GBool subst) {
- Ref *id;
- T1FontFile *fontFile;
- XOutputFont *font;
-
- // create the t1lib font file
- fontFile = new T1FontFile(t1Engine, fileName->getCString(),
- ((Gfx8BitFont *)gfxFont)->getEncoding(),
- gfxFont->getFontBBox());
- if (!fontFile->isOk()) {
- error(-1, "Couldn't create t1lib font from '%s'",
- fileName->getCString());
- delete fontFile;
- if (deleteFile) {
- unlink(fileName->getCString());
- }
- return NULL;
- }
-
- // add to list
- id = gfxFont->getID();
- t1FontFiles->append(new XOutputT1FontFile(id->num, id->gen,
- subst, fontFile,
- deleteFile ? fileName->copy()
- : (GString *)NULL));
-
- // create the Font
- font = new XOutputT1Font(gfxFont->getID(), fontFile,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, display, xOut);
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
-}
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputFont *XOutputFontCache::tryGetFTFont(XRef *xref,
- GfxFont *gfxFont,
- double m11, double m12,
- double m21, double m22) {
- Ref *id;
- XOutputFTFontFile *xFontFile;
- XOutputFont *font;
- Ref embRef;
- GString *fileName;
- FILE *f;
-#if 1 //~ need this until FT can handle fonts with missing tables
- char *fontBuf;
- int fontLen;
- TrueTypeFontFile *ff;
-#endif
- Object refObj, strObj;
- int c;
- int i;
-
- // check the already available font files
- id = gfxFont->getID();
- for (i = 0; i < ftFontFiles->getLength(); ++i) {
- xFontFile = (XOutputFTFontFile *)ftFontFiles->get(i);
- if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
- !xFontFile->subst) {
- font = new XOutputFTFont(id, xFontFile->fontFile,
- m11, m12, m21, m22,
- m11, m12, m21, m22, display, xOut);
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
- }
- }
-
- // check for an embedded font
- if (gfxFont->getEmbeddedFontID(&embRef)) {
-
- // create the font file
- fileName = NULL;
- if (!openTempFile(&fileName, &f, "wb", NULL)) {
- error(-1, "Couldn't create temporary TrueType font file");
- return NULL;
- }
-#if 1 //~ need this until FT can handle fonts with missing tables
- if (gfxFont->getType() == fontTrueType ||
- gfxFont->getType() == fontCIDType2) {
- if (!(fontBuf = gfxFont->readEmbFontFile(xref, &fontLen))) {
- fclose(f);
- unlink(fileName->getCString());
- delete fileName;
- return NULL;
- }
- ff = new TrueTypeFontFile(fontBuf, fontLen);
- ff->writeTTF(f);
- delete ff;
- gfree(fontBuf);
- } else {
- refObj.initRef(embRef.num, embRef.gen);
- refObj.fetch(xref, &strObj);
- refObj.free();
- strObj.streamReset();
- while ((c = strObj.streamGetChar()) != EOF) {
- fputc(c, f);
- }
- strObj.streamClose();
- strObj.free();
- }
-#else
- refObj.initRef(embRef.num, embRef.gen);
- refObj.fetch(xref, &strObj);
- refObj.free();
- strObj.streamReset();
- while ((c = strObj.streamGetChar()) != EOF) {
- fputc(c, f);
- }
- strObj.streamClose();
- strObj.free();
-#endif
- fclose(f);
-
- // create the Font
- font = tryGetFTFontFromFile(xref, fileName, gTrue, gfxFont,
- m11, m12, m21, m22,
- m11, m12, m21, m22, gTrue, gFalse);
-
- // on systems with Unix hard link semantics, this will remove the
- // last link to the temp file
- unlink(fileName->getCString());
-
- delete fileName;
-
- // check for an external font file
- } else if ((fileName = gfxFont->getExtFontFile())) {
- font = tryGetFTFontFromFile(xref, fileName, gFalse, gfxFont,
- m11, m12, m21, m22,
- m11, m12, m21, m22, gFalse, gFalse);
-
- } else {
- font = NULL;
- }
-
- return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetFTFontFromFile(XRef *xref,
- GString *fileName,
- GBool deleteFile,
- GfxFont *gfxFont,
- double m11Orig,
- double m12Orig,
- double m21Orig,
- double m22Orig,
- double m11, double m12,
- double m21, double m22,
- GBool embedded,
- GBool subst) {
- Ref *id;
- FTFontFile *fontFile;
- XOutputFont *font;
- char *buf;
- int len;
- FILE *f;
- TrueTypeFontFile *ff;
- Gushort *codeToGID;
-
- // create the FreeType font file
- if (gfxFont->isCIDFont()) {
- if (gfxFont->getType() == fontCIDType2) {
- fontFile = new FTFontFile(ftEngine, fileName->getCString(),
- ((GfxCIDFont *)gfxFont)->getCIDToGID(),
- ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(),
- embedded);
- } else { // fontCIDType0, fontCIDType0C
- fontFile = new FTFontFile(ftEngine, fileName->getCString(), embedded);
- }
- } else {
- if (!(f = fopen(fileName->getCString(), "rb"))) {
- return NULL;
- }
- fseek(f, 0, SEEK_END);
- len = (int)ftell(f);
- fseek(f, 0, SEEK_SET);
- buf = (char *)gmalloc(len);
- if ((int)fread(buf, 1, len, f) != len) {
- gfree(buf);
- fclose(f);
- return NULL;
- }
- fclose(f);
- ff = new TrueTypeFontFile(buf, len);
- codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
- fontFile = new FTFontFile(ftEngine, fileName->getCString(),
- ((Gfx8BitFont *)gfxFont)->getEncoding(),
- codeToGID);
- gfree(codeToGID);
- delete ff;
- gfree(buf);
- }
- if (!fontFile->isOk()) {
- error(-1, "Couldn't create FreeType font from '%s'",
- fileName->getCString());
- delete fontFile;
- if (deleteFile) {
- unlink(fileName->getCString());
- }
- return NULL;
- }
-
- // add to list
- id = gfxFont->getID();
- ftFontFiles->append(new XOutputFTFontFile(id->num, id->gen,
- subst, fontFile,
- deleteFile ? fileName->copy()
- : (GString *)NULL));
-
- // create the Font
- font = new XOutputFTFont(gfxFont->getID(), fontFile,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, display, xOut);
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
-}
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-XOutputFont *XOutputFontCache::tryGetTTFont(XRef *xref,
- GfxFont *gfxFont,
- double m11, double m12,
- double m21, double m22) {
- Ref *id;
- XOutputTTFontFile *xFontFile;
- XOutputFont *font;
- Ref embRef;
- GString *fileName;
- FILE *f;
- Object refObj, strObj;
- int c;
- int i;
-
- // check the already available font files
- id = gfxFont->getID();
- xFontFile = NULL;
- for (i = 0; i < ttFontFiles->getLength(); ++i) {
- xFontFile = (XOutputTTFontFile *)ttFontFiles->get(i);
- if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
- !xFontFile->subst) {
- font = new XOutputTTFont(id, xFontFile->fontFile,
- m11, m12, m21, m22,
- m11, m12, m21, m22, display, xOut);
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
- }
- }
-
- // check for an embedded font
- if (gfxFont->getEmbeddedFontID(&embRef)) {
-
- // create the font file
- fileName = NULL;
- if (!openTempFile(&fileName, &f, "wb", NULL)) {
- error(-1, "Couldn't create temporary TrueType font file");
- return NULL;
- }
- refObj.initRef(embRef.num, embRef.gen);
- refObj.fetch(xref, &strObj);
- refObj.free();
- strObj.streamReset();
- while ((c = strObj.streamGetChar()) != EOF) {
- fputc(c, f);
- }
- strObj.streamClose();
- strObj.free();
- fclose(f);
-
- // create the Font
- font = tryGetTTFontFromFile(xref, fileName, gTrue, gfxFont,
- m11, m12, m21, m22,
- m11, m12, m21, m22, gFalse);
-
- // on systems with Unix hard link semantics, this will remove the
- // last link to the temp file
- unlink(fileName->getCString());
-
- delete fileName;
-
- } else if ((fileName = gfxFont->getExtFontFile())) {
- font = tryGetTTFontFromFile(xref, fileName, gFalse, gfxFont,
- m11, m12, m21, m22,
- m11, m12, m21, m22, gFalse);
-
- } else {
- font = NULL;
- }
-
- return font;
-}
-
-XOutputFont *XOutputFontCache::tryGetTTFontFromFile(XRef *xref,
- GString *fileName,
- GBool deleteFile,
- GfxFont *gfxFont,
- double m11Orig,
- double m12Orig,
- double m21Orig,
- double m22Orig,
- double m11, double m12,
- double m21, double m22,
- GBool subst) {
- Ref *id;
- TTFontFile *fontFile;
- XOutputFont *font;
-
- // create the FreeType font file
- if (gfxFont->isCIDFont()) {
- // fontCIDType2
- fontFile = new TTFontFile(ttEngine, fileName->getCString(),
- ((GfxCIDFont *)gfxFont)->getCIDToGID(),
- ((GfxCIDFont *)gfxFont)->getCIDToGIDLen());
- } else {
- fontFile = new TTFontFile(ttEngine, fileName->getCString(),
- ((Gfx8BitFont *)gfxFont)->getEncoding(),
- ((Gfx8BitFont *)gfxFont)->getHasEncoding());
- }
- if (!fontFile->isOk()) {
- error(-1, "Couldn't create FreeType font from '%s'",
- fileName->getCString());
- delete fontFile;
- if (deleteFile) {
- unlink(fileName->getCString());
- }
- return NULL;
- }
-
- // add to list
- id = gfxFont->getID();
- ttFontFiles->append(new XOutputTTFontFile(id->num, id->gen,
- subst, fontFile,
- deleteFile ? fileName->copy()
- : (GString *)NULL));
-
- // create the Font
- font = new XOutputTTFont(gfxFont->getID(), fontFile,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22, display, xOut);
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
-}
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-XOutputFont *XOutputFontCache::tryGetServerFont(GString *xlfd,
- GString *encodingName,
- GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12,
- double m21, double m22) {
- XOutputFont *font;
- UnicodeMap *uMap;
- CharCodeToUnicode *ctu;
-
- uMap = globalParams->getUnicodeMap(encodingName);
- if (gfxFont->isCIDFont()) {
- ctu = ((GfxCIDFont *)gfxFont)->getToUnicode();
- font = new XOutputServer16BitFont(gfxFont->getID(), xlfd, uMap, ctu,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22,
- display, xOut);
- ctu->decRefCnt();
- } else {
- ctu = ((Gfx8BitFont *)gfxFont)->getToUnicode();
- font = new XOutputServer8BitFont(gfxFont->getID(), xlfd, uMap, ctu,
- m11Orig, m12Orig, m21Orig, m22Orig,
- m11, m12, m21, m22,
- display, xOut);
- ctu->decRefCnt();
- }
- uMap->decRefCnt();
- if (!font->isOk()) {
- delete font;
- return NULL;
- }
- return font;
-}
-
-//------------------------------------------------------------------------
-// T3FontCache
-//------------------------------------------------------------------------
-
-struct T3FontCacheTag {
- Gushort code;
- Gushort mru; // valid bit (0x8000) and MRU index
- double wx, wy; // untransformed glyph metrics
-};
-
-class T3FontCache {
-public:
-
- T3FontCache(Ref *fontID, double m11A, double m12A,
- double m21A, double m22A,
- int glyphXA, int glyphYA, int glyphWA, int glyphHA,
- Display *displayA, Visual *visual, Guint depth,
- Pixmap origPixmap);
- ~T3FontCache();
- GBool matches(Ref *idA, double m11A, double m12A,
- double m21A, double m22A)
- { return fontID.num == idA->num && fontID.gen == idA->gen &&
- m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; }
-
- Ref fontID; // PDF font ID
- double m11, m12, m21, m22; // transform matrix
- int glyphX, glyphY; // pixel offset of glyph pixmaps
- int glyphW, glyphH; // size of glyph pixmaps, in pixels
- int glyphSize; // size of glyph pixmaps, in bytes
- int cacheSets; // number of sets in cache
- int cacheAssoc; // cache associativity (glyphs per set)
- Guchar *cacheData; // glyph pixmap cache
- T3FontCacheTag *cacheTags; // cache tags, i.e., char codes
- Display *display;
- Pixmap pixmap;
- XImage *image;
-};
-
-T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
- double m21A, double m22A,
- int glyphXA, int glyphYA, int glyphWA, int glyphHA,
- Display *displayA, Visual *visual, Guint depth,
- Pixmap origPixmap) {
- int i;
-
- fontID = *fontIDA;
- m11 = m11A;
- m12 = m12A;
- m21 = m21A;
- m22 = m22A;
- glyphX = glyphXA;
- glyphY = glyphYA;
- glyphW = glyphWA;
- glyphH = glyphHA;
- glyphSize = glyphW * glyphH;
- cacheAssoc = 8;
- if (glyphSize <= 256) {
- cacheSets = 8;
- } else if (glyphSize <= 512) {
- cacheSets = 4;
- } else if (glyphSize <= 1024) {
- cacheSets = 2;
- } else {
- cacheSets = 1;
- }
- cacheData = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
- cacheTags = (T3FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
- sizeof(T3FontCacheTag));
- for (i = 0; i < cacheSets * cacheAssoc; ++i) {
- cacheTags[i].mru = i & (cacheAssoc - 1);
- }
- display = displayA;
- pixmap = XCreatePixmap(display, origPixmap, glyphW, glyphH, depth);
- image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL,
- glyphW, glyphH, 8, 0);
- image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
-}
-
-T3FontCache::~T3FontCache() {
- gfree(cacheData);
- gfree(cacheTags);
- XFreePixmap(display, pixmap);
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
-}
-
-struct T3GlyphStack {
- GBool cacheable;
- Gushort code;
- T3FontCache *cache;
- int cacheIdx;
- T3FontCacheTag *cacheTag;
- Guchar *cacheData;
- double x, y;
- Unicode *u;
- int uLen;
- GfxRGB color;
- int origPixmapW, origPixmapH;
- Pixmap origPixmap;
- GC origStrokeGC;
- GC origFillGC;
- Region origClipRegion;
- double origCTM4, origCTM5;
- double wx, wy; // untransformed glyph metrics
- T3GlyphStack *next;
-};
-
-//------------------------------------------------------------------------
-// XOutputDev
-//------------------------------------------------------------------------
-
-XOutputDev::XOutputDev(Display *displayA, int screenNumA,
- Visual *visualA, Colormap colormapA,
- GBool reverseVideoA, unsigned long paperColorA,
- GBool installCmap, int rgbCubeSize,
- int forceDepth) {
- XVisualInfo visualTempl;
- XVisualInfo *visualList;
- int nVisuals;
- Gulong mask;
- XColor xcolor;
- XColor *xcolors;
- int r, g, b, n, m;
- GBool ok;
-
- // no document yet
- xref = NULL;
-
- // display / screen / visual / colormap
- display = displayA;
- screenNum = screenNumA;
- visual = visualA;
- colormap = colormapA;
-
- // no pixmap yet
- pixmapW = pixmapH = 0;
-
- // check for TrueColor visual
- if (forceDepth != 0) {
- depth = forceDepth;
- trueColor = depth >= 16;
- } else {
- visualTempl.visualid = XVisualIDFromVisual(visual);
- visualList = XGetVisualInfo(display, VisualIDMask,
- &visualTempl, &nVisuals);
- if (nVisuals < 1) {
- // this shouldn't happen
- XFree((XPointer)visualList);
- visualList = XGetVisualInfo(display, VisualNoMask, &visualTempl,
- &nVisuals);
- }
- depth = visualList->depth;
- if (visualList->c_class == TrueColor) {
- trueColor = gTrue;
- for (mask = visualList->red_mask, rShift = 0;
- mask && !(mask & 1);
- mask >>= 1, ++rShift) ;
- rMul = (int)mask;
- for (mask = visualList->green_mask, gShift = 0;
- mask && !(mask & 1);
- mask >>= 1, ++gShift) ;
- gMul = (int)mask;
- for (mask = visualList->blue_mask, bShift = 0;
- mask && !(mask & 1);
- mask >>= 1, ++bShift) ;
- bMul = (int)mask;
- } else {
- trueColor = gFalse;
- }
- XFree((XPointer)visualList);
- }
-
- // allocate a color cube
- if (!trueColor) {
- redMap[BlackPixel(display, screenNum) & 0xff] = 0;
- redMap[WhitePixel(display, screenNum) & 0xff] = 1;
-
- // set colors in private colormap
- if (installCmap) {
- for (numColors = 6; numColors >= 2; --numColors) {
- m = numColors * numColors * numColors;
- if (XAllocColorCells(display, colormap, False, NULL, 0, colors, m)) {
- break;
- }
- }
- if (numColors >= 2) {
- m = numColors * numColors * numColors;
- xcolors = (XColor *)gmalloc(m * sizeof(XColor));
- n = 0;
- for (r = 0; r < numColors; ++r) {
- for (g = 0; g < numColors; ++g) {
- for (b = 0; b < numColors; ++b) {
- xcolors[n].pixel = colors[n];
- xcolors[n].red = (r * 65535) / (numColors - 1);
- xcolors[n].green = (g * 65535) / (numColors - 1);
- xcolors[n].blue = (b * 65535) / (numColors - 1);
- xcolors[n].flags = DoRed | DoGreen | DoBlue;
- redMap[xcolors[n].pixel & 0xff] = xcolors[n].red / 65535.0;
- ++n;
- }
- }
- }
- XStoreColors(display, colormap, xcolors, m);
- gfree(xcolors);
- } else {
- numColors = 1;
- colors[0] = BlackPixel(display, screenNum);
- colors[1] = WhitePixel(display, screenNum);
- }
-
- // allocate colors in shared colormap
- } else {
- if (rgbCubeSize > maxRGBCube) {
- rgbCubeSize = maxRGBCube;
- }
- ok = gFalse;
- for (numColors = rgbCubeSize; numColors >= 2; --numColors) {
- ok = gTrue;
- n = 0;
- for (r = 0; r < numColors && ok; ++r) {
- for (g = 0; g < numColors && ok; ++g) {
- for (b = 0; b < numColors && ok; ++b) {
- if (n == 0) {
- colors[n] = BlackPixel(display, screenNum);
- redMap[colors[n] & 0xff] = 0;
- ++n;
- } else {
- xcolor.red = (r * 65535) / (numColors - 1);
- xcolor.green = (g * 65535) / (numColors - 1);
- xcolor.blue = (b * 65535) / (numColors - 1);
- if (XAllocColor(display, colormap, &xcolor)) {
- colors[n++] = xcolor.pixel;
- redMap[xcolor.pixel & 0xff] = xcolor.red / 65535.0;
- } else {
- ok = gFalse;
- }
- }
- }
- }
- }
- if (ok) {
- break;
- }
- XFreeColors(display, colormap, &colors[1], n-1, 0);
- }
- if (!ok) {
- numColors = 1;
- colors[0] = BlackPixel(display, screenNum);
- colors[1] = WhitePixel(display, screenNum);
- }
- }
- }
-
- // misc parameters
- reverseVideo = reverseVideoA;
- paperColor = paperColorA;
-
- // set up the font cache and fonts
- gfxFont = NULL;
- font = NULL;
- needFontUpdate = gFalse;
- fontCache = new XOutputFontCache(display, depth, this,
- globalParams->getT1libControl(),
- globalParams->getFreeTypeControl());
- nT3Fonts = 0;
- t3GlyphStack = NULL;
-
- // no text outline clipping path
- textClipPath = NULL;
-
- // empty state stack
- save = NULL;
-
- // create text object
- text = new TextPage(gFalse);
-}
-
-XOutputDev::~XOutputDev() {
- int i;
-
- delete fontCache;
- for (i = 0; i < nT3Fonts; ++i) {
- delete t3FontCache[i];
- }
- delete text;
-}
-
-void XOutputDev::startDoc(XRef *xrefA) {
- int i;
-
- xref = xrefA;
- fontCache->startDoc(screenNum, visual, colormap, trueColor, rMul, gMul, bMul,
- rShift, gShift, bShift, colors, numColors);
- for (i = 0; i < nT3Fonts; ++i) {
- delete t3FontCache[i];
- }
- nT3Fonts = 0;
-}
-
-void XOutputDev::startPage(int pageNum, GfxState *state) {
- XGCValues gcValues;
- XRectangle rect;
-
- // default line flatness
- flatness = 0;
-
- // allocate GCs
- gcValues.foreground = BlackPixel(display, screenNum);
- gcValues.background = WhitePixel(display, screenNum);
- gcValues.line_width = 0;
- gcValues.line_style = LineSolid;
- strokeGC = XCreateGC(display, pixmap,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
- fillGC = XCreateGC(display, pixmap,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
- gcValues.foreground = paperColor;
- paperGC = XCreateGC(display, pixmap,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
-
- // initialize clip region
- clipRegion = XCreateRegion();
- rect.x = rect.y = 0;
- rect.width = pixmapW;
- rect.height = pixmapH;
- XUnionRectWithRegion(&rect, clipRegion, clipRegion);
- XSetRegion(display, strokeGC, clipRegion);
- XSetRegion(display, fillGC, clipRegion);
-
- // clear font
- gfxFont = NULL;
- font = NULL;
-
- // clear window
- XFillRectangle(display, pixmap, paperGC, 0, 0, pixmapW, pixmapH);
-
- // clear text object
- text->startPage(state);
-}
-
-void XOutputDev::endPage() {
- XOutputState *s;
-
- text->coalesce(gTrue);
-
- // clear state stack, free all GCs, free the clip region
- while (save) {
- s = save;
- save = save->next;
- XFreeGC(display, s->strokeGC);
- XFreeGC(display, s->fillGC);
- XDestroyRegion(s->clipRegion);
- delete s;
- }
- XFreeGC(display, strokeGC);
- XFreeGC(display, fillGC);
- XFreeGC(display, paperGC);
- XDestroyRegion(clipRegion);
-}
-
-void XOutputDev::drawLink(Link *link, Catalog *catalog) {
- double x1, y1, x2, y2;
- LinkBorderStyle *borderStyle;
- GfxRGB rgb;
- double *dash;
- char dashList[20];
- int dashLength;
- XPoint points[5];
- int x, y, i;
-
- link->getRect(&x1, &y1, &x2, &y2);
- borderStyle = link->getBorderStyle();
- if (borderStyle->getWidth() > 0) {
- borderStyle->getColor(&rgb.r, &rgb.g, &rgb.b);
- XSetForeground(display, strokeGC, findColor(&rgb));
- borderStyle->getDash(&dash, &dashLength);
- if (borderStyle->getType() == linkBorderDashed && dashLength > 0) {
- if (dashLength > 20) {
- dashLength = 20;
- }
- for (i = 0; i < dashLength; ++i) {
- if ((dashList[i] = xoutRound(dash[i])) == 0) {
- dashList[i] = 1;
- }
- }
- XSetLineAttributes(display, strokeGC, xoutRound(borderStyle->getWidth()),
- LineOnOffDash, CapButt, JoinMiter);
- XSetDashes(display, strokeGC, 0, dashList, dashLength);
- } else {
- XSetLineAttributes(display, strokeGC, xoutRound(borderStyle->getWidth()),
- LineSolid, CapButt, JoinMiter);
- }
- if (borderStyle->getType() == linkBorderUnderlined) {
- cvtUserToDev(x1, y1, &x, &y);
- points[0].x = x;
- points[0].y = y;
- cvtUserToDev(x2, y1, &x, &y);
- points[1].x = x;
- points[1].y = y;
- XDrawLine(display, pixmap, strokeGC, points[0].x, points[0].y,
- points[1].x, points[1].y);
- } else {
- cvtUserToDev(x1, y1, &x, &y);
- points[0].x = points[4].x = x;
- points[0].y = points[4].y = y;
- cvtUserToDev(x2, y1, &x, &y);
- points[1].x = x;
- points[1].y = y;
- cvtUserToDev(x2, y2, &x, &y);
- points[2].x = x;
- points[2].y = y;
- cvtUserToDev(x1, y2, &x, &y);
- points[3].x = x;
- points[3].y = y;
- XDrawLines(display, pixmap, strokeGC, points, 5, CoordModeOrigin);
- }
- }
-}
-
-void XOutputDev::saveState(GfxState *state) {
- XOutputState *s;
- XGCValues values;
-
- // save current state
- s = new XOutputState;
- s->strokeGC = strokeGC;
- s->fillGC = fillGC;
- s->clipRegion = clipRegion;
-
- // push onto state stack
- s->next = save;
- save = s;
-
- // create a new current state by copying
- strokeGC = XCreateGC(display, pixmap, 0, &values);
- XCopyGC(display, s->strokeGC, 0xffffffff, strokeGC);
- fillGC = XCreateGC(display, pixmap, 0, &values);
- XCopyGC(display, s->fillGC, 0xffffffff, fillGC);
- clipRegion = XCreateRegion();
- XUnionRegion(s->clipRegion, clipRegion, clipRegion);
- XSetRegion(display, strokeGC, clipRegion);
- XSetRegion(display, fillGC, clipRegion);
-}
-
-void XOutputDev::restoreState(GfxState *state) {
- XOutputState *s;
-
- if (save) {
- // kill current state
- XFreeGC(display, strokeGC);
- XFreeGC(display, fillGC);
- XDestroyRegion(clipRegion);
-
- // restore state
- flatness = state->getFlatness();
- strokeGC = save->strokeGC;
- fillGC = save->fillGC;
- clipRegion = save->clipRegion;
- XSetRegion(display, strokeGC, clipRegion);
- XSetRegion(display, fillGC, clipRegion);
-
- // pop state stack
- s = save;
- save = save->next;
- delete s;
-
- // we'll need to restore the font
- needFontUpdate = gTrue;
- }
-}
-
-void XOutputDev::updateAll(GfxState *state) {
- updateLineAttrs(state, gTrue);
- updateFlatness(state);
- updateMiterLimit(state);
- updateFillColor(state);
- updateStrokeColor(state);
- needFontUpdate = gTrue;
-}
-
-void XOutputDev::updateCTM(GfxState *state, double m11, double m12,
- double m21, double m22, double m31, double m32) {
- updateLineAttrs(state, gTrue);
-}
-
-void XOutputDev::updateLineDash(GfxState *state) {
- updateLineAttrs(state, gTrue);
-}
-
-void XOutputDev::updateFlatness(GfxState *state) {
- flatness = state->getFlatness();
-}
-
-void XOutputDev::updateLineJoin(GfxState *state) {
- updateLineAttrs(state, gFalse);
-}
-
-void XOutputDev::updateLineCap(GfxState *state) {
- updateLineAttrs(state, gFalse);
-}
-
-// unimplemented
-void XOutputDev::updateMiterLimit(GfxState *state) {
-}
-
-void XOutputDev::updateLineWidth(GfxState *state) {
- updateLineAttrs(state, gFalse);
-}
-
-void XOutputDev::updateLineAttrs(GfxState *state, GBool updateDash) {
- double width;
- int cap, join;
- double *dashPattern;
- int dashLength;
- double dashStart;
- char dashList[20];
- int i;
-
- width = state->getTransformedLineWidth();
- switch (state->getLineCap()) {
- case 0: cap = CapButt; break;
- case 1: cap = CapRound; break;
- case 2: cap = CapProjecting; break;
- default:
- error(-1, "Bad line cap style (%d)", state->getLineCap());
- cap = CapButt;
- break;
- }
- switch (state->getLineJoin()) {
- case 0: join = JoinMiter; break;
- case 1: join = JoinRound; break;
- case 2: join = JoinBevel; break;
- default:
- error(-1, "Bad line join style (%d)", state->getLineJoin());
- join = JoinMiter;
- break;
- }
- state->getLineDash(&dashPattern, &dashLength, &dashStart);
-#if 1 //~ work around a bug in XFree86 (???)
- if (dashLength > 0 && cap == CapProjecting) {
- cap = CapButt;
- }
-#endif
- XSetLineAttributes(display, strokeGC, xoutRound(width),
- dashLength > 0 ? LineOnOffDash : LineSolid,
- cap, join);
- if (updateDash && dashLength > 0) {
- if (dashLength > 20)
- dashLength = 20;
- for (i = 0; i < dashLength; ++i) {
- dashList[i] = xoutRound(state->transformWidth(dashPattern[i]));
- if (dashList[i] == 0)
- dashList[i] = 1;
- }
- XSetDashes(display, strokeGC, xoutRound(dashStart), dashList, dashLength);
- }
-}
-
-void XOutputDev::updateFillColor(GfxState *state) {
- GfxRGB rgb;
-
- state->getFillRGB(&rgb);
- if (reverseVideo) {
- rgb.r = 1 - rgb.r;
- rgb.g = 1 - rgb.g;
- rgb.b = 1 - rgb.b;
- }
- XSetForeground(display, fillGC, findColor(&rgb));
-}
-
-void XOutputDev::updateStrokeColor(GfxState *state) {
- GfxRGB rgb;
-
- state->getStrokeRGB(&rgb);
- if (reverseVideo) {
- rgb.r = 1 - rgb.r;
- rgb.g = 1 - rgb.g;
- rgb.b = 1 - rgb.b;
- }
- XSetForeground(display, strokeGC, findColor(&rgb));
-}
-
-void XOutputDev::updateFont(GfxState *state) {
- double m11, m12, m21, m22;
-
- needFontUpdate = gFalse;
-
- text->updateFont(state);
-
- if (!(gfxFont = state->getFont())) {
- font = NULL;
- return;
- }
- if (gfxFont->getType() == fontType3) {
- font = NULL;
- return;
- }
- state->getFontTransMat(&m11, &m12, &m21, &m22);
- m11 *= state->getHorizScaling();
- m12 *= state->getHorizScaling();
- font = fontCache->getFont(xref, gfxFont, m11, m12, m21, m22);
- if (font) {
- font->updateGC(fillGC);
- font->updateGC(strokeGC);
- }
-}
-
-void XOutputDev::stroke(GfxState *state) {
- XPoint *points;
- int *lengths;
- int n, size, numPoints, i, j;
-
- // transform points
- n = convertPath(state, state->getPath(),
- &points, &size, &numPoints, &lengths, gFalse);
-
- // draw each subpath
- j = 0;
- for (i = 0; i < n; ++i) {
- XDrawLines(display, pixmap, strokeGC, points + j, lengths[i],
- CoordModeOrigin);
- j += lengths[i];
- }
-
- // free points and lengths arrays
- if (points != tmpPoints)
- gfree(points);
- if (lengths != tmpLengths)
- gfree(lengths);
-}
-
-void XOutputDev::fill(GfxState *state) {
- doFill(state, WindingRule);
-}
-
-void XOutputDev::eoFill(GfxState *state) {
- doFill(state, EvenOddRule);
-}
-
-//
-// X doesn't color the pixels on the right-most and bottom-most
-// borders of a polygon. This means that one-pixel-thick polygons
-// are not colored at all. I think this is supposed to be a
-// feature, but I can't figure out why. So after it fills a
-// polygon, it also draws lines around the border. This is done
-// only for single-component polygons, since it's not very
-// compatible with the compound polygon kludge (see convertPath()).
-//
-void XOutputDev::doFill(GfxState *state, int rule) {
- XPoint *points;
- int *lengths;
- int n, size, numPoints, i, j;
-
- // set fill rule
- XSetFillRule(display, fillGC, rule);
-
- // transform points, build separate polygons
- n = convertPath(state, state->getPath(),
- &points, &size, &numPoints, &lengths, gTrue);
-
- // fill them
- j = 0;
- for (i = 0; i < n; ++i) {
- XFillPolygon(display, pixmap, fillGC, points + j, lengths[i],
- Complex, CoordModeOrigin);
- if (state->getPath()->getNumSubpaths() == 1) {
- XDrawLines(display, pixmap, fillGC, points + j, lengths[i],
- CoordModeOrigin);
- }
- j += lengths[i] + 1;
- }
-
- // free points and lengths arrays
- if (points != tmpPoints)
- gfree(points);
- if (lengths != tmpLengths)
- gfree(lengths);
-}
-
-void XOutputDev::clip(GfxState *state) {
- doClip(state, state->getPath(), WindingRule);
-}
-
-void XOutputDev::eoClip(GfxState *state) {
- doClip(state, state->getPath(), EvenOddRule);
-}
-
-void XOutputDev::doClip(GfxState *state, GfxPath *path, int rule) {
- GfxSubpath *subpath;
- Region region, region2;
- XPoint rect[5];
- XPoint *points;
- int *lengths;
- double x0, y0, x1, y1, x2, y2, x3, y3;
- GBool gotRect;
- int n, size, numPoints, i, j;
-
- // special case for rectangular clipping paths -- this is a common
- // case, and we want to make sure not to clip an extra pixel on the
- // right and bottom edges due to the difference between the PDF and
- // X rendering models
- gotRect = gFalse;
- if (path->getNumSubpaths() == 1) {
- subpath = path->getSubpath(0);
- if ((subpath->isClosed() && subpath->getNumPoints() == 5) ||
- (!subpath->isClosed() && subpath->getNumPoints() == 4)) {
- state->transform(subpath->getX(0), subpath->getY(0), &x0, &y0);
- state->transform(subpath->getX(1), subpath->getY(1), &x1, &y1);
- state->transform(subpath->getX(2), subpath->getY(2), &x2, &y2);
- state->transform(subpath->getX(3), subpath->getY(3), &x3, &y3);
- if (fabs(x0-x1) < 1 && fabs(x2-x3) < 1 &&
- fabs(y0-y3) < 1 && fabs(y1-y2) < 1) {
- if (x0 < x2) {
- rect[0].x = rect[1].x = rect[4].x = (int)floor(x0);
- rect[2].x = rect[3].x = (int)floor(x2) + 1;
- } else {
- rect[0].x = rect[1].x = rect[4].x = (int)floor(x0) + 1;
- rect[2].x = rect[3].x = (int)floor(x2);
- }
- if (y0 < y1) {
- rect[0].y = rect[3].y = rect[4].y = (int)floor(y0);
- rect[1].y = rect[2].y = (int)floor(y1) + 1;
- } else {
- rect[0].y = rect[3].y = rect[4].y = (int)floor(y0) + 1;
- rect[1].y = rect[2].y = (int)floor(y1);
- }
- gotRect = gTrue;
- } else if (fabs(x0-x3) < 1 && fabs(x1-x2) < 1 &&
- fabs(y0-y1) < 1 && fabs(y2-y3) < 1) {
- if (x0 < x1) {
- rect[0].x = rect[3].x = rect[4].x = (int)floor(x0);
- rect[1].x = rect[2].x = (int)floor(x1) + 1;
- } else {
- rect[0].x = rect[3].x = rect[4].x = (int)floor(x0) + 1;
- rect[1].x = rect[2].x = (int)floor(x1);
- }
- if (y0 < y2) {
- rect[0].y = rect[1].y = rect[4].y = (int)floor(y0);
- rect[2].y = rect[3].y = (int)floor(y2) + 1;
- } else {
- rect[0].y = rect[1].y = rect[4].y = (int)floor(y0) + 1;
- rect[2].y = rect[3].y = (int)floor(y2);
- }
- gotRect = gTrue;
- }
- }
- }
-
- if (gotRect) {
- region = XPolygonRegion(rect, 5, EvenOddRule);
-
- } else {
- // transform points, build separate polygons
- n = convertPath(state, path, &points, &size, &numPoints, &lengths, gTrue);
-
- // construct union of subpath regions
- // (XPolygonRegion chokes if there aren't at least three points --
- // this happens if the PDF file does moveto/closepath/clip, which
- // sets an empty clipping region)
- if (lengths[0] > 2) {
- region = XPolygonRegion(points, lengths[0], rule);
- } else {
- region = XCreateRegion();
- }
- j = lengths[0] + 1;
- for (i = 1; i < n; ++i) {
- if (lengths[i] > 2) {
- region2 = XPolygonRegion(points + j, lengths[i], rule);
- } else {
- region2 = XCreateRegion();
- }
- XUnionRegion(region2, region, region);
- XDestroyRegion(region2);
- j += lengths[i] + 1;
- }
-
- // free points and lengths arrays
- if (points != tmpPoints) {
- gfree(points);
- }
- if (lengths != tmpLengths) {
- gfree(lengths);
- }
- }
-
- // intersect region with clipping region
- XIntersectRegion(region, clipRegion, clipRegion);
- XDestroyRegion(region);
- XSetRegion(display, strokeGC, clipRegion);
- XSetRegion(display, fillGC, clipRegion);
-}
-
-//
-// Transform points in the path and convert curves to line segments.
-// Builds a set of subpaths and returns the number of subpaths.
-// If <fillHack> is set, close any unclosed subpaths and activate a
-// kludge for polygon fills: First, it divides up the subpaths into
-// non-overlapping polygons by simply comparing bounding rectangles.
-// Then it connects subaths within a single compound polygon to a single
-// point so that X can fill the polygon (sort of).
-//
-int XOutputDev::convertPath(GfxState *state, GfxPath *path,
- XPoint **points, int *size,
- int *numPoints, int **lengths, GBool fillHack) {
- BoundingRect *rects;
- BoundingRect rect;
- int n, i, ii, j, k, k0;
-
- // get path and number of subpaths
- n = path->getNumSubpaths();
-
- // allocate lengths array
- if (n < numTmpSubpaths)
- *lengths = tmpLengths;
- else
- *lengths = (int *)gmalloc(n * sizeof(int));
-
- // allocate bounding rectangles array
- if (fillHack) {
- if (n < numTmpSubpaths)
- rects = tmpRects;
- else
- rects = (BoundingRect *)gmalloc(n * sizeof(BoundingRect));
- } else {
- rects = NULL;
- }
-
- // do each subpath
- *points = tmpPoints;
- *size = numTmpPoints;
- *numPoints = 0;
- for (i = 0; i < n; ++i) {
-
- // transform the points
- j = *numPoints;
- convertSubpath(state, path->getSubpath(i), points, size, numPoints);
-
- // construct bounding rectangle
- if (fillHack) {
- rects[i].xMin = rects[i].xMax = (*points)[j].x;
- rects[i].yMin = rects[i].yMax = (*points)[j].y;
- for (k = j + 1; k < *numPoints; ++k) {
- if ((*points)[k].x < rects[i].xMin)
- rects[i].xMin = (*points)[k].x;
- else if ((*points)[k].x > rects[i].xMax)
- rects[i].xMax = (*points)[k].x;
- if ((*points)[k].y < rects[i].yMin)
- rects[i].yMin = (*points)[k].y;
- else if ((*points)[k].y > rects[i].yMax)
- rects[i].yMax = (*points)[k].y;
- }
- }
-
- // close subpath if necessary
- if (fillHack && ((*points)[*numPoints-1].x != (*points)[j].x ||
- (*points)[*numPoints-1].y != (*points)[j].y)) {
- addPoint(points, size, numPoints, (*points)[j].x, (*points)[j].y);
- }
-
- // length of this subpath
- (*lengths)[i] = *numPoints - j;
-
- // leave an extra point for compound fill hack
- if (fillHack)
- addPoint(points, size, numPoints, 0, 0);
- }
-
- // kludge: munge any points that are *way* out of bounds - these can
- // crash certain (buggy) X servers
- for (i = 0; i < *numPoints; ++i) {
- if ((*points)[i].x < -4 * pixmapW) {
- (*points)[i].x = -4 * pixmapW;
- } else if ((*points)[i].x > 4 * pixmapW) {
- (*points)[i].x = 4 * pixmapW;
- }
- if ((*points)[i].y < -pixmapH) {
- (*points)[i].y = -4 * pixmapH;
- } else if ((*points)[i].y > 4 * pixmapH) {
- (*points)[i].y = 4 * pixmapH;
- }
- }
-
- // combine compound polygons
- if (fillHack) {
- i = j = k = 0;
- while (i < n) {
-
- // start with subpath i
- rect = rects[i];
- (*lengths)[j] = (*lengths)[i];
- k0 = k;
- (*points)[k + (*lengths)[i]] = (*points)[k0];
- k += (*lengths)[i] + 1;
- ++i;
-
- // combine overlapping polygons
- do {
-
- // look for the first subsequent subpath, if any, which overlaps
- for (ii = i; ii < n; ++ii) {
- if (rects[ii].xMax > rects[i].xMin &&
- rects[ii].xMin < rects[i].xMax &&
- rects[ii].yMax > rects[i].yMin &&
- rects[ii].yMin < rects[i].yMax) {
- break;
- }
- }
-
- // if there is an overlap, combine the polygons
- if (ii < n) {
- for (; i <= ii; ++i) {
- if (rects[i].xMin < rect.xMin)
- rect.xMin = rects[j].xMin;
- if (rects[i].xMax > rect.xMax)
- rect.xMax = rects[j].xMax;
- if (rects[i].yMin < rect.yMin)
- rect.yMin = rects[j].yMin;
- if (rects[i].yMax > rect.yMax)
- rect.yMax = rects[j].yMax;
- (*lengths)[j] += (*lengths)[i] + 1;
- (*points)[k + (*lengths)[i]] = (*points)[k0];
- k += (*lengths)[i] + 1;
- }
- }
- } while (ii < n && i < n);
-
- ++j;
- }
-
- // free bounding rectangles
- if (rects != tmpRects)
- gfree(rects);
-
- n = j;
- }
-
- return n;
-}
-
-//
-// Transform points in a single subpath and convert curves to line
-// segments.
-//
-void XOutputDev::convertSubpath(GfxState *state, GfxSubpath *subpath,
- XPoint **points, int *size, int *n) {
- double x0, y0, x1, y1, x2, y2, x3, y3;
- int m, i;
-
- m = subpath->getNumPoints();
- i = 0;
- while (i < m) {
- if (i >= 1 && subpath->getCurve(i)) {
- state->transform(subpath->getX(i-1), subpath->getY(i-1), &x0, &y0);
- state->transform(subpath->getX(i), subpath->getY(i), &x1, &y1);
- state->transform(subpath->getX(i+1), subpath->getY(i+1), &x2, &y2);
- state->transform(subpath->getX(i+2), subpath->getY(i+2), &x3, &y3);
- doCurve(points, size, n, x0, y0, x1, y1, x2, y2, x3, y3);
- i += 3;
- } else {
- state->transform(subpath->getX(i), subpath->getY(i), &x1, &y1);
- addPoint(points, size, n, xoutRound(x1), xoutRound(y1));
- ++i;
- }
- }
-}
-
-//
-// Subdivide a Bezier curve. This uses floating point to avoid
-// propagating rounding errors. (The curves look noticeably more
-// jagged with integer arithmetic.)
-//
-void XOutputDev::doCurve(XPoint **points, int *size, int *n,
- double x0, double y0, double x1, double y1,
- double x2, double y2, double x3, double y3) {
- double x[(1<<maxCurveSplits)+1][3];
- double y[(1<<maxCurveSplits)+1][3];
- int next[1<<maxCurveSplits];
- int p1, p2, p3;
- double xx1, yy1, xx2, yy2;
- double dx, dy, mx, my, d1, d2;
- double xl0, yl0, xl1, yl1, xl2, yl2;
- double xr0, yr0, xr1, yr1, xr2, yr2, xr3, yr3;
- double xh, yh;
- double flat;
-
- flat = (double)(flatness * flatness);
- if (flat < 1)
- flat = 1;
-
- // initial segment
- p1 = 0;
- p2 = 1<<maxCurveSplits;
- x[p1][0] = x0; y[p1][0] = y0;
- x[p1][1] = x1; y[p1][1] = y1;
- x[p1][2] = x2; y[p1][2] = y2;
- x[p2][0] = x3; y[p2][0] = y3;
- next[p1] = p2;
-
- while (p1 < (1<<maxCurveSplits)) {
-
- // get next segment
- xl0 = x[p1][0]; yl0 = y[p1][0];
- xx1 = x[p1][1]; yy1 = y[p1][1];
- xx2 = x[p1][2]; yy2 = y[p1][2];
- p2 = next[p1];
- xr3 = x[p2][0]; yr3 = y[p2][0];
-
- // compute distances from control points to midpoint of the
- // straight line (this is a bit of a hack, but it's much faster
- // than computing the actual distances to the line)
- mx = (xl0 + xr3) * 0.5;
- my = (yl0 + yr3) * 0.5;
- dx = xx1 - mx;
- dy = yy1 - my;
- d1 = dx*dx + dy*dy;
- dx = xx2 - mx;
- dy = yy2 - my;
- d2 = dx*dx + dy*dy;
-
- // if curve is flat enough, or no more divisions allowed then
- // add the straight line segment
- if (p2 - p1 <= 1 || (d1 <= flat && d2 <= flat)) {
- addPoint(points, size, n, xoutRound(xr3), xoutRound(yr3));
- p1 = p2;
-
- // otherwise, subdivide the curve
- } else {
- xl1 = (xl0 + xx1) * 0.5;
- yl1 = (yl0 + yy1) * 0.5;
- xh = (xx1 + xx2) * 0.5;
- yh = (yy1 + yy2) * 0.5;
- xl2 = (xl1 + xh) * 0.5;
- yl2 = (yl1 + yh) * 0.5;
- xr2 = (xx2 + xr3) * 0.5;
- yr2 = (yy2 + yr3) * 0.5;
- xr1 = (xh + xr2) * 0.5;
- yr1 = (yh + yr2) * 0.5;
- xr0 = (xl2 + xr1) * 0.5;
- yr0 = (yl2 + yr1) * 0.5;
-
- // add the new subdivision points
- p3 = (p1 + p2) / 2;
- x[p1][1] = xl1; y[p1][1] = yl1;
- x[p1][2] = xl2; y[p1][2] = yl2;
- next[p1] = p3;
- x[p3][0] = xr0; y[p3][0] = yr0;
- x[p3][1] = xr1; y[p3][1] = yr1;
- x[p3][2] = xr2; y[p3][2] = yr2;
- next[p3] = p2;
- }
- }
-}
-
-//
-// Add a point to the points array. (This would use a generic resizable
-// array type if C++ supported parameterized types in some reasonable
-// way -- templates are a disgusting kludge.)
-//
-void XOutputDev::addPoint(XPoint **points, int *size, int *k, int x, int y) {
- if (*k >= *size) {
- *size += 32;
- if (*points == tmpPoints) {
- *points = (XPoint *)gmalloc(*size * sizeof(XPoint));
- memcpy(*points, tmpPoints, *k * sizeof(XPoint));
- } else {
- *points = (XPoint *)grealloc(*points, *size * sizeof(XPoint));
- }
- }
- (*points)[*k].x = x;
- (*points)[*k].y = y;
- ++(*k);
-}
-
-void XOutputDev::beginString(GfxState *state, GString *s) {
- text->beginWord(state, state->getCurX(), state->getCurY());
-}
-
-void XOutputDev::endString(GfxState *state) {
- text->endWord();
-}
-
-void XOutputDev::drawChar(GfxState *state, double x, double y,
- double dx, double dy,
- double originX, double originY,
- CharCode code, Unicode *u, int uLen) {
- int render;
- double x1, y1, dx1, dy1;
- GfxRGB rgb;
- double saveCurX, saveCurY;
- double *ctm;
- double saveCTM[6];
-
- if (needFontUpdate) {
- updateFont(state);
- }
-
- text->addChar(state, x, y, dx, dy, code, u, uLen);
-
- if (!font) {
- return;
- }
-
- // check for invisible text -- this is used by Acrobat Capture
- render = state->getRender();
- if (render == 3) {
- return;
- }
-
- x -= originX;
- y -= originY;
- state->transform(x, y, &x1, &y1);
- state->transformDelta(dx, dy, &dx1, &dy1);
-
- // fill
- if (!(render & 1)) {
- state->getFillRGB(&rgb);
- if (reverseVideo) {
- rgb.r = 1 - rgb.r;
- rgb.g = 1 - rgb.g;
- rgb.b = 1 - rgb.b;
- }
- font->drawChar(state, pixmap, pixmapW, pixmapH, fillGC, &rgb,
- x1, y1, dx1, dy1, code, u, uLen);
- }
-
- // stroke
- if ((render & 3) == 1 || (render & 3) == 2) {
- if (font->hasGetCharPath()) {
- saveCurX = state->getCurX();
- saveCurY = state->getCurY();
- ctm = state->getCTM();
- memcpy(saveCTM, ctm, 6 * sizeof(double));
- state->setCTM(1, 0, 0, 1, x1, y1);
- font->getCharPath(state, code, u, uLen);
- stroke(state);
- state->clearPath();
- state->setCTM(saveCTM[0], saveCTM[1], saveCTM[2], saveCTM[3],
- saveCTM[4], saveCTM[5]);
- state->moveTo(saveCurX, saveCurY);
- } else {
- // can't stroke the outline, so just fill it using the stroke
- // color
- state->getStrokeRGB(&rgb);
- if (reverseVideo) {
- rgb.r = 1 - rgb.r;
- rgb.g = 1 - rgb.g;
- rgb.b = 1 - rgb.b;
- }
- font->drawChar(state, pixmap, pixmapW, pixmapH, strokeGC, &rgb,
- x1, y1, dx1, dy1, code, u, uLen);
- }
- }
-
- // clip
- if (render & 4) {
- if (font->hasGetCharPath()) {
- saveCurX = state->getCurX();
- saveCurY = state->getCurY();
- font->getCharPath(state, code, u, uLen);
- state->getPath()->offset(x1, y1);
- if (textClipPath) {
- textClipPath->append(state->getPath());
- } else {
- textClipPath = state->getPath()->copy();
- }
- state->clearPath();
- state->moveTo(saveCurX, saveCurY);
- }
- }
-}
-
-GBool XOutputDev::beginType3Char(GfxState *state,
- CharCode code, Unicode *u, int uLen) {
- Ref *fontID;
- double *ctm, *bbox;
- GfxRGB color;
- T3FontCache *t3Font;
- T3GlyphStack *t3gs;
- double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
- int i, j;
-
- if (needFontUpdate) {
- updateFont(state);
- }
- if (!gfxFont) {
- return gFalse;
- }
- fontID = gfxFont->getID();
- ctm = state->getCTM();
- state->transform(0, 0, &xt, &yt);
-
- // is it the first (MRU) font in the cache?
- if (!(nT3Fonts > 0 &&
- t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) {
-
- // is the font elsewhere in the cache?
- for (i = 1; i < nT3Fonts; ++i) {
- if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) {
- t3Font = t3FontCache[i];
- for (j = i; j > 0; --j) {
- t3FontCache[j] = t3FontCache[j - 1];
- }
- t3FontCache[0] = t3Font;
- break;
- }
- }
- if (i >= nT3Fonts) {
-
- // create new entry in the font cache
- if (nT3Fonts == xOutT3FontCacheSize) {
- delete t3FontCache[nT3Fonts - 1];
- --nT3Fonts;
- }
- for (j = nT3Fonts; j > 0; --j) {
- t3FontCache[j] = t3FontCache[j - 1];
- }
- ++nT3Fonts;
- bbox = gfxFont->getFontBBox();
- if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) {
- // broken bounding box -- just take a guess
- xMin = xt - 5;
- xMax = xMin + 30;
- yMax = yt + 15;
- yMin = yMax - 45;
- } else {
- state->transform(bbox[0], bbox[1], &x1, &y1);
- xMin = xMax = x1;
- yMin = yMax = y1;
- state->transform(bbox[0], bbox[3], &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(bbox[2], bbox[1], &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(bbox[2], bbox[3], &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- }
- t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
- (int)floor(xMin - xt),
- (int)floor(yMin - yt),
- (int)ceil(xMax) - (int)floor(xMin) + 3,
- (int)ceil(yMax) - (int)floor(yMin) + 3,
- display, visual, depth, pixmap);
- }
- }
- t3Font = t3FontCache[0];
-
- // is the glyph in the cache?
- i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
- for (j = 0; j < t3Font->cacheAssoc; ++j) {
- if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
- t3Font->cacheTags[i+j].code == code) {
- state->getFillRGB(&color);
- if (reverseVideo) {
- color.r = 1 - color.r;
- color.g = 1 - color.g;
- color.b = 1 - color.b;
- }
- text->addChar(state, 0, 0,
- t3Font->cacheTags[i+j].wx, t3Font->cacheTags[i+j].wy,
- code, u, uLen);
- drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
- t3Font->cacheData + (i+j) * t3Font->glyphSize,
- xt, yt, &color);
- return gTrue;
- }
- }
-
- // push a new Type 3 glyph record
- t3gs = new T3GlyphStack();
- t3gs->next = t3GlyphStack;
- t3GlyphStack = t3gs;
- t3GlyphStack->cacheable = gFalse;
- t3GlyphStack->code = code;
- t3GlyphStack->cache = t3Font;
- t3GlyphStack->cacheIdx = i;
- t3GlyphStack->x = xt;
- t3GlyphStack->y = yt;
- t3GlyphStack->u = u;
- t3GlyphStack->uLen = uLen;
-
- return gFalse;
-}
-
-void XOutputDev::endType3Char(GfxState *state) {
- XImage *image;
- Guchar *p;
- int x, y;
- Gulong pixel;
- double alpha;
- T3GlyphStack *t3gs;
- double *ctm;
-
- if (t3GlyphStack->cacheable) {
- image = t3GlyphStack->cache->image;
- XGetSubImage(display, pixmap, 0, 0,
- t3GlyphStack->cache->glyphW, t3GlyphStack->cache->glyphH,
- (1 << depth) - 1, ZPixmap, image, 0, 0);
- p = t3GlyphStack->cacheData;
- for (y = 0; y < t3GlyphStack->cache->glyphH; ++y) {
- for (x = 0; x < t3GlyphStack->cache->glyphW; ++x) {
- pixel = XGetPixel(image, x, y);
- if (trueColor) {
- alpha = (double)((pixel >> rShift) & rMul) / (double)rMul;
- } else {
- alpha = redMap[pixel & 0xff];
- }
- if (alpha <= 0.2) {
- *p++ = 4;
- } else if (alpha <= 0.4) {
- *p++ = 3;
- } else if (alpha <= 0.6) {
- *p++ = 2;
- } else if (alpha <= 0.8) {
- *p++ = 1;
- } else {
- *p++ = 0;
- }
- }
- }
- XDestroyRegion(clipRegion);
- XFreeGC(display, strokeGC);
- XFreeGC(display, fillGC);
- pixmapW = t3GlyphStack->origPixmapW;
- pixmapH = t3GlyphStack->origPixmapH;
- pixmap = t3GlyphStack->origPixmap;
- strokeGC = t3GlyphStack->origStrokeGC;
- fillGC = t3GlyphStack->origFillGC;
- clipRegion = t3GlyphStack->origClipRegion;
- drawType3Glyph(t3GlyphStack->cache,
- t3GlyphStack->cacheTag, t3GlyphStack->cacheData,
- t3GlyphStack->x, t3GlyphStack->y, &t3GlyphStack->color);
- // the CTM must be restored here in order for TextPage::addChar to
- // work correctly
- ctm = state->getCTM();
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
- }
- text->addChar(state, 0, 0, t3GlyphStack->wx, t3GlyphStack->wy,
- t3GlyphStack->code, t3GlyphStack->u, t3GlyphStack->uLen);
- t3gs = t3GlyphStack;
- t3GlyphStack = t3gs->next;
- delete t3gs;
-}
-
-void XOutputDev::drawType3Glyph(T3FontCache *t3Font,
- T3FontCacheTag *tag, Guchar *data,
- double x, double y, GfxRGB *color) {
- XImage *image;
- XColor xcolor;
- GfxRGB bg, rgb;
- Gulong map[5];
- Gulong pixel;
- Guchar *p;
- int x0, y0, w0, h0, x1, y1;
- int ix, iy;
-
- // compute: (x0,y0) = position in destination pixmap
- // (x1,y1) = position in the XImage
- // (w0,h0) = size of XImage transfer
- x0 = xoutRound(x + t3Font->glyphX);
- y0 = xoutRound(y + t3Font->glyphY);
- x1 = 0;
- y1 = 0;
- w0 = t3Font->glyphW;
- h0 = t3Font->glyphH;
- if (x0 < 0) {
- x1 = -x0;
- w0 += x0;
- x0 = 0;
- }
- if (x0 + w0 > pixmapW) {
- w0 = pixmapW - x0;
- }
- if (w0 <= 0) {
- return;
- }
- if (y0 < 0) {
- y1 = -y0;
- h0 += y0;
- y0 = 0;
- }
- if (y0 + h0 > pixmapH) {
- h0 = pixmapH - y0;
- }
- if (h0 <= 0) {
- return;
- }
-
- image = t3Font->image;
- XGetSubImage(display, pixmap, x0, y0, w0, h0,
- (1 << depth) - 1, ZPixmap, image, x1, y1);
- xcolor.pixel = XGetPixel(image, t3Font->glyphW / 2, t3Font->glyphH / 2);
- XQueryColor(display, colormap, &xcolor);
- bg.r = xcolor.red / 65535.0;
- bg.g = xcolor.green / 65535.0;
- bg.b = xcolor.blue / 65535.0;
- rgb.r = 0.25 * (color->r + 3 * bg.r);
- rgb.g = 0.25 * (color->g + 3 * bg.g);
- rgb.b = 0.25 * (color->b + 3 * bg.b);
- map[1] = findColor(&rgb);
- rgb.r = 0.5 * (color->r + bg.r);
- rgb.g = 0.5 * (color->g + bg.g);
- rgb.b = 0.5 * (color->b + bg.b);
- map[2] = findColor(&rgb);
- rgb.r = 0.25 * (3 * color->r + bg.r);
- rgb.g = 0.25 * (3 * color->g + bg.g);
- rgb.b = 0.25 * (3 * color->b + bg.b);
- map[3] = findColor(&rgb);
- map[4] = findColor(color);
- p = data;
- for (iy = 0; iy < t3Font->glyphH; ++iy) {
- for (ix = 0; ix < t3Font->glyphW; ++ix) {
- pixel = *p++;
- if (pixel > 0) {
- XPutPixel(image, ix, iy, map[pixel]);
- }
- }
- }
- XPutImage(display, pixmap, fillGC, image, x1, y1, x0, y0, w0, h0);
-}
-
-void XOutputDev::type3D0(GfxState *state, double wx, double wy) {
- t3GlyphStack->wx = wx;
- t3GlyphStack->wy = wy;
-}
-
-void XOutputDev::type3D1(GfxState *state, double wx, double wy,
- double llx, double lly, double urx, double ury) {
- GfxColor fgColor;
- XGCValues gcValues;
- XRectangle rect;
- double *ctm;
- T3FontCache *t3Font;
- double xt, yt, xMin, xMax, yMin, yMax, x1, y1;
- int i, j;
-
- t3Font = t3GlyphStack->cache;
- t3GlyphStack->wx = wx;
- t3GlyphStack->wy = wy;
-
- // check for a valid bbox
- state->transform(0, 0, &xt, &yt);
- state->transform(llx, lly, &x1, &y1);
- xMin = xMax = x1;
- yMin = yMax = y1;
- state->transform(llx, ury, &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(urx, lly, &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- state->transform(urx, ury, &x1, &y1);
- if (x1 < xMin) {
- xMin = x1;
- } else if (x1 > xMax) {
- xMax = x1;
- }
- if (y1 < yMin) {
- yMin = y1;
- } else if (y1 > yMax) {
- yMax = y1;
- }
- if (xMin - xt < t3Font->glyphX ||
- yMin - yt < t3Font->glyphY ||
- xMax - xt > t3Font->glyphX + t3Font->glyphW ||
- yMax - yt > t3Font->glyphY + t3Font->glyphH) {
- error(-1, "Bad bounding box in Type 3 glyph");
- return;
- }
-
- // allocate a cache entry
- t3GlyphStack->cacheable = gTrue;
- i = t3GlyphStack->cacheIdx;
- for (j = 0; j < t3Font->cacheAssoc; ++j) {
- if ((t3Font->cacheTags[i+j].mru & 0x7fff) == t3Font->cacheAssoc - 1) {
- t3Font->cacheTags[i+j].mru = 0x8000;
- t3Font->cacheTags[i+j].code = t3GlyphStack->code;
- t3GlyphStack->cacheTag = &t3Font->cacheTags[i+j];
- t3GlyphStack->cacheData = t3Font->cacheData + (i+j) * t3Font->glyphSize;
- } else {
- ++t3Font->cacheTags[i+j].mru;
- }
- }
- t3GlyphStack->cacheTag->wx = wx;
- t3GlyphStack->cacheTag->wy = wy;
-
- // prepare to rasterize the glyph
- //~ do we need to handle both fill and stroke color?
- state->getFillRGB(&t3GlyphStack->color);
- if (reverseVideo) {
- t3GlyphStack->color.r = 1 - t3GlyphStack->color.r;
- t3GlyphStack->color.g = 1 - t3GlyphStack->color.g;
- t3GlyphStack->color.b = 1 - t3GlyphStack->color.b;
- }
- fgColor.c[0] = reverseVideo ? 1 : 0;
- state->setFillColorSpace(new GfxDeviceGrayColorSpace());
- state->setFillColor(&fgColor);
- state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
- state->setStrokeColor(&fgColor);
- t3GlyphStack->origPixmapW = pixmapW;
- t3GlyphStack->origPixmapH = pixmapH;
- t3GlyphStack->origPixmap = pixmap;
- t3GlyphStack->origStrokeGC = strokeGC;
- t3GlyphStack->origFillGC = fillGC;
- t3GlyphStack->origClipRegion = clipRegion;
- pixmapW = t3GlyphStack->cache->glyphW;
- pixmapH = t3GlyphStack->cache->glyphH;
- pixmap = t3GlyphStack->cache->pixmap;
- gcValues.foreground = BlackPixel(display, screenNum);
- gcValues.background = WhitePixel(display, screenNum);
- gcValues.line_width = 0;
- gcValues.line_style = LineSolid;
- strokeGC = XCreateGC(display, pixmap,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
- updateLineAttrs(state, gTrue);
- gcValues.foreground = WhitePixel(display, screenNum);
- fillGC = XCreateGC(display, pixmap,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
- XFillRectangle(display, pixmap, fillGC, 0, 0, pixmapW, pixmapH);
- XSetForeground(display, fillGC, BlackPixel(display, screenNum));
- clipRegion = XCreateRegion();
- rect.x = rect.y = 0;
- rect.width = pixmapW;
- rect.height = pixmapH;
- XUnionRectWithRegion(&rect, clipRegion, clipRegion);
- XSetRegion(display, strokeGC, clipRegion);
- XSetRegion(display, fillGC, clipRegion);
- ctm = state->getCTM();
- t3GlyphStack->origCTM4 = ctm[4];
- t3GlyphStack->origCTM5 = ctm[5];
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- -t3GlyphStack->cache->glyphX, -t3GlyphStack->cache->glyphY);
-}
-
-void XOutputDev::endTextObject(GfxState *state) {
- double *ctm;
- double saveCTM[6];
-
- if (textClipPath) {
- ctm = state->getCTM();
- memcpy(saveCTM, ctm, 6 * sizeof(double));
- state->setCTM(1, 0, 0, 1, 0, 0);
- doClip(state, textClipPath, WindingRule);
- state->setCTM(saveCTM[0], saveCTM[1], saveCTM[2], saveCTM[3],
- saveCTM[4], saveCTM[5]);
- delete textClipPath;
- textClipPath = NULL;
- }
-}
-
-inline Gulong XOutputDev::findColor(GfxRGB *x, GfxRGB *actual) {
- double gray;
- int r, g, b;
- Gulong pixel;
-
- if (trueColor) {
- r = xoutRound(x->r * rMul);
- g = xoutRound(x->g * gMul);
- b = xoutRound(x->b * bMul);
- pixel = ((Gulong)r << rShift) +
- ((Gulong)g << gShift) +
- ((Gulong)b << bShift);
- actual->r = (double)r / rMul;
- actual->g = (double)g / gMul;
- actual->b = (double)b / bMul;
- } else if (numColors == 1) {
- gray = 0.299 * x->r + 0.587 * x->g + 0.114 * x->b;
- if (gray < 0.5) {
- pixel = colors[0];
- actual->r = actual->g = actual->b = 0;
- } else {
- pixel = colors[1];
- actual->r = actual->g = actual->b = 1;
- }
- } else {
- r = xoutRound(x->r * (numColors - 1));
- g = xoutRound(x->g * (numColors - 1));
- b = xoutRound(x->b * (numColors - 1));
- pixel = colors[(r * numColors + g) * numColors + b];
- actual->r = (double)r / (numColors - 1);
- actual->g = (double)g / (numColors - 1);
- actual->b = (double)b / (numColors - 1);
- }
- return pixel;
-}
-
-Gulong XOutputDev::findColor(GfxRGB *rgb) {
- int r, g, b;
- double gray;
- Gulong pixel;
-
- if (trueColor) {
- r = xoutRound(rgb->r * rMul);
- g = xoutRound(rgb->g * gMul);
- b = xoutRound(rgb->b * bMul);
- pixel = ((Gulong)r << rShift) +
- ((Gulong)g << gShift) +
- ((Gulong)b << bShift);
- } else if (numColors == 1) {
- gray = 0.299 * rgb->r + 0.587 * rgb->g + 0.114 * rgb->b;
- if (gray < 0.5)
- pixel = colors[0];
- else
- pixel = colors[1];
- } else {
- r = xoutRound(rgb->r * (numColors - 1));
- g = xoutRound(rgb->g * (numColors - 1));
- b = xoutRound(rgb->b * (numColors - 1));
-#if 0 // this makes things worse as often as better
- // even a very light color shouldn't map to white
- if (r == numColors - 1 && g == numColors - 1 && b == numColors - 1) {
- if (color->getR() < 0.95)
- --r;
- if (color->getG() < 0.95)
- --g;
- if (color->getB() < 0.95)
- --b;
- }
-#endif
- pixel = colors[(r * numColors + g) * numColors + b];
- }
- return pixel;
-}
-
-void XOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg) {
- ImageStream *imgStr;
- XImage *image;
- double *ctm;
- GBool rot;
- double xScale, yScale, xShear, yShear;
- int tx, ty, scaledWidth, scaledHeight, xSign, ySign;
- int ulx, uly, llx, lly, urx, ury, lrx, lry;
- int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
- int bx0, by0, bx1, by1, bw, bh;
- int cx0, cy0, cx1, cy1, cw, ch;
- int yp, yq, yt, yStep, lastYStep;
- int xp, xq, xt, xStep, xSrc;
- GfxRGB rgb;
- Guchar *pixBuf;
- int imgPix;
- double alpha;
- XColor xcolor;
- Gulong lastPixel;
- GfxRGB rgb2;
- double r0, g0, b0, r1, g1, b1;
- Gulong pix;
- Guchar *p;
- int x, y, x1, y1, x2, y2;
- int n, m, i, j;
-
- // get CTM, check for singular matrix
- ctm = state->getCTM();
- if (fabs(ctm[0] * ctm[3] - ctm[1] * ctm[2]) < 0.000001) {
- error(-1, "Singular CTM in drawImage");
- if (inlineImg) {
- j = height * ((width + 7) / 8);
- str->reset();
- for (i = 0; i < j; ++i) {
- str->getChar();
- }
- str->close();
- }
- return;
- }
-
- // compute scale, shear, rotation, translation parameters
- rot = fabs(ctm[1]) > fabs(ctm[0]);
- if (rot) {
- xScale = -ctm[1];
- yScale = -ctm[2] + (ctm[0] * ctm[3]) / ctm[1];
- xShear = ctm[3] / yScale;
- yShear = -ctm[0] / ctm[1];
- } else {
- xScale = ctm[0];
- yScale = -ctm[3] + (ctm[1] * ctm[2]) / ctm[0];
- xShear = -ctm[2] / yScale;
- yShear = ctm[1] / ctm[0];
- }
- tx = xoutRound(ctm[2] + ctm[4]);
- ty = xoutRound(ctm[3] + ctm[5]);
- // use ceil() to avoid gaps between "striped" images
- scaledWidth = (int)ceil(fabs(xScale));
- xSign = (xScale < 0) ? -1 : 1;
- scaledHeight = (int)ceil(fabs(yScale));
- ySign = (yScale < 0) ? -1 : 1;
-
- // compute corners in device space
- ulx1 = 0;
- uly1 = 0;
- urx1 = xSign * (scaledWidth - 1);
- ury1 = xoutRound(yShear * urx1);
- llx1 = xoutRound(xShear * ySign * (scaledHeight - 1));
- lly1 = ySign * (scaledHeight - 1) + xoutRound(yShear * llx1);
- lrx1 = xSign * (scaledWidth - 1) +
- xoutRound(xShear * ySign * (scaledHeight - 1));
- lry1 = ySign * (scaledHeight - 1) + xoutRound(yShear * lrx1);
- if (rot) {
- ulx = tx + uly1; uly = ty - ulx1;
- urx = tx + ury1; ury = ty - urx1;
- llx = tx + lly1; lly = ty - llx1;
- lrx = tx + lry1; lry = ty - lrx1;
- } else {
- ulx = tx + ulx1; uly = ty + uly1;
- urx = tx + urx1; ury = ty + ury1;
- llx = tx + llx1; lly = ty + lly1;
- lrx = tx + lrx1; lry = ty + lry1;
- }
-
- // bounding box:
- // (bx0, by0) = upper-left corner
- // (bx1, by1) = lower-right corner
- // (bw, bh) = size
- bx0 = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
- : (llx < lrx) ? llx : lrx
- : (urx < llx) ? (urx < lrx) ? urx : lrx
- : (llx < lrx) ? llx : lrx;
- bx1 = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
- : (llx > lrx) ? llx : lrx
- : (urx > llx) ? (urx > lrx) ? urx : lrx
- : (llx > lrx) ? llx : lrx;
- by0 = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
- : (lly < lry) ? lly : lry
- : (ury < lly) ? (ury < lry) ? ury : lry
- : (lly < lry) ? lly : lry;
- by1 = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
- : (lly > lry) ? lly : lry
- : (ury > lly) ? (ury > lry) ? ury : lry
- : (lly > lry) ? lly : lry;
- bw = bx1 - bx0 + 1;
- bh = by1 - by0 + 1;
-
- // Bounding box clipped to pixmap, i.e., "valid" rectangle:
- // (cx0, cy0) = upper-left corner of valid rectangle in Pixmap
- // (cx1, cy1) = upper-left corner of valid rectangle in XImage
- // (cw, ch) = size of valid rectangle
- // These values will be used to transfer the XImage from/to the
- // Pixmap.
- cw = (bx1 >= pixmapW) ? pixmapW - bx0 : bw;
- if (bx0 < 0) {
- cx0 = 0;
- cx1 = -bx0;
- cw += bx0;
- } else {
- cx0 = bx0;
- cx1 = 0;
- }
- ch = (by1 >= pixmapH) ? pixmapH - by0 : bh;
- if (by0 < 0) {
- cy0 = 0;
- cy1 = -by0;
- ch += by0;
- } else {
- cy0 = by0;
- cy1 = 0;
- }
-
- // check for tiny (zero width or height) images
- // and off-page images
- if (scaledWidth <= 0 || scaledHeight <= 0 || cw <= 0 || ch <= 0) {
- if (inlineImg) {
- j = height * ((width + 7) / 8);
- str->reset();
- for (i = 0; i < j; ++i) {
- str->getChar();
- }
- str->close();
- }
- return;
- }
-
- // compute Bresenham parameters for x and y scaling
- yp = height / scaledHeight;
- yq = height % scaledHeight;
- xp = width / scaledWidth;
- xq = width % scaledWidth;
-
- // allocate pixel buffer
- pixBuf = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
-
- // allocate XImage and read from page pixmap
- image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL, bw, bh, 8, 0);
- image->data = (char *)gmalloc(bh * image->bytes_per_line);
- XGetSubImage(display, pixmap, cx0, cy0, cw, ch, (1 << depth) - 1, ZPixmap,
- image, cx1, cy1);
-
- // get mask color
- state->getFillRGB(&rgb);
- if (reverseVideo) {
- rgb.r = 1 - rgb.r;
- rgb.g = 1 - rgb.g;
- rgb.b = 1 - rgb.b;
- }
- r0 = rgb.r;
- g0 = rgb.g;
- b0 = rgb.b;
-
- // initialize background color
- // (the specific pixel value doesn't matter here, as long as
- // r1,g1,b1 correspond correctly to lastPixel)
- xcolor.pixel = lastPixel = 0;
- XQueryColor(display, colormap, &xcolor);
- r1 = (double)xcolor.red / 65535.0;
- g1 = (double)xcolor.green / 65535.0;
- b1 = (double)xcolor.blue / 65535.0;
-
- // initialize the image stream
- imgStr = new ImageStream(str, width, 1, 1);
- imgStr->reset();
-
- // init y scale Bresenham
- yt = 0;
- lastYStep = 1;
-
- for (y = 0; y < scaledHeight; ++y) {
-
- // y scale Bresenham
- yStep = yp;
- yt += yq;
- if (yt >= scaledHeight) {
- yt -= scaledHeight;
- ++yStep;
- }
-
- // read row(s) from image
- n = (yp > 0) ? yStep : lastYStep;
- if (n > 0) {
- p = pixBuf;
- for (i = 0; i < n; ++i) {
- memcpy(p, imgStr->getLine(), width);
- if (invert) {
- for (j = 0; j < width; ++j) {
- p[j] ^= 1;
- }
- }
- p += width;
- }
- }
- lastYStep = yStep;
-
- // init x scale Bresenham
- xt = 0;
- xSrc = 0;
-
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
-
- // x shear
- x1 = xSign * x + xoutRound(xShear * ySign * y);
-
- // y shear
- y1 = ySign * y + xoutRound(yShear * x1);
-
- // rotation
- if (rot) {
- x2 = y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = y1;
- }
-
- // compute the filtered pixel at (x,y) after the
- // x and y scaling operations
- n = yStep > 0 ? yStep : 1;
- m = xStep > 0 ? xStep : 1;
- p = pixBuf + xSrc;
- imgPix = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- imgPix += *p++;
- }
- p += width - m;
- }
-
- // x scale Bresenham
- xSrc += xStep;
-
- // blend image pixel with background
- alpha = (double)imgPix / (double)(n * m);
- xcolor.pixel = XGetPixel(image, tx + x2 - bx0, ty + y2 - by0);
- if (xcolor.pixel != lastPixel) {
- XQueryColor(display, colormap, &xcolor);
- r1 = (double)xcolor.red / 65535.0;
- g1 = (double)xcolor.green / 65535.0;
- b1 = (double)xcolor.blue / 65535.0;
- lastPixel = xcolor.pixel;
- }
- rgb2.r = r0 * (1 - alpha) + r1 * alpha;
- rgb2.g = g0 * (1 - alpha) + g1 * alpha;
- rgb2.b = b0 * (1 - alpha) + b1 * alpha;
- pix = findColor(&rgb2);
-
- // set pixel
- XPutPixel(image, tx + x2 - bx0, ty + y2 - by0, pix);
- }
- }
-
- // blit the image into the pixmap
- XPutImage(display, pixmap, fillGC, image, cx1, cy1, cx0, cy0, cw, ch);
-
- // free memory
- delete imgStr;
- gfree(pixBuf);
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
-}
-
-void XOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg) {
- ImageStream *imgStr;
- XImage *image;
- int nComps, nVals, nBits;
- GBool dither;
- double *ctm;
- GBool rot;
- double xScale, yScale, xShear, yShear;
- int tx, ty, scaledWidth, scaledHeight, xSign, ySign;
- int ulx, uly, llx, lly, urx, ury, lrx, lry;
- int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1;
- int bx0, by0, bx1, by1, bw, bh;
- int cx0, cy0, cx1, cy1, cw, ch;
- int yp, yq, yt, yStep, lastYStep;
- int xp, xq, xt, xStep, xSrc;
- GfxRGB *pixBuf;
- Guchar *pixBuf1, *alphaBuf;
- Guchar pixBuf2[gfxColorMaxComps];
- GfxRGB color2, color3, actual, err, errRight;
- GfxRGB *errDown0, *errDown1, *errDownTmp;
- double r0, g0, b0, alpha, mul;
- Gulong pix;
- GfxRGB *p;
- Guchar *q, *p1, *p2;
- GBool oneBitMode;
- GfxRGB oneBitRGB[2];
- int x, y, x1, y1, x2, y2;
- int n, m, i, j, k;
-
- // image parameters
- nComps = colorMap->getNumPixelComps();
- nVals = width * nComps;
- nBits = colorMap->getBits();
- oneBitMode = nComps == 1 && nBits == 1 && !maskColors;
- dither = nComps > 1 || nBits > 1;
-
- // get CTM, check for singular matrix
- ctm = state->getCTM();
- if (fabs(ctm[0] * ctm[3] - ctm[1] * ctm[2]) < 0.000001) {
- error(-1, "Singular CTM in drawImage");
- if (inlineImg) {
- str->reset();
- j = height * ((nVals * nBits + 7) / 8);
- for (i = 0; i < j; ++i) {
- str->getChar();
- }
- str->close();
- }
- return;
- }
-
- // compute scale, shear, rotation, translation parameters
- rot = fabs(ctm[1]) > fabs(ctm[0]);
- if (rot) {
- xScale = -ctm[1];
- yScale = -ctm[2] + (ctm[0] * ctm[3]) / ctm[1];
- xShear = ctm[3] / yScale;
- yShear = -ctm[0] / ctm[1];
- } else {
- xScale = ctm[0];
- yScale = -ctm[3] + (ctm[1] * ctm[2]) / ctm[0];
- xShear = -ctm[2] / yScale;
- yShear = ctm[1] / ctm[0];
- }
- tx = xoutRound(ctm[2] + ctm[4]);
- ty = xoutRound(ctm[3] + ctm[5]);
- if (xScale < 0) {
- // this is the right edge which needs to be (left + width - 1)
- --tx;
- }
- if (yScale < 0) {
- // this is the bottom edge which needs to be (top + height - 1)
- --ty;
- }
- // use ceil() to avoid gaps between "striped" images
- scaledWidth = (int)ceil(fabs(xScale));
- xSign = (xScale < 0) ? -1 : 1;
- scaledHeight = (int)ceil(fabs(yScale));
- ySign = (yScale < 0) ? -1 : 1;
-
- // compute corners in device space
- ulx1 = 0;
- uly1 = 0;
- urx1 = xSign * (scaledWidth - 1);
- ury1 = xoutRound(yShear * urx1);
- llx1 = xoutRound(xShear * ySign * (scaledHeight - 1));
- lly1 = ySign * (scaledHeight - 1) + xoutRound(yShear * llx1);
- lrx1 = xSign * (scaledWidth - 1) +
- xoutRound(xShear * ySign * (scaledHeight - 1));
- lry1 = ySign * (scaledHeight - 1) + xoutRound(yShear * lrx1);
- if (rot) {
- ulx = tx + uly1; uly = ty - ulx1;
- urx = tx + ury1; ury = ty - urx1;
- llx = tx + lly1; lly = ty - llx1;
- lrx = tx + lry1; lry = ty - lrx1;
- } else {
- ulx = tx + ulx1; uly = ty + uly1;
- urx = tx + urx1; ury = ty + ury1;
- llx = tx + llx1; lly = ty + lly1;
- lrx = tx + lrx1; lry = ty + lry1;
- }
-
- // bounding box:
- // (bx0, by0) = upper-left corner
- // (bx1, by1) = lower-right corner
- // (bw, bh) = size
- bx0 = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx
- : (llx < lrx) ? llx : lrx
- : (urx < llx) ? (urx < lrx) ? urx : lrx
- : (llx < lrx) ? llx : lrx;
- bx1 = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx
- : (llx > lrx) ? llx : lrx
- : (urx > llx) ? (urx > lrx) ? urx : lrx
- : (llx > lrx) ? llx : lrx;
- by0 = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry
- : (lly < lry) ? lly : lry
- : (ury < lly) ? (ury < lry) ? ury : lry
- : (lly < lry) ? lly : lry;
- by1 = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry
- : (lly > lry) ? lly : lry
- : (ury > lly) ? (ury > lry) ? ury : lry
- : (lly > lry) ? lly : lry;
- bw = bx1 - bx0 + 1;
- bh = by1 - by0 + 1;
-
- // Bounding box clipped to pixmap, i.e., "valid" rectangle:
- // (cx0, cy0) = upper-left corner of valid rectangle in Pixmap
- // (cx1, cy1) = upper-left corner of valid rectangle in XImage
- // (cw, ch) = size of valid rectangle
- // These values will be used to transfer the XImage from/to the
- // Pixmap.
- cw = (bx1 >= pixmapW) ? pixmapW - bx0 : bw;
- if (bx0 < 0) {
- cx0 = 0;
- cx1 = -bx0;
- cw += bx0;
- } else {
- cx0 = bx0;
- cx1 = 0;
- }
- ch = (by1 >= pixmapH) ? pixmapH - by0 : bh;
- if (by0 < 0) {
- cy0 = 0;
- cy1 = -by0;
- ch += by0;
- } else {
- cy0 = by0;
- cy1 = 0;
- }
-
- // check for tiny (zero width or height) images
- // and off-page images
- if (scaledWidth <= 0 || scaledHeight <= 0 || cw <= 0 || ch <= 0) {
- if (inlineImg) {
- str->reset();
- j = height * ((nVals * nBits + 7) / 8);
- for (i = 0; i < j; ++i)
- str->getChar();
- str->close();
- }
- return;
- }
-
- // compute Bresenham parameters for x and y scaling
- yp = height / scaledHeight;
- yq = height % scaledHeight;
- xp = width / scaledWidth;
- xq = width % scaledWidth;
-
- // allocate pixel buffer
- if (oneBitMode) {
- pixBuf1 = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
- pixBuf = NULL;
- } else {
- pixBuf = (GfxRGB *)gmalloc((yp + 1) * width * sizeof(GfxRGB));
- pixBuf1 = NULL;
- }
- if (maskColors) {
- alphaBuf = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
- } else {
- alphaBuf = NULL;
- }
-
- // allocate XImage
- image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL, bw, bh, 8, 0);
- image->data = (char *)gmalloc(bh * image->bytes_per_line);
-
- // if the transform is anything other than a 0/90/180/270 degree
- // rotation/flip, or if there is color key masking, read the
- // backgound pixmap to fill in the corners
- if (!((ulx == llx && uly == ury) ||
- (uly == lly && ulx == urx)) ||
- maskColors) {
- XGetSubImage(display, pixmap, cx0, cy0, cw, ch, (1 << depth) - 1, ZPixmap,
- image, cx1, cy1);
- }
-
- // allocate error diffusion accumulators
- if (dither) {
- errDown0 = (GfxRGB *)gmalloc((scaledWidth + 2) * sizeof(GfxRGB));
- errDown1 = (GfxRGB *)gmalloc((scaledWidth + 2) * sizeof(GfxRGB));
- for (j = 0; j < scaledWidth + 2; ++j) {
- errDown0[j].r = errDown0[j].g = errDown0[j].b = 0;
- errDown1[j].r = errDown1[j].g = errDown1[j].b = 0;
- }
- } else {
- errDown0 = errDown1 = NULL;
- }
-
- // optimize the one-bit-deep image case
- if (oneBitMode) {
- pixBuf2[0] = 0;
- colorMap->getRGB(pixBuf2, &oneBitRGB[0]);
- pixBuf2[0] = 1;
- colorMap->getRGB(pixBuf2, &oneBitRGB[1]);
- }
-
- // initialize the image stream
- imgStr = new ImageStream(str, width, nComps, nBits);
- imgStr->reset();
-
- // init y scale Bresenham
- yt = 0;
- lastYStep = 1;
-
- for (y = 0; y < scaledHeight; ++y) {
-
- // initialize error diffusion accumulators
- if (dither) {
- errDownTmp = errDown0;
- errDown0 = errDown1;
- errDown1 = errDownTmp;
- for (j = 0; j < scaledWidth + 2; ++j) {
- errDown1[j].r = errDown1[j].g = errDown1[j].b = 0;
- }
- errRight.r = errRight.g = errRight.b = 0;
- }
-
- // y scale Bresenham
- yStep = yp;
- yt += yq;
- if (yt >= scaledHeight) {
- yt -= scaledHeight;
- ++yStep;
- }
-
- // read row(s) from image
- n = (yp > 0) ? yStep : lastYStep;
- if (n > 0) {
- if (oneBitMode) {
- p1 = pixBuf1;
- for (i = 0; i < n; ++i) {
- p2 = imgStr->getLine();
- memcpy(p1, p2, width);
- p1 += width;
- }
- } else {
- p = pixBuf;
- q = alphaBuf;
- for (i = 0; i < n; ++i) {
- p2 = imgStr->getLine();
- for (j = 0; j < width; ++j) {
- colorMap->getRGB(p2, p);
- ++p;
- if (q) {
- *q = 1;
- for (k = 0; k < nComps; ++k) {
- if (p2[k] < maskColors[2*k] ||
- p2[k] > maskColors[2*k+1]) {
- *q = 0;
- break;
- }
- }
- ++q;
- }
- p2 += nComps;
- }
- }
- }
- }
- lastYStep = yStep;
-
- // init x scale Bresenham
- xt = 0;
- xSrc = 0;
-
- for (x = 0; x < scaledWidth; ++x) {
-
- // x scale Bresenham
- xStep = xp;
- xt += xq;
- if (xt >= scaledWidth) {
- xt -= scaledWidth;
- ++xStep;
- }
-
- // x shear
- x1 = xSign * x + xoutRound(xShear * ySign * y);
-
- // y shear
- y1 = ySign * y + xoutRound(yShear * x1);
-
- // rotation
- if (rot) {
- x2 = y1;
- y2 = -x1;
- } else {
- x2 = x1;
- y2 = y1;
- }
-
- // compute the filtered pixel at (x,y) after the
- // x and y scaling operations
- n = yStep > 0 ? yStep : 1;
- m = xStep > 0 ? xStep : 1;
- if (oneBitMode) {
- p1 = pixBuf1 + xSrc;
- k = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- k += *p1++;
- }
- p1 += width - m;
- }
- mul = (double)k / (double)(n * m);
- r0 = mul * oneBitRGB[1].r + (1 - mul) * oneBitRGB[0].r;
- g0 = mul * oneBitRGB[1].g + (1 - mul) * oneBitRGB[0].g;
- b0 = mul * oneBitRGB[1].b + (1 - mul) * oneBitRGB[0].b;
- alpha = 0;
- } else {
- p = pixBuf + xSrc;
- q = alphaBuf ? alphaBuf + xSrc : (Guchar *)NULL;
- alpha = 0;
- r0 = g0 = b0 = 0;
- for (i = 0; i < n; ++i) {
- for (j = 0; j < m; ++j) {
- r0 += p->r;
- g0 += p->g;
- b0 += p->b;
- ++p;
- if (q) {
- alpha += *q++;
- }
- }
- p += width - m;
- }
- mul = 1 / (double)(n * m);
- r0 *= mul;
- g0 *= mul;
- b0 *= mul;
- alpha *= mul;
- }
-
- // x scale Bresenham
- xSrc += xStep;
-
- // compute pixel
- if (dither) {
- color2.r = r0 + errRight.r + errDown0[x + 1].r;
- if (color2.r > 1) {
- color3.r = 1;
- } else if (color2.r < 0) {
- color3.r = 0;
- } else {
- color3.r = color2.r;
- }
- color2.g = g0 + errRight.g + errDown0[x + 1].g;
- if (color2.g > 1) {
- color3.g = 1;
- } else if (color2.g < 0) {
- color3.g = 0;
- } else {
- color3.g = color2.g;
- }
- color2.b = b0 + errRight.b + errDown0[x + 1].b;
- if (color2.b > 1) {
- color3.b = 1;
- } else if (color2.b < 0) {
- color3.b = 0;
- } else {
- color3.b = color2.b;
- }
- pix = findColor(&color3, &actual);
- err.r = (color2.r - actual.r) / 16;
- err.g = (color2.g - actual.g) / 16;
- err.b = (color2.b - actual.b) / 16;
- errRight.r = 7 * err.r;
- errRight.g = 7 * err.g;
- errRight.b = 7 * err.b;
- errDown1[x].r += 3 * err.r;
- errDown1[x].g += 3 * err.g;
- errDown1[x].b += 3 * err.b;
- errDown1[x + 1].r += 5 * err.r;
- errDown1[x + 1].g += 5 * err.g;
- errDown1[x + 1].b += 5 * err.b;
- errDown1[x + 2].r = err.r;
- errDown1[x + 2].g = err.g;
- errDown1[x + 2].b = err.b;
- } else {
- color2.r = r0;
- color2.g = g0;
- color2.b = b0;
- pix = findColor(&color2, &actual);
- }
-
- // set pixel
- //~ this should do a blend when 0 < alpha < 1
- if (alpha < 0.75) {
- XPutPixel(image, tx + x2 - bx0, ty + y2 - by0, pix);
- }
- }
- }
-
- // blit the image into the pixmap
- XPutImage(display, pixmap, fillGC, image, cx1, cy1, cx0, cy0, cw, ch);
-
- // free memory
- delete imgStr;
- if (oneBitMode) {
- gfree(pixBuf1);
- } else {
- gfree(pixBuf);
- }
- if (maskColors) {
- gfree(alphaBuf);
- }
- gfree(image->data);
- image->data = NULL;
- XDestroyImage(image);
- gfree(errDown0);
- gfree(errDown1);
-}
-
-GBool XOutputDev::findText(Unicode *s, int len,
- GBool startAtTop, GBool stopAtBottom,
- GBool startAtLast, GBool stopAtLast,
- int *xMin, int *yMin,
- int *xMax, int *yMax) {
- double xMin1, yMin1, xMax1, yMax1;
-
- xMin1 = (double)*xMin;
- yMin1 = (double)*yMin;
- xMax1 = (double)*xMax;
- yMax1 = (double)*yMax;
- if (text->findText(s, len, startAtTop, stopAtBottom,
- startAtLast, stopAtLast,
- &xMin1, &yMin1, &xMax1, &yMax1)) {
- *xMin = xoutRound(xMin1);
- *xMax = xoutRound(xMax1);
- *yMin = xoutRound(yMin1);
- *yMax = xoutRound(yMax1);
- return gTrue;
- }
- return gFalse;
-}
-
-GString *XOutputDev::getText(int xMin, int yMin, int xMax, int yMax) {
- return text->getText((double)xMin, (double)yMin,
- (double)xMax, (double)yMax);
-}
diff --git a/pdf/xpdf/XOutputDev.h b/pdf/xpdf/XOutputDev.h
deleted file mode 100644
index 3efa1dd..0000000
--- a/pdf/xpdf/XOutputDev.h
+++ /dev/null
@@ -1,680 +0,0 @@
-//========================================================================
-//
-// XOutputDev.h
-//
-// Copyright 1996-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef XOUTPUTDEV_H
-#define XOUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <stddef.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include "config.h"
-#include "Object.h"
-#include "CharTypes.h"
-#include "GlobalParams.h"
-#include "OutputDev.h"
-
-class GString;
-class GList;
-struct GfxRGB;
-class GfxFont;
-class GfxPath;
-class GfxSubpath;
-class TextPage;
-class XOutputFontCache;
-struct T3FontCacheTag;
-class T3FontCache;
-struct T3GlyphStack;
-class XOutputDev;
-class Link;
-class Catalog;
-class DisplayFontParam;
-class UnicodeMap;
-class CharCodeToUnicode;
-
-#if HAVE_T1LIB_H
-class T1FontEngine;
-class T1FontFile;
-class T1Font;
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class FTFontEngine;
-class FTFontFile;
-class FTFont;
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class TTFontEngine;
-class TTFontFile;
-class TTFont;
-#endif
-
-//------------------------------------------------------------------------
-// Constants
-//------------------------------------------------------------------------
-
-#define maxRGBCube 7 // max size of RGB color cube
-
-#define numTmpPoints 256 // number of XPoints in temporary array
-#define numTmpSubpaths 16 // number of elements in temporary arrays
- // for fill/clip
-
-//------------------------------------------------------------------------
-// Misc types
-//------------------------------------------------------------------------
-
-struct BoundingRect {
- short xMin, xMax; // min/max x values
- short yMin, yMax; // min/max y values
-};
-
-//------------------------------------------------------------------------
-// XOutputFont
-//------------------------------------------------------------------------
-
-class XOutputFont {
-public:
-
- XOutputFont(Ref *idA, double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A, double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA);
-
- virtual ~XOutputFont();
-
- // Does this font match the ID and transform?
- GBool matches(Ref *idA, double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA)
- { return id.num == idA->num && id.gen == idA->gen &&
- m11Orig == m11OrigA && m12Orig == m12OrigA &&
- m21Orig == m21OrigA && m22Orig == m22OrigA; }
-
- // Was font created successfully?
- virtual GBool isOk() = 0;
-
- // Update <gc> with this font.
- virtual void updateGC(GC gc) = 0;
-
- // Draw character <c>/<u> at <x>,<y> (in device space).
- virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen) = 0;
-
- // Returns true if this XOutputFont subclass provides the
- // getCharPath function.
- virtual GBool hasGetCharPath() { return gFalse; }
-
- // Add the character outline for <c>/<u> to the current path.
- virtual void getCharPath(GfxState *state,
- CharCode c, Unicode *u, int ulen);
-
-protected:
-
- Ref id; // font ID
- double m11Orig, m12Orig, // original transform matrix
- m21Orig, m22Orig;
- double m11, m12, m21, m22; // actual transform matrix (possibly
- // modified for font substitution)
- Display *display; // X display
- XOutputDev *xOut;
-};
-
-#if HAVE_T1LIB_H
-//------------------------------------------------------------------------
-// XOutputT1Font
-//------------------------------------------------------------------------
-
-class XOutputT1Font: public XOutputFont {
-public:
-
- XOutputT1Font(Ref *idA, T1FontFile *fontFileA,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA);
-
- virtual ~XOutputT1Font();
-
- // Was font created successfully?
- virtual GBool isOk();
-
- // Update <gc> with this font.
- virtual void updateGC(GC gc);
-
- // Draw character <c>/<u> at <x>,<y>.
- virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen);
-
- // Returns true if this XOutputFont subclass provides the
- // getCharPath function.
- virtual GBool hasGetCharPath() { return gTrue; }
-
- // Add the character outline for <c>/<u> to the current path.
- virtual void getCharPath(GfxState *state,
- CharCode c, Unicode *u, int ulen);
-
-private:
-
- T1FontFile *fontFile;
- T1Font *font;
-};
-#endif // HAVE_T1LIB_H
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputFTFont
-//------------------------------------------------------------------------
-
-class XOutputFTFont: public XOutputFont {
-public:
-
- XOutputFTFont(Ref *idA, FTFontFile *fontFileA,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA);
-
- virtual ~XOutputFTFont();
-
- // Was font created successfully?
- virtual GBool isOk();
-
- // Update <gc> with this font.
- virtual void updateGC(GC gc);
-
- // Draw character <c>/<u> at <x>,<y>.
- virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen);
-
- // Returns true if this XOutputFont subclass provides the
- // getCharPath function.
- virtual GBool hasGetCharPath() { return gTrue; }
-
- // Add the character outline for <c>/<u> to the current path.
- virtual void getCharPath(GfxState *state,
- CharCode c, Unicode *u, int ulen);
-
-private:
-
- FTFontFile *fontFile;
- FTFont *font;
-};
-#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-//------------------------------------------------------------------------
-// XOutputTTFont
-//------------------------------------------------------------------------
-
-class XOutputTTFont: public XOutputFont {
-public:
-
- XOutputTTFont(Ref *idA, TTFontFile *fontFileA,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A,
- double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA);
-
- virtual ~XOutputTTFont();
-
- // Was font created successfully?
- virtual GBool isOk();
-
- // Update <gc> with this font.
- virtual void updateGC(GC gc);
-
- // Draw character <c>/<u> at <x>,<y>.
- virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen);
-
-private:
-
- TTFontFile *fontFile;
- TTFont *font;
-};
-#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-
-//------------------------------------------------------------------------
-// XOutputServer8BitFont
-//------------------------------------------------------------------------
-
-class XOutputServer8BitFont: public XOutputFont {
-public:
-
- XOutputServer8BitFont(Ref *idA, GString *xlfdFmt,
- UnicodeMap *xUMapA, CharCodeToUnicode *fontUMap,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A, double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA);
-
- virtual ~XOutputServer8BitFont();
-
- // Was font created successfully?
- virtual GBool isOk();
-
- // Update <gc> with this font.
- virtual void updateGC(GC gc);
-
- // Draw character <c>/<u> at <x>,<y>.
- virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen);
-
-private:
-
- XFontStruct *xFont; // the X font
- Gushort map[256]; // forward map (char code -> X font code)
- UnicodeMap *xUMap;
-};
-
-//------------------------------------------------------------------------
-// XOutputServer16BitFont
-//------------------------------------------------------------------------
-
-class XOutputServer16BitFont: public XOutputFont {
-public:
-
- XOutputServer16BitFont(Ref *idA, GString *xlfdFmt,
- UnicodeMap *xUMapA, CharCodeToUnicode *fontUMap,
- double m11OrigA, double m12OrigA,
- double m21OrigA, double m22OrigA,
- double m11A, double m12A, double m21A, double m22A,
- Display *displayA, XOutputDev *xOutA);
-
- virtual ~XOutputServer16BitFont();
-
- // Was font created successfully?
- virtual GBool isOk();
-
- // Update <gc> with this font.
- virtual void updateGC(GC gc);
-
- // Draw character <c>/<u> at <x>,<y>.
- virtual void drawChar(GfxState *state, Pixmap pixmap, int w, int h,
- GC gc, GfxRGB *rgb,
- double x, double y, double dx, double dy,
- CharCode c, Unicode *u, int uLen);
-
-private:
-
- XFontStruct *xFont; // the X font
- UnicodeMap *xUMap;
-};
-
-//------------------------------------------------------------------------
-// XOutputFontCache
-//------------------------------------------------------------------------
-
-#if HAVE_T1LIB_H
-class XOutputT1FontFile {
-public:
- XOutputT1FontFile(int numA, int genA, GBool substA,
- T1FontFile *fontFileA, GString *tmpFileNameA)
- { num = numA; gen = genA; subst = substA;
- fontFile = fontFileA; tmpFileName = tmpFileNameA; }
- ~XOutputT1FontFile();
- int num, gen;
- GBool subst;
- T1FontFile *fontFile;
- GString *tmpFileName;
-};
-#endif
-
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class XOutputFTFontFile {
-public:
- XOutputFTFontFile(int numA, int genA, GBool substA,
- FTFontFile *fontFileA, GString *tmpFileNameA)
- { num = numA; gen = genA; subst = substA;
- fontFile = fontFileA; tmpFileName = tmpFileNameA; }
- ~XOutputFTFontFile();
- int num, gen;
- GBool subst;
- FTFontFile *fontFile;
- GString *tmpFileName;
-};
-#endif
-
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
-class XOutputTTFontFile {
-public:
- XOutputTTFontFile(int numA, int genA, GBool substA,
- TTFontFile *fontFileA, GString *tmpFileNameA)
- { num = numA; gen = genA; subst = substA;
- fontFile = fontFileA; tmpFileName = tmpFileNameA; }
- ~XOutputTTFontFile();
- int num, gen;
- GBool subst;
- TTFontFile *fontFile;
- GString *tmpFileName;
-};
-#endif
-
-class XOutputFontCache {
-public:
-
- // Constructor.
- XOutputFontCache(Display *displayA, Guint depthA,
- XOutputDev *xOutA,
- FontRastControl t1libControlA,
- FontRastControl freetypeControlA);
-
- // Destructor.
- ~XOutputFontCache();
-
- // Initialize (or re-initialize) the font cache for a new document.
- void startDoc(int screenNum, Visual *visual,
- Colormap colormap, GBool trueColor,
- int rMul, int gMul, int bMul,
- int rShift, int gShift, int bShift,
- Gulong *colors, int numColors);
-
- // Get a font. This creates a new font if necessary.
- XOutputFont *getFont(XRef *xref, GfxFont *gfxFont, double m11, double m12,
- double m21, double m22);
-
-private:
-
- void delFonts();
- void clear();
- XOutputFont *tryGetFont(XRef *xref, DisplayFontParam *dfp, GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12, double m21, double m22,
- GBool subst);
-#if HAVE_T1LIB_H
- XOutputFont *tryGetT1Font(XRef *xref, GfxFont *gfxFont,
- double m11, double m12, double m21, double m22);
- XOutputFont *tryGetT1FontFromFile(XRef *xref, GString *fileName,
- GBool deleteFile, GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12,
- double m21, double m22, GBool subst);
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- XOutputFont *tryGetFTFont(XRef *xref, GfxFont *gfxFont,
- double m11, double m12, double m21, double m22);
- XOutputFont *tryGetFTFontFromFile(XRef *xref, GString *fileName,
- GBool deleteFile, GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12,
- double m21, double m22,
- GBool embedded, GBool subst);
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- XOutputFont *tryGetTTFont(XRef *xref, GfxFont *gfxFont,
- double m11, double m12, double m21, double m22);
- XOutputFont *tryGetTTFontFromFile(XRef *xref, GString *fileName,
- GBool deleteFile, GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12,
- double m21, double m22, GBool subst);
-#endif
- XOutputFont *tryGetServerFont(GString *xlfd, GString *encodingName,
- GfxFont *gfxFont,
- double m11Orig, double m12Orig,
- double m21Orig, double m22Orig,
- double m11, double m12,
- double m21, double m22);
-
- Display *display; // X display pointer
- XOutputDev *xOut;
- Guint depth; // pixmap depth
-
- XOutputFont *
- fonts[xOutFontCacheSize];
- int nFonts;
-
-#if HAVE_T1LIB_H
- FontRastControl t1libControl; // t1lib settings
- T1FontEngine *t1Engine; // Type 1 font engine
- GList *t1FontFiles; // list of Type 1 font files
- // [XOutputT1FontFile]
-#endif
-
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
- FontRastControl // FreeType settings
- freetypeControl;
-#endif
-#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- FTFontEngine *ftEngine; // FreeType font engine
- GList *ftFontFiles; // list of FreeType font files
- // [XOutputFTFontFile]
-#endif
-#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
- TTFontEngine *ttEngine; // TrueType font engine
- GList *ttFontFiles; // list of TrueType font files
- // [XOutputTTFontFile]
-#endif
-};
-
-//------------------------------------------------------------------------
-// XOutputState
-//------------------------------------------------------------------------
-
-struct XOutputState {
- GC strokeGC;
- GC fillGC;
- Region clipRegion;
- XOutputState *next;
-};
-
-//------------------------------------------------------------------------
-// XOutputDev
-//------------------------------------------------------------------------
-
-class XOutputDev: public OutputDev {
-public:
-
- // Constructor.
- XOutputDev(Display *displayA, int screenNumA,
- Visual *visualA, Colormap colormapA,
- GBool reverseVideoA, unsigned long paperColorA,
- GBool installCmap, int rgbCubeSize,
- int forceDepth = 0);
-
- // Destructor.
- virtual ~XOutputDev();
-
- //---- get info about output device
-
- // Does this device use upside-down coordinates?
- // (Upside-down means (0,0) is the top left corner of the page.)
- virtual GBool upsideDown() { return gTrue; }
-
- // Does this device use drawChar() or drawString()?
- virtual GBool useDrawChar() { return gTrue; }
-
- // Does this device use beginType3Char/endType3Char? Otherwise,
- // text in Type 3 fonts will be drawn with drawChar/drawString.
- virtual GBool interpretType3Chars() { return gTrue; }
-
- //----- initialization and control
-
- // Start a page.
- virtual void startPage(int pageNum, GfxState *state);
-
- // End a page.
- virtual void endPage();
-
- //----- link borders
- virtual void drawLink(Link *link, Catalog *catalog);
-
- //----- save/restore graphics state
- virtual void saveState(GfxState *state);
- virtual void restoreState(GfxState *state);
-
- //----- update graphics state
- virtual void updateAll(GfxState *state);
- virtual void updateCTM(GfxState *state, double m11, double m12,
- double m21, double m22, double m31, double m32);
- virtual void updateLineDash(GfxState *state);
- virtual void updateFlatness(GfxState *state);
- virtual void updateLineJoin(GfxState *state);
- virtual void updateLineCap(GfxState *state);
- virtual void updateMiterLimit(GfxState *state);
- virtual void updateLineWidth(GfxState *state);
- virtual void updateFillColor(GfxState *state);
- virtual void updateStrokeColor(GfxState *state);
-
- //----- update text state
- virtual void updateFont(GfxState *state);
-
- //----- path painting
- virtual void stroke(GfxState *state);
- virtual void fill(GfxState *state);
- virtual void eoFill(GfxState *state);
-
- //----- path clipping
- virtual void clip(GfxState *state);
- virtual void eoClip(GfxState *state);
-
- //----- text drawing
- virtual void beginString(GfxState *state, GString *s);
- virtual void endString(GfxState *state);
- virtual void drawChar(GfxState *state, double x, double y,
- double dx, double dy,
- double originX, double originY,
- CharCode code, Unicode *u, int uLen);
- virtual GBool beginType3Char(GfxState *state,
- 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,
- int width, int height, GBool invert,
- GBool inlineImg);
- virtual void drawImage(GfxState *state, Object *ref, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int *maskColors, GBool inlineImg);
-
- //----- Type 3 font operators
- virtual void type3D0(GfxState *state, double wx, double wy);
- virtual void type3D1(GfxState *state, double wx, double wy,
- double llx, double lly, double urx, double ury);
-
- //----- special access
-
- // Called to indicate that a new PDF document has been loaded.
- void startDoc(XRef *xrefA);
-
- // Find a string. If <startAtTop> is true, starts looking at the
- // top of the page; else if <startAtLast> is true, starts looking
- // immediately after the last find result; else starts looking at
- // <xMin>,<yMin>. If <stopAtBottom> is true, stops looking at the
- // bottom of the page; else if <stopAtLast> is true, stops looking
- // just before the last find result; else stops looking at
- // <xMax>,<yMax>.
- GBool findText(Unicode *s, int len,
- GBool startAtTop, GBool stopAtBottom,
- GBool startAtLast, GBool stopAtLast,
- int *xMin, int *yMin,
- int *xMax, int *yMax);
-
- // Get the text which is inside the specified rectangle.
- GString *getText(int xMin, int yMin, int xMax, int yMax);
-
- GBool isReverseVideo() { return reverseVideo; }
-
- // Update pixmap ID after a page change.
- void setPixmap(Pixmap pixmapA, int pixmapWA, int pixmapHA)
- { pixmap = pixmapA; pixmapW = pixmapWA; pixmapH = pixmapHA; }
-
- // Get the off-screen pixmap, its size, various display info.
- Pixmap getPixmap() { return pixmap; }
- int getPixmapWidth() { return pixmapW; }
- int getPixmapHeight() { return pixmapH; }
- Display *getDisplay() { return display; }
- Guint getDepth() { return depth; }
-
- Gulong findColor(GfxRGB *rgb);
-
-private:
-
- XRef *xref; // the xref table for this PDF file
- Display *display; // X display pointer
- int screenNum; // X screen number
- Pixmap pixmap; // pixmap to draw into
- int pixmapW, pixmapH; // size of pixmap
- Guint depth; // pixmap depth
- Visual *visual; // X visual
- Colormap colormap; // X colormap
- int flatness; // line flatness
- GC paperGC; // GC for background
- GC strokeGC; // GC with stroke color
- GC fillGC; // GC with fill color
- Region clipRegion; // clipping region
- GBool trueColor; // set if using a TrueColor visual
- int rMul, gMul, bMul; // RGB multipliers (for TrueColor)
- int rShift, gShift, bShift; // RGB shifts (for TrueColor)
- Gulong // color cube
- colors[maxRGBCube * maxRGBCube * maxRGBCube];
- unsigned long paperColor; // paper color (pixel value)
- int numColors; // size of color cube
- double redMap[256]; // map pixel (from color cube) to red value
- GBool reverseVideo; // reverse video mode
- XPoint // temporary points array
- tmpPoints[numTmpPoints];
- int // temporary arrays for fill/clip
- tmpLengths[numTmpSubpaths];
- BoundingRect
- tmpRects[numTmpSubpaths];
- GfxFont *gfxFont; // current PDF font
- XOutputFont *font; // current font
- GBool needFontUpdate; // set when the font needs to be updated
- XOutputFontCache *fontCache; // font cache
- T3FontCache * // Type 3 font cache
- t3FontCache[xOutT3FontCacheSize];
- int nT3Fonts; // number of valid entries in t3FontCache
- T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack
- GfxPath *textClipPath; // text outline clipping path
- XOutputState *save; // stack of saved states
-
- TextPage *text; // text from the current page
-
- void updateLineAttrs(GfxState *state, GBool updateDash);
- void doFill(GfxState *state, int rule);
- void doClip(GfxState *state, GfxPath *path, int rule);
- int convertPath(GfxState *state, GfxPath *path,
- XPoint **points, int *size,
- int *numPoints, int **lengths, GBool fillHack);
- void convertSubpath(GfxState *state, GfxSubpath *subpath,
- XPoint **points, int *size, int *n);
- void doCurve(XPoint **points, int *size, int *k,
- double x0, double y0, double x1, double y1,
- double x2, double y2, double x3, double y3);
- void addPoint(XPoint **points, int *size, int *k, int x, int y);
- void drawType3Glyph(T3FontCache *t3Font,
- T3FontCacheTag *tag, Guchar *data,
- double x, double y, GfxRGB *color);
- Gulong findColor(GfxRGB *x, GfxRGB *actual);
-};
-
-#endif
diff --git a/pdf/xpdf/XPixmapOutputDev.cc b/pdf/xpdf/XPixmapOutputDev.cc
deleted file mode 100644
index d55b2d2..0000000
--- a/pdf/xpdf/XPixmapOutputDev.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-//========================================================================
-//
-// XPixmapOutputDev.cc
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include "Object.h"
-#include "GfxState.h"
-#include "XPixmapOutputDev.h"
-
-//------------------------------------------------------------------------
-
-#define xoutRound(x) ((int)(x + 0.5))
-
-//------------------------------------------------------------------------
-
-XPixmapOutputDev::XPixmapOutputDev(Display *displayA, int screenNumA,
- Visual *visualA, Colormap colormapA,
- GBool reverseVideoA, Gulong paperColorA,
- GBool installCmapA, int rgbCubeSizeA,
- GBool incrementalUpdateA,
- void (*redrawCbkA)(void *data),
- void *redrawCbkDataA):
- XOutputDev(displayA, screenNumA, visualA, colormapA,
- reverseVideoA, paperColorA, installCmapA, rgbCubeSizeA)
-{
- incrementalUpdate = incrementalUpdateA;
- redrawCbk = redrawCbkA;
- redrawCbkData = redrawCbkDataA;
-}
-
-XPixmapOutputDev::~XPixmapOutputDev() {
- if (getPixmapWidth() > 0) {
- XFreePixmap(getDisplay(), getPixmap());
- }
-}
-
-void XPixmapOutputDev::clear() {
- startDoc(NULL);
- startPage(0, NULL);
-}
-
-void XPixmapOutputDev::startPage(int pageNum, GfxState *state) {
- int oldPixmapW, oldPixmapH, newPixmapW, newPixmapH;
-
- // resize the off-screen pixmap (if needed)
- oldPixmapW = getPixmapWidth();
- oldPixmapH = getPixmapHeight();
- newPixmapW = xoutRound(state ? state->getPageWidth() : 1);
- newPixmapH = xoutRound(state ? state->getPageHeight() : 1);
- if (oldPixmapW == 0 ||
- newPixmapW != oldPixmapW || newPixmapH != oldPixmapH) {
- if (oldPixmapW > 0) {
- XFreePixmap(getDisplay(), getPixmap());
- }
- setPixmap(XCreatePixmap(getDisplay(), win, newPixmapW, newPixmapH,
- getDepth()),
- newPixmapW, newPixmapH);
- }
-
- XOutputDev::startPage(pageNum, state);
-}
-
-void XPixmapOutputDev::endPage() {
- if (!incrementalUpdate) {
- (*redrawCbk)(redrawCbkData);
- }
- XOutputDev::endPage();
-}
-
-void XPixmapOutputDev::dump() {
- if (incrementalUpdate) {
- (*redrawCbk)(redrawCbkData);
- }
- XOutputDev::dump();
-}
diff --git a/pdf/xpdf/XPixmapOutputDev.h b/pdf/xpdf/XPixmapOutputDev.h
deleted file mode 100644
index 8b83167..0000000
--- a/pdf/xpdf/XPixmapOutputDev.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//========================================================================
-//
-// XPixmapOutputDev.h
-//
-// Copyright 2002-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef XPIXMAPOUTPUTDEV_H
-#define XPIXMAPOUTPUTDEV_H
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include <X11/Xlib.h>
-#include "XOutputDev.h"
-
-//------------------------------------------------------------------------
-
-class XPixmapOutputDev: public XOutputDev {
-public:
-
- XPixmapOutputDev(Display *displayA, int screenNumA,
- Visual *visualA, Colormap colormapA,
- GBool reverseVideoA, Gulong paperColorA,
- GBool installCmapA, int rgbCubeSizeA,
- GBool incrementalUpdateA,
- void (*redrawCbkA)(void *data),
- void *redrawCbkDataA);
-
- ~XPixmapOutputDev();
-
- //----- initialization and control
-
- // Start a page.
- virtual void startPage(int pageNum, GfxState *state);
-
- // End a page.
- virtual void endPage();
-
- // Dump page contents to display.
- virtual void dump();
-
- //----- special access
-
- // Set the window - this is used only to create a compatible pixmap.
- void setWindow(Window winA) { win = winA; }
-
- // Clear out the document (used when displaying an empty window).
- void clear();
-
-private:
-
- GBool incrementalUpdate; // incrementally update the display?
- void (*redrawCbk)(void *data);
- void *redrawCbkData;
- Window win;
-};
-
-#endif
diff --git a/pdf/xpdf/XRef.cc b/pdf/xpdf/XRef.cc
index eca638d..e0d82d2 100644
--- a/pdf/xpdf/XRef.cc
+++ b/pdf/xpdf/XRef.cc
@@ -47,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;
@@ -60,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;
@@ -96,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);
@@ -117,19 +260,16 @@ 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);
@@ -148,175 +288,126 @@ Guint XRef::readTrailer() {
}
}
if (i < 0) {
- goto err1;
+ return 0;
}
for (p = &buf[i+9]; isspace(*p); ++p) ;
- pos = lastXRefPos = strToUnsigned(p);
+ 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)) {
- goto err1;
- }
- pos1 = pos + 4;
- while (1) {
- str->setPos(start + pos1);
- for (i = 0; i < 35; ++i) {
- if ((c = str->getChar()) == EOF) {
- goto err1;
- }
- 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) {
- goto err1;
- }
- pos1 += (p - buf) + n * 20;
- }
- pos1 += 7;
+ 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;
- // read trailer dict
+ // 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 {
- goto err3;
+ str->makeSubStream(start + *pos, gFalse, 0, &obj)));
+ parser->getObj(&obj);
+
+ // parse an old-style xref table
+ if (obj.isCmd("xref")) {
+ obj.free();
+ more = readXRefTable(parser, pos);
+
+ // parse an xref stream
+ } else if (obj.isInt()) {
+ obj.free();
+ if (!parser->getObj(&obj)->isInt()) {
+ goto err1;
}
obj.free();
- trailerDict.dictLookupNF("Root", &obj);
- if (obj.isRef()) {
- rootNum = obj.getRefNum();
- rootGen = obj.getRefGen();
- } else {
- goto err3;
+ 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 {
- goto err2;
+ goto err1;
}
- delete parser;
- // return first xref position
- return pos;
+ delete parser;
+ return more;
- err3:
+ err1:
obj.free();
- err2:
- trailerDict.free();
delete parser;
- err1:
- size = 0;
- return 0;
+ 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;
- }
- 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;
+ if (!obj.isInt()) {
+ goto err1;
}
- 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 = first + n;
+ 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;
@@ -325,20 +416,12 @@ 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();
@@ -351,23 +434,185 @@ GBool XRef::readXRef(Guint *pos) {
} 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;
@@ -377,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;
@@ -391,26 +640,25 @@ GBool XRef::constructXRef() {
// got trailer dictionary
if (!strncmp(p, "trailer", 7)) {
- gotRoot = gFalse;
obj.initNull();
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 {
- trailerDict.free();
}
+ newTrailerDict.free();
delete parser;
// look for object
@@ -439,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;
}
}
}
@@ -610,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,
@@ -623,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/pdf/xpdf/XRef.h b/pdf/xpdf/XRef.h
index 3f5a598..bec487a 100644
--- a/pdf/xpdf/XRef.h
+++ b/pdf/xpdf/XRef.h
@@ -20,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 {
@@ -103,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
@@ -113,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/pdf/xpdf/pdffonts.cc b/pdf/xpdf/pdffonts.cc
index 2fcd1a8..2f17995 100644
--- a/pdf/xpdf/pdffonts.cc
+++ b/pdf/xpdf/pdffonts.cc
@@ -197,8 +197,9 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) {
}
if (gfxFontDict) {
for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
- font = gfxFontDict->getFont(i);
- scanFont(font, doc);
+ if ((font = gfxFontDict->getFont(i))) {
+ scanFont(font, doc);
+ }
}
delete gfxFontDict;
}
@@ -225,9 +226,9 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) {
static void scanFont(GfxFont *font, PDFDoc *doc) {
Ref fontRef, embRef;
- Object fontObj, nameObj, toUnicodeObj;
+ Object fontObj, toUnicodeObj;
GString *name;
- GBool subset, hasToUnicode;
+ GBool emb, subset, hasToUnicode;
int i;
fontRef = *font->getID();
@@ -242,6 +243,13 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
// font name
name = font->getOrigName();
+ // check for an embedded font
+ if (font->getType() == fontType3) {
+ emb = gTrue;
+ } else {
+ emb = font->getEmbeddedFontID(&embRef);
+ }
+
// look for a ToUnicode map
hasToUnicode = gFalse;
if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
@@ -266,7 +274,7 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
printf("%-36s %-12s %-3s %-3s %-3s",
name ? name->getCString() : "[none]",
fontTypeNames[font->getType()],
- font->getEmbeddedFontID(&embRef) ? "yes" : "no",
+ emb ? "yes" : "no",
subset ? "yes" : "no",
hasToUnicode ? "yes" : "no");
if (fontRef.gen >= 100000) {
diff --git a/pdf/xpdf/pdfimages.cc b/pdf/xpdf/pdfimages.cc
index a661fb5..20e1add 100644
--- a/pdf/xpdf/pdfimages.cc
+++ b/pdf/xpdf/pdfimages.cc
@@ -134,7 +134,7 @@ int main(int argc, char *argv[]) {
// write image files
imgOut = new ImageOutputDev(imgRoot, dumpJPEG);
if (imgOut->isOk()) {
- doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, gFalse);
+ doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, gTrue, gFalse);
}
delete imgOut;
diff --git a/pdf/xpdf/pdfinfo.cc b/pdf/xpdf/pdfinfo.cc
index e29e673..4a50fee 100644
--- a/pdf/xpdf/pdfinfo.cc
+++ b/pdf/xpdf/pdfinfo.cc
@@ -33,9 +33,11 @@
static void printInfoString(Dict *infoDict, char *key, char *text,
UnicodeMap *uMap);
static void printInfoDate(Dict *infoDict, char *key, char *text);
+static void printBox(char *text, PDFRectangle *box);
static int firstPage = 1;
static int lastPage = 0;
+static GBool printBoxes = gFalse;
static GBool printMetadata = gFalse;
static char textEncName[128] = "";
static char ownerPassword[33] = "\001";
@@ -49,6 +51,8 @@ static ArgDesc argDesc[] = {
"first page to convert"},
{"-l", argInt, &lastPage, 0,
"last page to convert"},
+ {"-box", argFlag, &printBoxes, 0,
+ "print the page bounding boxes"},
{"-meta", argFlag, &printMetadata, 0,
"print the document metadata (XML)"},
{"-enc", argString, textEncName, sizeof(textEncName),
@@ -77,7 +81,9 @@ int main(int argc, char *argv[]) {
GString *fileName;
GString *ownerPW, *userPW;
UnicodeMap *uMap;
+ Page *page;
Object info;
+ char buf[256];
double w, h, wISO, hISO;
FILE *f;
GString *metadata;
@@ -211,6 +217,32 @@ int main(int argc, char *argv[]) {
printf("\n");
}
+ // print the boxes
+ if (printBoxes) {
+ if (multiPage) {
+ for (pg = firstPage; pg <= lastPage; ++pg) {
+ page = doc->getCatalog()->getPage(pg);
+ sprintf(buf, "Page %4d MediaBox: ", pg);
+ printBox(buf, page->getMediaBox());
+ sprintf(buf, "Page %4d CropBox: ", pg);
+ printBox(buf, page->getCropBox());
+ sprintf(buf, "Page %4d BleedBox: ", pg);
+ printBox(buf, page->getBleedBox());
+ sprintf(buf, "Page %4d TrimBox: ", pg);
+ printBox(buf, page->getTrimBox());
+ sprintf(buf, "Page %4d ArtBox: ", pg);
+ printBox(buf, page->getArtBox());
+ }
+ } else {
+ page = doc->getCatalog()->getPage(firstPage);
+ printBox("MediaBox: ", page->getMediaBox());
+ printBox("CropBox: ", page->getCropBox());
+ printBox("BleedBox: ", page->getBleedBox());
+ printBox("TrimBox: ", page->getTrimBox());
+ printBox("ArtBox: ", page->getArtBox());
+ }
+ }
+
// print file size
#ifdef VMS
f = fopen(fileName->getCString(), "rb", "ctx=stm");
@@ -337,3 +369,8 @@ static void printInfoDate(Dict *infoDict, char *key, char *text) {
}
obj.free();
}
+
+static void printBox(char *text, PDFRectangle *box) {
+ printf("%s%8.2f %8.2f %8.2f %8.2f\n",
+ text, box->x1, box->y1, box->x2, box->y2);
+}
diff --git a/pdf/xpdf/pdftopbm.cc b/pdf/xpdf/pdftopbm.cc
deleted file mode 100644
index a0d0af5..0000000
--- a/pdf/xpdf/pdftopbm.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-//========================================================================
-//
-// pdftopbm.cc
-//
-// Copyright 1998-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include "parseargs.h"
-#include "GString.h"
-#include "gmem.h"
-#include "GlobalParams.h"
-#include "Object.h"
-#include "Stream.h"
-#include "Array.h"
-#include "Dict.h"
-#include "XRef.h"
-#include "Catalog.h"
-#include "Page.h"
-#include "PDFDoc.h"
-#include "PBMOutputDev.h"
-#include "Error.h"
-#include "config.h"
-
-static int firstPage = 1;
-static int lastPage = 0;
-static int resolution = 150;
-static char ownerPassword[33] = "\001";
-static char userPassword[33] = "\001";
-static GBool quiet = gFalse;
-static char cfgFileName[256] = "";
-static GBool printVersion = gFalse;
-static GBool printHelp = gFalse;
-
-static ArgDesc argDesc[] = {
- {"-f", argInt, &firstPage, 0,
- "first page to print"},
- {"-l", argInt, &lastPage, 0,
- "last page to print"},
- {"-r", argInt, &resolution, 0,
- "resolution, in DPI (default is 150)"},
- {"-opw", argString, ownerPassword, sizeof(ownerPassword),
- "owner password (for encrypted files)"},
- {"-upw", argString, userPassword, sizeof(userPassword),
- "user password (for encrypted files)"},
- {"-q", argFlag, &quiet, 0,
- "don't print any messages or errors"},
- {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
- "configuration file to use in place of .xpdfrc"},
- {"-v", argFlag, &printVersion, 0,
- "print copyright and version info"},
- {"-h", argFlag, &printHelp, 0,
- "print usage information"},
- {"-help", argFlag, &printHelp, 0,
- "print usage information"},
- {"--help", argFlag, &printHelp, 0,
- "print usage information"},
- {"-?", argFlag, &printHelp, 0,
- "print usage information"},
- {NULL}
-};
-
-int main(int argc, char *argv[]) {
- PDFDoc *doc;
- GString *fileName;
- char *pbmRoot;
- GString *ownerPW, *userPW;
- PBMOutputDev *pbmOut;
- GBool ok;
- int exitCode;
-
- exitCode = 99;
-
- // parse args
- ok = parseArgs(argDesc, &argc, argv);
- if (!ok || argc != 3 || printVersion || printHelp) {
- fprintf(stderr, "pdftopbm version %s\n", xpdfVersion);
- fprintf(stderr, "%s\n", xpdfCopyright);
- if (!printVersion) {
- printUsage("pdftopbm", "<PDF-file> <PBM-root>", argDesc);
- }
- goto err0;
- }
- fileName = new GString(argv[1]);
- pbmRoot = argv[2];
-
- // read config file
- globalParams = new GlobalParams(cfgFileName);
- if (quiet) {
- globalParams->setErrQuiet(quiet);
- }
-
- // open PDF file
- if (ownerPassword[0] != '\001') {
- ownerPW = new GString(ownerPassword);
- } else {
- ownerPW = NULL;
- }
- if (userPassword[0] != '\001') {
- userPW = new GString(userPassword);
- } else {
- userPW = NULL;
- }
- doc = new PDFDoc(fileName, ownerPW, userPW);
- if (userPW) {
- delete userPW;
- }
- if (ownerPW) {
- delete ownerPW;
- }
- if (!doc->isOk()) {
- exitCode = 1;
- goto err1;
- }
-
- // get page range
- if (firstPage < 1)
- firstPage = 1;
- if (lastPage < 1 || lastPage > doc->getNumPages())
- lastPage = doc->getNumPages();
-
- // write PBM files
- pbmOut = PBMOutputDev::makePBMOutputDev(NULL, pbmRoot);
- pbmOut->startDoc(doc->getXRef());
- doc->displayPages(pbmOut, firstPage, lastPage,
- resolution, resolution, 0, gFalse);
- PBMOutputDev::killPBMOutputDev(pbmOut);
-
- exitCode = 0;
-
- // clean up
- err1:
- delete doc;
- delete globalParams;
- err0:
-
- // check for memory leaks
- Object::memCheck(stderr);
- gMemReport(stderr);
-
- return exitCode;
-}
diff --git a/pdf/xpdf/pdftops.cc b/pdf/xpdf/pdftops.cc
index 247e455..3042006 100644
--- a/pdf/xpdf/pdftops.cc
+++ b/pdf/xpdf/pdftops.cc
@@ -47,6 +47,10 @@ static GBool noEmbedCIDTTFonts = gFalse;
static char paperSize[15] = "";
static int paperWidth = 0;
static int paperHeight = 0;
+static GBool noCrop = gFalse;
+static GBool expand = gFalse;
+static GBool noShrink = gFalse;
+static GBool noCenter = gFalse;
static GBool duplex = gFalse;
static char ownerPassword[33] = "\001";
static char userPassword[33] = "\001";
@@ -56,63 +60,71 @@ static GBool printVersion = gFalse;
static GBool printHelp = gFalse;
static ArgDesc argDesc[] = {
- {"-f", argInt, &firstPage, 0,
+ {"-f", argInt, &firstPage, 0,
"first page to print"},
- {"-l", argInt, &lastPage, 0,
+ {"-l", argInt, &lastPage, 0,
"last page to print"},
- {"-level1", argFlag, &level1, 0,
+ {"-level1", argFlag, &level1, 0,
"generate Level 1 PostScript"},
- {"-level1sep", argFlag, &level1Sep, 0,
+ {"-level1sep", argFlag, &level1Sep, 0,
"generate Level 1 separable PostScript"},
- {"-level2", argFlag, &level2, 0,
+ {"-level2", argFlag, &level2, 0,
"generate Level 2 PostScript"},
- {"-level2sep", argFlag, &level2Sep, 0,
+ {"-level2sep", argFlag, &level2Sep, 0,
"generate Level 2 separable PostScript"},
- {"-level3", argFlag, &level3, 0,
+ {"-level3", argFlag, &level3, 0,
"generate Level 3 PostScript"},
- {"-level3sep", argFlag, &level3Sep, 0,
+ {"-level3sep", argFlag, &level3Sep, 0,
"generate Level 3 separable PostScript"},
- {"-eps", argFlag, &doEPS, 0,
+ {"-eps", argFlag, &doEPS, 0,
"generate Encapsulated PostScript (EPS)"},
- {"-form", argFlag, &doForm, 0,
+ {"-form", argFlag, &doForm, 0,
"generate a PostScript form"},
#if OPI_SUPPORT
- {"-opi", argFlag, &doOPI, 0,
+ {"-opi", argFlag, &doOPI, 0,
"generate OPI comments"},
#endif
- {"-noembt1", argFlag, &noEmbedT1Fonts, 0,
+ {"-noembt1", argFlag, &noEmbedT1Fonts, 0,
"don't embed Type 1 fonts"},
- {"-noembtt", argFlag, &noEmbedTTFonts, 0,
+ {"-noembtt", argFlag, &noEmbedTTFonts, 0,
"don't embed TrueType fonts"},
- {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0,
+ {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0,
"don't embed CID PostScript fonts"},
- {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0,
+ {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0,
"don't embed CID TrueType fonts"},
- {"-paper", argString, paperSize, sizeof(paperSize),
+ {"-paper", argString, paperSize, sizeof(paperSize),
"paper size (letter, legal, A4, A3, match)"},
- {"-paperw", argInt, &paperWidth, 0,
+ {"-paperw", argInt, &paperWidth, 0,
"paper width, in points"},
- {"-paperh", argInt, &paperHeight, 0,
+ {"-paperh", argInt, &paperHeight, 0,
"paper height, in points"},
- {"-duplex", argFlag, &duplex, 0,
+ {"-nocrop", argFlag, &noCrop, 0,
+ "don't crop pages to CropBox"},
+ {"-expand", argFlag, &expand, 0,
+ "expand pages smaller than the paper size"},
+ {"-noshrink", argFlag, &noShrink, 0,
+ "don't shrink pages larger than the paper size"},
+ {"-nocenter", argFlag, &noCenter, 0,
+ "don't center pages smaller than the paper size"},
+ {"-duplex", argFlag, &duplex, 0,
"enable duplex printing"},
- {"-opw", argString, ownerPassword, sizeof(ownerPassword),
+ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
"owner password (for encrypted files)"},
- {"-upw", argString, userPassword, sizeof(userPassword),
+ {"-upw", argString, userPassword, sizeof(userPassword),
"user password (for encrypted files)"},
- {"-q", argFlag, &quiet, 0,
+ {"-q", argFlag, &quiet, 0,
"don't print any messages or errors"},
{"-cfg", argString, cfgFileName, sizeof(cfgFileName),
"configuration file to use in place of .xpdfrc"},
- {"-v", argFlag, &printVersion, 0,
+ {"-v", argFlag, &printVersion, 0,
"print copyright and version info"},
- {"-h", argFlag, &printHelp, 0,
+ {"-h", argFlag, &printHelp, 0,
"print usage information"},
- {"-help", argFlag, &printHelp, 0,
+ {"-help", argFlag, &printHelp, 0,
"print usage information"},
- {"--help", argFlag, &printHelp, 0,
+ {"--help", argFlag, &printHelp, 0,
"print usage information"},
- {"-?", argFlag, &printHelp, 0,
+ {"-?", argFlag, &printHelp, 0,
"print usage information"},
{NULL}
};
@@ -192,6 +204,18 @@ int main(int argc, char *argv[]) {
globalParams->setPSPaperHeight(paperHeight);
}
}
+ if (noCrop) {
+ globalParams->setPSCrop(gFalse);
+ }
+ if (expand) {
+ globalParams->setPSExpandSmaller(gTrue);
+ }
+ if (noShrink) {
+ globalParams->setPSShrinkLarger(gFalse);
+ }
+ if (noCenter) {
+ globalParams->setPSCenter(gFalse);
+ }
if (duplex) {
globalParams->setPSDuplex(duplex);
}
@@ -281,7 +305,8 @@ int main(int argc, char *argv[]) {
psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
doc->getCatalog(), firstPage, lastPage, mode);
if (psOut->isOk()) {
- doc->displayPages(psOut, firstPage, lastPage, 72, 72, 0, gFalse);
+ doc->displayPages(psOut, firstPage, lastPage, 72, 72,
+ 0, globalParams->getPSCrop(), gFalse);
} else {
delete psOut;
exitCode = 2;
diff --git a/pdf/xpdf/pdftotext.cc b/pdf/xpdf/pdftotext.cc
index c6ad9c0..2de03e3 100644
--- a/pdf/xpdf/pdftotext.cc
+++ b/pdf/xpdf/pdftotext.cc
@@ -234,7 +234,7 @@ int main(int argc, char *argv[]) {
textOut = new TextOutputDev(textFileName->getCString(),
physLayout, rawOrder, htmlMeta);
if (textOut->isOk()) {
- doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, gFalse);
+ doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, gTrue, gFalse);
} else {
delete textOut;
exitCode = 2;
diff --git a/pdf/xpdf/vms_make.com b/pdf/xpdf/vms_make.com
index 4a59bda..f4fb74a 100644
--- a/pdf/xpdf/vms_make.com
+++ b/pdf/xpdf/vms_make.com
@@ -18,9 +18,9 @@ $ COMMON_OBJS = "Annot.obj,Array.obj,BuiltinFont.obj," + -
"CMap.obj,Decrypt.obj,Dict.obj,Error.obj," + -
"FontEncodingTables.obj,FontFile.obj," + -
"Function.obj,Gfx.obj,GfxFont.obj,GfxState.obj,"+ -
- "GlobalParams.obj,JBIG2Stream.obj,Lexer.obj," + -
- "Link.obj,NameToCharCode.obj,Object.obj,Outline.obj,"+ -
- "OutputDev.obj,Page.obj,Parser.obj,PDFdoc.obj," + -
+ "GlobalParams.obj,JArithmeticDecoder.obj,JBIG2Stream.obj,"+ -
+ "Lexer.obj,Link.obj,NameToCharCode.obj,Object.obj,"+ -
+ "Outline.obj,OutputDev.obj,Page.obj,Parser.obj,PDFdoc.obj," + -
"PDFDocEncoding.obj,PSTokenizer.obj,Stream.obj," + -
"UnicodeMap.obj,UnicodeTypeTable.obj,XRef.obj"
$ COMMON_LIBS = "[]common.olb/lib,[-.goo]libgoo.olb/lib"
diff --git a/pdf/xpdf/xpdf.cc b/pdf/xpdf/xpdf.cc
index bda355e..0824e4c 100644
--- a/pdf/xpdf/xpdf.cc
+++ b/pdf/xpdf/xpdf.cc
@@ -21,8 +21,9 @@
// command line options
//------------------------------------------------------------------------
-static char t1libControlStr[16] = "";
-static char freetypeControlStr[16] = "";
+static char enableT1libStr[16] = "";
+static char enableFreeTypeStr[16] = "";
+static char antialiasStr[16] = "";
static char psFileArg[256];
static char paperSize[15] = "";
static int paperWidth = 0;
@@ -61,13 +62,15 @@ static ArgDesc argDesc[] = {
{"-z", argStringDummy, NULL, 0,
"initial zoom level (percent, 'page', 'width')"},
#if HAVE_T1LIB_H
- {"-t1lib", argString, t1libControlStr, sizeof(t1libControlStr),
- "t1lib font rasterizer control: none, plain, low, high"},
+ {"-t1lib", argString, enableT1libStr, sizeof(enableT1libStr),
+ "enable t1lib font rasterizer: yes, no"},
#endif
#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
- {"-freetype", argString, freetypeControlStr, sizeof(freetypeControlStr),
- "FreeType font rasterizer control: none, plain, low, high"},
+ {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr),
+ "enable FreeType font rasterizer: yes, no"},
#endif
+ {"-aa", argString, antialiasStr, sizeof(antialiasStr),
+ "enable font anti-aliasing: yes, no"},
{"-ps", argString, psFileArg, sizeof(psFileArg),
"default PostScript file name or command"},
{"-paper", argString, paperSize, sizeof(paperSize),
@@ -131,9 +134,19 @@ int main(int argc, char *argv[]) {
// parse args
ok = parseArgs(argDesc, &argc, argv);
+ if (!ok || printVersion || printHelp) {
+ fprintf(stderr, "xpdf version %s\n", xpdfVersion);
+ fprintf(stderr, "%s\n", xpdfCopyright);
+ if (!printVersion) {
+ printUsage("xpdf", "[<PDF-file> [<page> | +<dest>]]", argDesc);
+ }
+ exitCode = 99;
+ goto done0;
+ }
// read config file
globalParams = new GlobalParams(cfgFileName);
+ globalParams->setupBaseFonts(NULL);
if (psFileArg[0]) {
globalParams->setPSFile(psFileArg);
}
@@ -160,16 +173,21 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Bad '-eol' value on command line\n");
}
}
- if (t1libControlStr[0]) {
- if (!globalParams->setT1libControl(t1libControlStr)) {
+ if (enableT1libStr[0]) {
+ if (!globalParams->setEnableT1lib(enableT1libStr)) {
fprintf(stderr, "Bad '-t1lib' value on command line\n");
}
}
- if (freetypeControlStr[0]) {
- if (!globalParams->setFreeTypeControl(freetypeControlStr)) {
+ if (enableFreeTypeStr[0]) {
+ if (!globalParams->setEnableFreeType(enableFreeTypeStr)) {
fprintf(stderr, "Bad '-freetype' value on command line\n");
}
}
+ if (antialiasStr[0]) {
+ if (!globalParams->setAntialias(antialiasStr)) {
+ fprintf(stderr, "Bad '-aa' value on command line\n");
+ }
+ }
if (printCommands) {
globalParams->setPrintCommands(printCommands);
}
@@ -290,6 +308,7 @@ int main(int argc, char *argv[]) {
delete globalParams;
// check for memory leaks
+ done0:
Object::memCheck(stderr);
gMemReport(stderr);
diff --git a/pdf/xpdf/xpdfconfig.h b/pdf/xpdf/xpdfconfig.h
index ef08a7f..bf6baf4 100644
--- a/pdf/xpdf/xpdfconfig.h
+++ b/pdf/xpdf/xpdfconfig.h
@@ -2,7 +2,7 @@
//
// config.h
//
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2004 Glyph & Cog, LLC
//
//========================================================================
@@ -14,23 +14,23 @@
//------------------------------------------------------------------------
// xpdf version
-#define xpdfVersion "2.03"
-#define xpdfVersionNum 2.03
-#define xpdfMajorVersion 2
-#define xpdfMinorVersion 3
-#define xpdfMajorVersionStr "2"
-#define xpdfMinorVersionStr "3"
+#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-2003 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2004 Glyph & Cog, LLC"
// Windows resource file stuff
-#define winxpdfVersion "WinXpdf 2.03"
-#define xpdfCopyrightAmp "Copyright 1996-2003 Glyph && Cog, LLC"
+#define winxpdfVersion "WinXpdf 3.00"
+#define xpdfCopyrightAmp "Copyright 1996-2004 Glyph && Cog, LLC"
//------------------------------------------------------------------------
// paper size