//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
int j;
if (n > 0) {
- for (j = i; j <= length - n; ++j)
+ if (i + n > length) {
+ n = length - i;
+ }
+ for (j = i; j <= length - n; ++j) {
s[j] = s[j + n];
+ }
resize(length -= n);
}
return this;
#ifndef GSTRING_H
#define GSTRING_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
#ifndef ARRAY_H
#define ARRAY_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
// Catalog
//------------------------------------------------------------------------
-Catalog::Catalog(XRef *xrefA, GBool printCommands) {
+Catalog::Catalog(XRef *xrefA) {
Object catDict, pagesDict;
Object obj, obj2;
int numPages0;
pageRefs[i].num = -1;
pageRefs[i].gen = -1;
}
- numPages = readPageTree(pagesDict.getDict(), NULL, 0, printCommands);
+ numPages = readPageTree(pagesDict.getDict(), NULL, 0);
if (numPages != numPages0) {
error(-1, "Page count in top-level pages object is incorrect");
}
// get the structure tree root
catDict.dictLookup("StructTreeRoot", &structTreeRoot);
+ // get the outline dictionary
+ catDict.dictLookup("Outlines", &outline);
+
catDict.free();
return;
}
metadata.free();
structTreeRoot.free();
+ outline.free();
}
GString *Catalog::readMetadata() {
return s;
}
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
- GBool printCommands) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
Object kids;
Object kid;
Object kidRef;
kids.arrayGet(i, &kid);
if (kid.isDict("Page")) {
attrs2 = new PageAttrs(attrs1, kid.getDict());
- page = new Page(xref, start+1, kid.getDict(), attrs2, printCommands);
+ page = new Page(xref, start+1, kid.getDict(), attrs2);
if (!page->isOk()) {
++start;
goto err3;
// This should really be isDict("Pages"), but I've seen at least one
// PDF file where the /Type entry is missing.
} else if (kid.isDict()) {
- if ((start = readPageTree(kid.getDict(), attrs1, start, printCommands))
+ if ((start = readPageTree(kid.getDict(), attrs1, start))
< 0)
goto err2;
} else {
error(-1, "Bad named destination value");
}
obj1.free();
+ if (dest && !dest->isOk()) {
+ delete dest;
+ dest = NULL;
+ }
return dest;
}
#ifndef CATALOG_H
#define CATALOG_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
public:
// Constructor.
- Catalog(XRef *xrefA, GBool printCommands = gFalse);
+ Catalog(XRef *xrefA);
// Destructor.
~Catalog();
// NULL if <name> is not a destination.
LinkDest *findDest(GString *name);
+ Object *getOutline() { return &outline; }
+
private:
XRef *xref; // the xref table for this PDF file
GString *baseURI; // base URI for URI-type links
Object metadata; // metadata stream
Object structTreeRoot; // structure tree root dictionary
+ Object outline; // outline dictionary
GBool ok; // true if catalog is valid
- int readPageTree(Dict *pages, PageAttrs *attrs, int start,
- GBool printCommands);
+ int readPageTree(Dict *pages, PageAttrs *attrs, int start);
Object *findDestInTree(Object *tree, GString *name, Object *obj);
};
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
#ifndef DICT_H
#define DICT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#ifndef ERROR_H
#define ERROR_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#pragma implementation
#endif
+#include <locale.h>
#include <math.h>
#include <stdlib.h>
#include <stddef.h>
}
} while (i < 64);
buf[i] = '\0';
- x = atof(buf);
+ {
+ char *theLocale = setlocale(LC_NUMERIC, "C");
+ x = atof(buf);
+ setlocale(LC_NUMERIC, theLocale);
+ }
*isFP = gTrue;
} else if (b0 == 31) {
x = 0;
#pragma implementation
#endif
+#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
resizeCode(*codePtr);
if (isReal) {
code[*codePtr].type = psReal;
- code[*codePtr].real = atof(tok->getCString());
+ {
+ char *theLocale = setlocale(LC_NUMERIC, "C");
+ code[*codePtr].real = atof(tok->getCString());
+ setlocale(LC_NUMERIC, theLocale);
+ }
} else {
code[*codePtr].type = psInt;
code[*codePtr].intg = atoi(tok->getCString());
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include "gmem.h"
+#include "GlobalParams.h"
#include "CharTypes.h"
#include "Object.h"
#include "Array.h"
Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
- GBool printCommandsA) {
+ GBool (*abortCheckCbkA)(void *data),
+ void *abortCheckCbkDataA) {
int i;
xref = xrefA;
subPage = gFalse;
- printCommands = printCommandsA;
+ printCommands = globalParams->getPrintCommands();
// start the resource stack
res = new GfxResources(xref, resDict, NULL);
for (i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
}
+ abortCheckCbk = abortCheckCbkA;
+ abortCheckCbkData = abortCheckCbkDataA;
// set crop box
if (crop) {
}
Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
- PDFRectangle *box, GBool crop, PDFRectangle *cropBox) {
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox,
+ GBool (*abortCheckCbkA)(void *data),
+ void *abortCheckCbkDataA) {
int i;
xref = xrefA;
subPage = gTrue;
- printCommands = gFalse;
+ printCommands = globalParams->getPrintCommands();
// start the resource stack
res = new GfxResources(xref, resDict, NULL);
for (i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
}
+ abortCheckCbk = abortCheckCbkA;
+ abortCheckCbkData = abortCheckCbkDataA;
// set crop box
if (crop) {
void Gfx::go(GBool topLevel) {
Object obj;
Object args[maxArgs];
- int numArgs;
- int i;
+ int numArgs, i;
+ int lastAbortCheck;
// scan a sequence of objects
- updateLevel = 0;
+ updateLevel = lastAbortCheck = 0;
numArgs = 0;
parser->getObj(&obj);
while (!obj.isEOF()) {
updateLevel = 0;
}
+ // check for an abort
+ if (abortCheckCbk) {
+ if (updateLevel - lastAbortCheck > 10) {
+ if ((*abortCheckCbk)(abortCheckCbkData)) {
+ break;
+ }
+ lastAbortCheck = updateLevel;
+ }
+ }
+
// got an argument - save it
} else if (numArgs < maxArgs) {
args[numArgs++] = obj;
int i;
// find operator
- name = cmd->getName();
+ name = cmd->getCmd();
if (!(op = findOp(name))) {
if (ignoreUndef == 0)
error(getPos(), "Unknown operator '%s'", name);
#ifndef GFX_H
#define GFX_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
class GfxRadialShading;
class GfxState;
class Gfx;
-struct PDFRectangle;
+class PDFRectangle;
//------------------------------------------------------------------------
// Gfx
// Constructor for regular output.
Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, double dpi,
PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
- GBool printCommandsA);
+ GBool (*abortCheckCbkA)(void *data) = NULL,
+ void *abortCheckCbkDataA = NULL);
// Constructor for a sub-page object.
Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
- PDFRectangle *box, GBool crop, PDFRectangle *cropBox);
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox,
+ GBool (*abortCheckCbkA)(void *data) = NULL,
+ void *abortCheckCbkDataA = NULL);
~Gfx();
Parser *parser; // parser for page content stream(s)
+ GBool // callback to check for an abort
+ (*abortCheckCbk)(void *data);
+ void *abortCheckCbkData;
+
static Operator opTab[]; // table of operators
void go(GBool topLevel);
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
if (!baseEnc) {
if (builtinFont) {
baseEnc = builtinFont->defaultBaseEnc;
+ hasEncoding = gTrue;
} else if (type == fontTrueType) {
- baseEnc = macRomanEncoding;
+ baseEnc = winAnsiEncoding;
} else {
baseEnc = standardEncoding;
}
GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) {
int i;
Object obj1, obj2;
+ Ref r;
numFonts = fontDict->getLength();
fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
for (i = 0; i < numFonts; ++i) {
fontDict->getValNF(i, &obj1);
obj1.fetch(xref, &obj2);
- if (obj1.isRef() && obj2.isDict()) {
+ if (obj2.isDict()) {
+ if (obj1.isRef()) {
+ r = obj1.getRef();
+ } else {
+ // no indirect reference for this font, so invent a unique one
+ // (legal generation numbers are five digits, so any 6-digit
+ // number would be safe)
+ r.num = i;
+ r.gen = 999999;
+ }
fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
- obj1.getRef(), obj2.getDict());
+ r, obj2.getDict());
if (fonts[i] && !fonts[i]->isOk()) {
delete fonts[i];
fonts[i] = NULL;
}
} else {
- error(-1, "font resource is not a dictionary reference");
+ error(-1, "font resource is not a dictionary");
fonts[i] = NULL;
}
obj1.free();
#ifndef GFXFONT_H
#define GFXFONT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <math.h>
#include <string.h> // for memcpy()
void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
Guchar *p;
GfxColor color2;
+ double low[gfxColorMaxComps], range[gfxColorMaxComps];
int n, i;
n = base->getNComps();
+ base->getDefaultRanges(low, range, indexHigh);
p = &lookup[(int)(color->c[0] + 0.5) * n];
for (i = 0; i < n; ++i) {
- color2.c[i] = p[i] / 255.0;
+ color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
}
base->getGray(&color2, gray);
}
void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
Guchar *p;
GfxColor color2;
+ double low[gfxColorMaxComps], range[gfxColorMaxComps];
int n, i;
n = base->getNComps();
+ base->getDefaultRanges(low, range, indexHigh);
p = &lookup[(int)(color->c[0] + 0.5) * n];
for (i = 0; i < n; ++i) {
- color2.c[i] = p[i] / 255.0;
+ color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
}
base->getRGB(&color2, rgb);
}
void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
Guchar *p;
GfxColor color2;
+ double low[gfxColorMaxComps], range[gfxColorMaxComps];
int n, i;
n = base->getNComps();
+ base->getDefaultRanges(low, range, indexHigh);
p = &lookup[(int)(color->c[0] + 0.5) * n];
for (i = 0; i < n; ++i) {
- color2.c[i] = p[i] / 255.0;
+ color2.c[i] = low[i] + (p[i] / 255.0) * range[i];
}
base->getCMYK(&color2, cmyk);
}
nComps2 = colorSpace2->getNComps();
lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
lookup2 = indexedCS->getLookup();
+ colorSpace2->getDefaultRanges(x, y, indexHigh);
for (i = 0; i <= indexHigh; ++i) {
- j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
+ j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
for (k = 0; k < nComps2; ++k) {
- lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
+ lookup[j*nComps2 + k] = x[k] + (lookup2[i*nComps2 + k] / 255.0) * y[k];
}
}
} else if (colorSpace->getMode() == csSeparation) {
#ifndef GFXSTATE_H
#define GFXSTATE_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
class Array;
class GfxFont;
-struct PDFRectangle;
+class PDFRectangle;
//------------------------------------------------------------------------
// GfxColor
virtual int getNComps() { return nComps; }
// DeviceN-specific access.
+ GString *getColorantName(int i) { return names[i]; }
GfxColorSpace *getAlt() { return alt; }
+ Function *getTintTransformFunc() { return func; }
private:
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int *maskColors, GBool inlineImg) {
FILE *f;
ImageStream *imgStr;
- Guchar pixBuf[4];
+ Guchar *p;
GfxRGB rgb;
int x, y;
int c;
// copy the stream
size = height * ((width + 7) / 8);
for (i = 0; i < size; ++i) {
- fputc(str->getChar(), f);
+ fputc(str->getChar() ^ 0xff, f);
}
str->close();
for (y = 0; y < height; ++y) {
// write the line
+ p = imgStr->getLine();
for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getRGB(pixBuf, &rgb);
+ colorMap->getRGB(p, &rgb);
fputc((int)(rgb.r * 255 + 0.5), f);
fputc((int)(rgb.g * 255 + 0.5), f);
fputc((int)(rgb.b * 255 + 0.5), f);
+ p += colorMap->getNumPixelComps();
}
}
delete imgStr;
#ifndef IMAGEOUTPUTDEV_H
#define IMAGEOUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
+++ /dev/null
-//========================================================================
-//
-// LTKOutputDev.cc
-//
-// Copyright 1998-2002 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifdef __GNUC__
-#pragma implementation
-#endif
-
-#include <aconf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include "gmem.h"
-#include "GString.h"
-#include "LTKWindow.h"
-#include "LTKScrollingCanvas.h"
-#include "Object.h"
-#include "Stream.h"
-#include "GfxState.h"
-#include "GfxFont.h"
-#include "Error.h"
-#include "LTKOutputDev.h"
-
-//------------------------------------------------------------------------
-
-LTKOutputDev::LTKOutputDev(LTKWindow *winA, GBool reverseVideoA,
- unsigned long paperColor, GBool installCmap,
- GBool rgbCubeSize, GBool incrementalUpdateA):
- XOutputDev(winA->getDisplay(),
- ((LTKScrollingCanvas *)winA->findWidget("canvas"))->getPixmap(),
- 0, winA->getColormap(), reverseVideoA, paperColor,
- installCmap, rgbCubeSize)
-{
- win = winA;
- canvas = (LTKScrollingCanvas *)win->findWidget("canvas");
- setPixmap(canvas->getPixmap(),
- canvas->getRealWidth(), canvas->getRealHeight());
- incrementalUpdate = incrementalUpdateA;
-}
-
-LTKOutputDev::~LTKOutputDev() {
-}
-
-void LTKOutputDev::startPage(int pageNum, GfxState *state) {
- canvas->resize((int)(state->getPageWidth() + 0.5),
- (int)(state->getPageHeight() + 0.5));
- setPixmap(canvas->getPixmap(),
- canvas->getRealWidth(), canvas->getRealHeight());
- XOutputDev::startPage(pageNum, state);
- if (incrementalUpdate) {
- canvas->redraw();
- }
-}
-
-void LTKOutputDev::endPage() {
- if (!incrementalUpdate) {
- canvas->redraw();
- }
- XOutputDev::endPage();
-}
-
-void LTKOutputDev::dump() {
- if (incrementalUpdate) {
- canvas->redraw();
- }
- XOutputDev::dump();
-}
+++ /dev/null
-//========================================================================
-//
-// LTKOutputDev.h
-//
-// Copyright 1998-2002 Glyph & Cog, LLC
-//
-//========================================================================
-
-#ifndef LTKOUTPUTDEV_H
-#define LTKOUTPUTDEV_H
-
-#ifdef __GNUC__
-#pragma interface
-#endif
-
-#include <stddef.h>
-#include "config.h"
-#include "XOutputDev.h"
-
-class LTKApp;
-class LTKWindow;
-
-//------------------------------------------------------------------------
-
-class LTKOutputDev: public XOutputDev {
-public:
-
- LTKOutputDev(LTKWindow *winA, GBool reverseVideoA,
- unsigned long paperColor, GBool installCmap,
- GBool rgbCubeSize, GBool incrementalUpdateA);
-
- ~LTKOutputDev();
-
- //----- 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();
-
-private:
-
- LTKWindow *win; // window
- LTKScrollingCanvas *canvas; // drawing canvas
- GBool incrementalUpdate; // incrementally update the display?
-};
-
-#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#ifndef LEXER_H
#define LEXER_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
#include "Link.h"
//------------------------------------------------------------------------
+// LinkAction
+//------------------------------------------------------------------------
+
+LinkAction *LinkAction::parseDest(Object *obj) {
+ LinkAction *action;
+
+ action = new LinkGoTo(obj);
+ if (!action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
+ LinkAction *action;
+ Object obj2, obj3, obj4;
+
+ if (!obj->isDict()) {
+ error(-1, "Bad annotation action");
+ return NULL;
+ }
+
+ obj->dictLookup("S", &obj2);
+
+ // GoTo action
+ if (obj2.isName("GoTo")) {
+ obj->dictLookup("D", &obj3);
+ action = new LinkGoTo(&obj3);
+ obj3.free();
+
+ // GoToR action
+ } else if (obj2.isName("GoToR")) {
+ obj->dictLookup("F", &obj3);
+ obj->dictLookup("D", &obj4);
+ action = new LinkGoToR(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // Launch action
+ } else if (obj2.isName("Launch")) {
+ action = new LinkLaunch(obj);
+
+ // URI action
+ } else if (obj2.isName("URI")) {
+ obj->dictLookup("URI", &obj3);
+ action = new LinkURI(&obj3, baseURI);
+ obj3.free();
+
+ // Named action
+ } else if (obj2.isName("Named")) {
+ obj->dictLookup("N", &obj3);
+ action = new LinkNamed(&obj3);
+ obj3.free();
+
+ // Movie action
+ } else if (obj2.isName("Movie")) {
+ obj->dictLookupNF("Annot", &obj3);
+ obj->dictLookup("T", &obj4);
+ action = new LinkMovie(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // unknown action
+ } else if (obj2.isName()) {
+ action = new LinkUnknown(obj2.getName());
+
+ // action is missing or wrong type
+ } else {
+ error(-1, "Bad annotation action");
+ action = NULL;
+ }
-static GString *getFileSpecName(Object *fileSpecObj);
+ obj2.free();
+
+ if (action && !action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
+ GString *name;
+ Object obj1;
+
+ name = NULL;
+
+ // string
+ if (fileSpecObj->isString()) {
+ name = fileSpecObj->getString()->copy();
+
+ // dictionary
+ } else if (fileSpecObj->isDict()) {
+ if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
+ obj1.free();
+ fileSpecObj->dictLookup("F", &obj1);
+ }
+ if (obj1.isString())
+ name = obj1.getString()->copy();
+ else
+ error(-1, "Illegal file spec in link");
+ obj1.free();
+
+ // error
+ } else {
+ error(-1, "Illegal file spec in link");
+ }
+
+ return name;
+}
//------------------------------------------------------------------------
// LinkDest
ok = gFalse;
// get page
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array has wrong length");
+ return;
+ }
a->getNF(0, &obj1);
if (obj1.isInt()) {
pageNum = obj1.getInt() + 1;
// XYZ link
if (obj1.isName("XYZ")) {
+ if (a->getLength() != 5) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destXYZ;
a->get(2, &obj2);
if (obj2.isNull()) {
// Fit link
} else if (obj1.isName("Fit")) {
+ if (a->getLength() != 2) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFit;
// FitH link
} else if (obj1.isName("FitH")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
// FitV link
} else if (obj1.isName("FitV")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
// FitR link
} else if (obj1.isName("FitR")) {
+ if (a->getLength() != 6) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitR;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
// FitB link
} else if (obj1.isName("FitB")) {
+ if (a->getLength() != 2) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitB;
// FitBH link
} else if (obj1.isName("FitBH")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitBH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
// FitBV link
} else if (obj1.isName("FitBV")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitBV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
fileName = getFileSpecName(&obj1);
} else {
obj1.free();
+#ifdef WIN32
+ if (actionObj->dictLookup("Win", &obj1)->isDict()) {
+ obj1.dictLookup("F", &obj2);
+ fileName = getFileSpecName(&obj2);
+ obj2.free();
+ if (obj1.dictLookup("P", &obj2)->isString()) {
+ params = obj2.getString()->copy();
+ }
+ obj2.free();
+ } else {
+ error(-1, "Bad launch-type link action");
+ }
+#else
//~ This hasn't been defined by Adobe yet, so assume it looks
//~ just like the Win dictionary until they say otherwise.
if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
obj1.dictLookup("F", &obj2);
fileName = getFileSpecName(&obj2);
obj2.free();
- if (obj1.dictLookup("P", &obj2)->isString())
+ if (obj1.dictLookup("P", &obj2)->isString()) {
params = obj2.getString()->copy();
+ }
obj2.free();
} else {
error(-1, "Bad launch-type link action");
}
+#endif
}
obj1.free();
}
}
}
+//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
+ annotRef.num = -1;
+ title = NULL;
+ if (annotObj->isRef()) {
+ annotRef = annotObj->getRef();
+ } else if (titleObj->isString()) {
+ title = titleObj->getString()->copy();
+ } else {
+ error(-1, "Movie action is missing both the Annot and T keys");
+ }
+}
+
+LinkMovie::~LinkMovie() {
+ if (title) {
+ delete title;
+ }
+}
+
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
//------------------------------------------------------------------------
Link::Link(Dict *dict, GString *baseURI) {
- Object obj1, obj2, obj3, obj4;
+ Object obj1, obj2;
double t;
action = NULL;
// look for destination
if (!dict->lookup("Dest", &obj1)->isNull()) {
- action = new LinkGoTo(&obj1);
+ action = LinkAction::parseDest(&obj1);
// look for action
} else {
obj1.free();
if (dict->lookup("A", &obj1)->isDict()) {
- obj1.dictLookup("S", &obj2);
-
- // GoTo action
- if (obj2.isName("GoTo")) {
- obj1.dictLookup("D", &obj3);
- action = new LinkGoTo(&obj3);
- obj3.free();
-
- // GoToR action
- } else if (obj2.isName("GoToR")) {
- obj1.dictLookup("F", &obj3);
- obj1.dictLookup("D", &obj4);
- action = new LinkGoToR(&obj3, &obj4);
- obj3.free();
- obj4.free();
-
- // Launch action
- } else if (obj2.isName("Launch")) {
- action = new LinkLaunch(&obj1);
-
- // URI action
- } else if (obj2.isName("URI")) {
- obj1.dictLookup("URI", &obj3);
- action = new LinkURI(&obj3, baseURI);
- obj3.free();
-
- // Named action
- } else if (obj2.isName("Named")) {
- obj1.dictLookup("N", &obj3);
- action = new LinkNamed(&obj3);
- obj3.free();
-
- // unknown action
- } else if (obj2.isName()) {
- action = new LinkUnknown(obj2.getName());
-
- // action is missing or wrong type
- } else {
- error(-1, "Bad annotation action");
- action = NULL;
- }
-
- obj2.free();
-
- } else {
- error(-1, "Missing annotation destination/action");
- action = NULL;
+ action = LinkAction::parseAction(&obj1, baseURI);
}
}
obj1.free();
// check for bad action
- if (action && action->isOk())
+ if (action) {
ok = gTrue;
+ }
return;
}
return gFalse;
}
-
-//------------------------------------------------------------------------
-
-// Extract a file name from a file specification (string or dictionary).
-static GString *getFileSpecName(Object *fileSpecObj) {
- GString *name;
- Object obj1;
-
- name = NULL;
-
- // string
- if (fileSpecObj->isString()) {
- name = fileSpecObj->getString()->copy();
-
- // dictionary
- } else if (fileSpecObj->isDict()) {
- if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
- obj1.free();
- fileSpecObj->dictLookup("F", &obj1);
- }
- if (obj1.isString())
- name = obj1.getString()->copy();
- else
- error(-1, "Illegal file spec in link");
- obj1.free();
-
- // error
- } else {
- error(-1, "Illegal file spec in link");
- }
-
- return name;
-}
#ifndef LINK_H
#define LINK_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
actionLaunch, // launch app (or open document)
actionURI, // URI
actionNamed, // named action
+ actionMovie, // movie action
actionUnknown // anything else
};
// Check link action type.
virtual LinkActionKind getKind() = 0;
+
+ // Parse a destination (old-style action) name, string, or array.
+ static LinkAction *parseDest(Object *obj);
+
+ // Parse an action dictionary.
+ static LinkAction *parseAction(Object *obj, GString *baseURI = NULL);
+
+ // Extract a file name from a file specification (string or
+ // dictionary).
+ static GString *getFileSpecName(Object *fileSpecObj);
};
//------------------------------------------------------------------------
GString *name;
};
+//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+class LinkMovie: public LinkAction {
+public:
+
+ LinkMovie(Object *annotObj, Object *titleObj);
+
+ virtual ~LinkMovie();
+
+ virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; }
+
+ virtual LinkActionKind getKind() { return actionMovie; }
+ GBool hasAnnotRef() { return annotRef.num >= 0; }
+ Ref *getAnnotRef() { return &annotRef; }
+ GString *getTitle() { return title; }
+
+private:
+
+ Ref annotRef;
+ GString *title;
+};
+
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
INCLUDES = \
-I$(top_srcdir)/goo \
- -I$(top_srcdir)/ltk \
-DDATADIR=\""$(datadir)"\" \
-DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DGNOMEICONDIR=\""$(datadir)/pixmaps"\" \
GfxState.h \
GlobalParams.cc \
GlobalParams.h \
+ JBIG2Stream.cc \
+ JBIG2Stream.h \
Lexer.cc \
Lexer.h \
Link.cc \
NameToUnicodeTable.h \
Object.cc \
Object.h \
+ Outline.cc \
+ Outline.h \
OutputDev.cc \
OutputDev.h \
PDFDoc.cc \
PDFDoc.h \
+ PDFDocEncoding.cc \
+ PDFDocEncoding.h \
PSTokenizer.cc \
PSTokenizer.h \
Page.cc \
xpdf_SOURCES = \
$(common_sources) \
+ XPDFApp.cc \
+ XPDFApp.h \
+ XPDFCore.cc \
+ XPDFCore.h \
+ XPDFTree.cc \
+ XPDFTree.h \
+ XPDFViewer.cc \
+ XPDFViewer.h \
XOutputDev.cc \
- LTKOutputDev.cc \
+ XOutputDev.h \
+ XPixmapOutputDev.cc \
+ XPixmapOutputDev.h \
PSOutputDev.cc \
PSOutputDev.h \
xpdf.cc
xpdf_CFLAGS = $(X_CFLAGS)
xpdf_LDADD = \
$(top_builddir)/goo/libgoo.a \
- $(top_builddir)/ltk/libltk.a \
-lXpm \
$(EXTRA_GNOME_LIBS) \
$(libpaper_LIBS)
#pdftopbm_LDADD = ../goo/libgoo.a $(EXTRA_GNOME_LIBS)
-xpdf-ltk.h: xpdf.ltk
- rm -f $@
- $(top_srcdir)/ltk/ltkbuild <xpdf.ltk >$@.new
- mv $@.new $@
-
#bitmaps =
# about.xbm
# dblLeftArrow.xbm
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
#ifndef OBJECT_H
#define OBJECT_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
Ref getRef() { return ref; }
int getRefNum() { return ref.num; }
int getRefGen() { return ref.gen; }
+ char *getCmd() { return cmd; }
// Array accessors.
int arrayGetLength();
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Stream.h"
#ifndef OUTPUTDEV_H
#define OUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
PBMOutputDev::PBMOutputDev(Display *displayA, int screenA,
Pixmap pixmapA, Window dummyWinA,
int invertA, char *fileRootA):
- XOutputDev(displayA, pixmapA, 1,
- DefaultColormap(displayA, screenA), gFalse,
+ XOutputDev(displayA, screenA,
+ DefaultVisual(displayA, screenA),
+ DefaultColormap(displayA, screenA),
+ gFalse,
WhitePixel(displayA, DefaultScreen(displayA)),
- gFalse, 1)
+ gFalse, 1, 1)
{
display = displayA;
screen = screenA;
#ifndef PBMOUTPUTDEV_H
#define PBMOUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GString.h"
#include "config.h"
+#include "GlobalParams.h"
#include "Page.h"
#include "Catalog.h"
#include "Stream.h"
#include "ErrorCodes.h"
#include "Lexer.h"
#include "Parser.h"
+#ifndef DISABLE_OUTLINE
+#include "Outline.h"
+#endif
#include "PDFDoc.h"
//------------------------------------------------------------------------
//------------------------------------------------------------------------
PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
- GString *userPassword, GBool printCommandsA) {
+ GString *userPassword) {
Object obj;
- GString *fileName2;
+ GString *fileName1, *fileName2;
ok = gFalse;
errCode = errNone;
xref = NULL;
catalog = NULL;
links = NULL;
- printCommands = printCommandsA;
+#ifndef DISABLE_OUTLINE
+ outline = NULL;
+#endif
- // try to open file
fileName = fileNameA;
+ fileName1 = fileName;
+
+
+ // try to open file
fileName2 = NULL;
#ifdef VMS
- if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
- error(-1, "Couldn't open file '%s'", fileName->getCString());
+ if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
+ error(-1, "Couldn't open file '%s'", fileName1->getCString());
errCode = errOpenFile;
return;
}
#else
- if (!(file = fopen(fileName->getCString(), "rb"))) {
+ if (!(file = fopen(fileName1->getCString(), "rb"))) {
fileName2 = fileName->copy();
fileName2->lowerCase();
if (!(file = fopen(fileName2->getCString(), "rb"))) {
}
PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
- GString *userPassword, GBool printCommandsA) {
+ GString *userPassword) {
ok = gFalse;
errCode = errNone;
fileName = NULL;
xref = NULL;
catalog = NULL;
links = NULL;
- printCommands = printCommandsA;
+#ifndef DISABLE_OUTLINE
+ outline = NULL;
+#endif
ok = setup(ownerPassword, userPassword);
}
}
// read catalog
- catalog = new Catalog(xref, printCommands);
+ catalog = new Catalog(xref);
if (!catalog->isOk()) {
error(-1, "Couldn't read page catalog");
errCode = errBadCatalog;
return gFalse;
}
+#ifndef DISABLE_OUTLINE
+ // read outline
+ outline = new Outline(catalog->getOutline(), xref);
+#endif
+
// done
return gTrue;
}
PDFDoc::~PDFDoc() {
+#ifndef DISABLE_OUTLINE
+ if (outline) {
+ delete outline;
+ }
+#endif
if (catalog) {
delete catalog;
}
}
void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
- int rotate, GBool doLinks) {
+ int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
Page *p;
- if (printCommands) {
+ if (globalParams->getPrintCommands()) {
printf("***** page %d *****\n", page);
}
p = catalog->getPage(page);
links = NULL;
}
getLinks(p);
- p->display(out, zoom, rotate, links, catalog);
+ p->display(out, zoom, rotate, links, catalog,
+ abortCheckCbk, abortCheckCbkData);
} else {
- p->display(out, zoom, rotate, NULL, catalog);
+ p->display(out, zoom, rotate, NULL, catalog,
+ abortCheckCbk, abortCheckCbkData);
}
}
void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
- int zoom, int rotate, GBool doLinks) {
+ int zoom, int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
int page;
for (page = firstPage; page <= lastPage; ++page) {
- displayPage(out, page, zoom, rotate, doLinks);
+ displayPage(out, page, zoom, rotate, doLinks,
+ abortCheckCbk, abortCheckCbkData);
}
}
+void PDFDoc::displayPageSlice(OutputDev *out, int page, double zoom,
+ int rotate, int sliceX, int sliceY,
+ int sliceW, int sliceH,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ Page *p;
+
+ p = catalog->getPage(page);
+ p->displaySlice(out, zoom, rotate, sliceX, sliceY, sliceW, sliceH,
+ NULL, catalog, abortCheckCbk, abortCheckCbkData);
+}
+
GBool PDFDoc::isLinearized() {
Parser *parser;
Object obj1, obj2, obj3, obj4, obj5;
#ifndef PDFDOC_H
#define PDFDOC_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
class Links;
class LinkAction;
class LinkDest;
+class Outline;
//------------------------------------------------------------------------
// PDFDoc
public:
PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, GBool printCommandsA = gFalse);
+ GString *userPassword = NULL);
PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
- GString *userPassword = NULL, GBool printCommandsA = gFalse);
+ GString *userPassword = NULL);
~PDFDoc();
// Was PDF document successfully opened?
// Display a page.
void displayPage(OutputDev *out, int page, double zoom,
- int rotate, GBool doLinks);
+ int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
- int zoom, int rotate, GBool doLinks);
+ int zoom, int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display part of a page.
+ void displayPageSlice(OutputDev *out, int page, double zoom,
+ int rotate, int sliceX, int sliceY,
+ int sliceW, int sliceH,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
// Find a page, given its object ID. Returns page number, or 0 if
// not found.
LinkDest *findDest(GString *name)
{ return catalog->findDest(name); }
+#ifndef DISABLE_OUTLINE
+ // Return the outline object.
+ Outline *getOutline() { return outline; }
+#endif
+
// Is the file encrypted?
GBool isEncrypted() { return xref->isEncrypted(); }
// Return the document's Info dictionary (if any).
Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); }
+ Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); }
// Return the PDF version specified by the file.
double getPDFVersion() { return pdfVersion; }
// Save this file with another name.
GBool saveAs(GString *name);
+
private:
GBool setup(GString *ownerPassword, GString *userPassword);
XRef *xref;
Catalog *catalog;
Links *links;
- GBool printCommands;
+#ifndef DISABLE_OUTLINE
+ Outline *outline;
+#endif
+
GBool ok;
int errCode;
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
" /PageSize exch def",
" /ImagingBBox null def",
" /Policies 1 dict dup begin /PageSize 3 def end def",
- " /Duplex exch def",
+ " { /Duplex true def } if",
" currentdict end setpagedevice",
" } {",
" pop pop",
" } if",
" pdfTextRender 3 and dup 1 eq exch 2 eq or {",
" 8 6 roll moveto",
- " sCol false awcp currentpoint stroke moveto",
+ " currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
+ " false awcp currentpoint stroke moveto",
" } {",
" 8 {pop} repeat",
" } ifelse",
typedef void (*SignalFunc)(int);
}
+static void outputToFile(void *stream, char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA) {
- Page *page;
- PDFRectangle *box;
- Dict *resDict;
- Annots *annots;
- char **p;
- int pg;
- Object obj1, obj2;
- int i;
+ FILE *f;
+ PSFileType fileTypeA;
- // initialize
- xref = xrefA;
- level = globalParams->getPSLevel();
- mode = modeA;
- paperWidth = globalParams->getPSPaperWidth();
- paperHeight = globalParams->getPSPaperHeight();
fontIDs = NULL;
fontFileIDs = NULL;
fontFileNames = NULL;
font16Enc = NULL;
embFontList = NULL;
- f = NULL;
- if (mode == psModeForm) {
- lastPage = firstPage;
- }
- processColors = 0;
customColors = NULL;
- inType3Char = gFalse;
t3String = NULL;
-#if OPI_SUPPORT
- // initialize OPI nesting levels
- opi13Nest = 0;
- opi20Nest = 0;
-#endif
-
// open file or pipe
- ok = gTrue;
if (!strcmp(fileName, "-")) {
- fileType = psStdout;
+ fileTypeA = psStdout;
f = stdout;
} else if (fileName[0] == '|') {
- fileType = psPipe;
+ fileTypeA = psPipe;
#ifdef HAVE_POPEN
#ifndef WIN32
signal(SIGPIPE, (SignalFunc)SIG_IGN);
return;
#endif
} else {
- fileType = psFile;
+ fileTypeA = psFile;
if (!(f = fopen(fileName, "w"))) {
error(-1, "Couldn't open PostScript file '%s'", fileName);
ok = gFalse;
}
}
+ init(outputToFile, f, fileTypeA,
+ xrefA, catalog, firstPage, lastPage, modeA);
+}
+
+PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
+ XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA) {
+ fontIDs = NULL;
+ fontFileIDs = NULL;
+ fontFileNames = NULL;
+ font16Enc = NULL;
+ embFontList = NULL;
+ customColors = NULL;
+ t3String = NULL;
+
+ init(outputFuncA, outputStreamA, psGeneric,
+ xrefA, catalog, firstPage, lastPage, modeA);
+}
+
+void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
+ PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA) {
+ Page *page;
+ PDFRectangle *box;
+ Dict *resDict;
+ Annots *annots;
+ char **p;
+ int pg;
+ Object obj1, obj2;
+ int i;
+
+ // initialize
+ ok = gTrue;
+ outputFunc = outputFuncA;
+ outputStream = outputStreamA;
+ fileType = fileTypeA;
+ xref = xrefA;
+ level = globalParams->getPSLevel();
+ mode = modeA;
+ paperWidth = globalParams->getPSPaperWidth();
+ paperHeight = globalParams->getPSPaperHeight();
+ if (mode == psModeForm) {
+ lastPage = firstPage;
+ }
+ processColors = 0;
+ inType3Char = gFalse;
+
+#if OPI_SUPPORT
+ // initialize OPI nesting levels
+ opi13Nest = 0;
+ opi20Nest = 0;
+#endif
+
// initialize fontIDs, fontFileIDs, and fontFileNames lists
fontIDSize = 64;
fontIDLen = 0;
// write header
switch (mode) {
case psModePS:
- writePS("%%!PS-Adobe-3.0\n");
- writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
- writePS("%%%%LanguageLevel: %d\n",
- (level == psLevel1 || level == psLevel1Sep) ? 1 :
- (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ writePS("%!PS-Adobe-3.0\n");
+ writePSFmt("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
+ writePSFmt("%%%%LanguageLevel: %d\n",
+ (level == psLevel1 || level == psLevel1Sep) ? 1 :
+ (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
- writePS("%%%%DocumentProcessColors: (atend)\n");
- writePS("%%%%DocumentCustomColors: (atend)\n");
- }
- writePS("%%%%DocumentSuppliedResources: (atend)\n");
- writePS("%%%%DocumentMedia: plain %d %d 0 () ()\n",
- paperWidth, paperHeight);
- writePS("%%%%Pages: %d\n", lastPage - firstPage + 1);
- writePS("%%%%EndComments\n");
- writePS("%%%%BeginDefaults\n");
- writePS("%%%%PageMedia: plain\n");
- writePS("%%%%EndDefaults\n");
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
+ }
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePSFmt("%%%%DocumentMedia: plain %d %d 0 () ()\n",
+ paperWidth, paperHeight);
+ writePSFmt("%%%%Pages: %d\n", lastPage - firstPage + 1);
+ writePS("%%EndComments\n");
+ writePS("%%BeginDefaults\n");
+ writePS("%%PageMedia: plain\n");
+ writePS("%%EndDefaults\n");
break;
case psModeEPS:
- writePS("%%!PS-Adobe-3.0 EPSF-3.0\n");
- writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
- writePS("%%%%LanguageLevel: %d\n",
- (level == psLevel1 || level == psLevel1Sep) ? 1 :
- (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ writePS("%!PS-Adobe-3.0 EPSF-3.0\n");
+ writePSFmt("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
+ writePSFmt("%%%%LanguageLevel: %d\n",
+ (level == psLevel1 || level == psLevel1Sep) ? 1 :
+ (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
- writePS("%%%%DocumentProcessColors: (atend)\n");
- writePS("%%%%DocumentCustomColors: (atend)\n");
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
}
page = catalog->getPage(firstPage);
box = page->getBox();
- writePS("%%%%BoundingBox: %d %d %d %d\n",
- (int)floor(box->x1), (int)floor(box->y1),
- (int)ceil(box->x2), (int)ceil(box->y2));
+ 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)) {
- writePS("%%%%HiResBoundingBox: %g %g %g %g\n",
- box->x1, box->y1, box->x2, box->y2);
+ writePSFmt("%%%%HiResBoundingBox: %g %g %g %g\n",
+ box->x1, box->y1, box->x2, box->y2);
}
- writePS("%%%%DocumentSuppliedResources: (atend)\n");
- writePS("%%%%EndComments\n");
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePS("%%EndComments\n");
break;
case psModeForm:
- writePS("%%!PS-Adobe-3.0 Resource-Form\n");
- writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
- writePS("%%%%LanguageLevel: %d\n",
- (level == psLevel1 || level == psLevel1Sep) ? 1 :
- (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ writePS("%!PS-Adobe-3.0 Resource-Form\n");
+ writePSFmt("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
+ writePSFmt("%%%%LanguageLevel: %d\n",
+ (level == psLevel1 || level == psLevel1Sep) ? 1 :
+ (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
- writePS("%%%%DocumentProcessColors: (atend)\n");
- writePS("%%%%DocumentCustomColors: (atend)\n");
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
}
- writePS("%%%%DocumentSuppliedResources: (atend)\n");
- writePS("%%%%EndComments\n");
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePS("%%EndComments\n");
page = catalog->getPage(firstPage);
box = page->getBox();
writePS("32 dict dup begin\n");
- writePS("/BBox [%d %d %d %d] def\n",
- (int)box->x1, (int)box->y1, (int)box->x2, (int)box->y2);
+ writePSFmt("/BBox [%d %d %d %d] def\n",
+ (int)box->x1, (int)box->y1, (int)box->x2, (int)box->y2);
writePS("/FormType 1 def\n");
writePS("/Matrix [1 0 0 1 0 0] def\n");
break;
// write prolog
if (mode != psModeForm) {
- writePS("%%%%BeginProlog\n");
+ writePS("%%BeginProlog\n");
}
- writePS("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
+ writePSFmt("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
for (p = prolog; *p; ++p) {
- writePS("%s\n", *p);
+ writePSFmt("%s\n", *p);
}
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
if (level >= psLevel3) {
for (p = cmapProlog; *p; ++p) {
- writePS("%s\n", *p);
+ writePSFmt("%s\n", *p);
}
}
if (mode != psModeForm) {
- writePS("%%%%EndProlog\n");
+ writePS("%%EndProlog\n");
}
// set up fonts and images
// swap the form and xpdf dicts
writePS("xpdf end begin dup begin\n");
} else {
- writePS("%%%%BeginSetup\n");
+ writePS("%%BeginSetup\n");
writePS("xpdf begin\n");
}
for (pg = firstPage; pg <= lastPage; ++pg) {
}
if (mode != psModeForm) {
if (mode != psModeEPS) {
- writePS("%d %d %s pdfSetup\n",
- paperWidth, paperHeight,
- globalParams->getPSDuplex() ? "true" : "false");
+ writePSFmt("%d %d %s pdfSetup\n",
+ paperWidth, paperHeight,
+ globalParams->getPSDuplex() ? "true" : "false");
}
#if OPI_SUPPORT
if (globalParams->getPSOPI()) {
writePS("/opiMatrix matrix currentmatrix def\n");
}
#endif
- writePS("%%%%EndSetup\n");
+ writePS("%%EndSetup\n");
}
// initialize sequential page number
PSOutCustomColor *cc;
int i;
- if (f) {
+ if (ok) {
if (mode == psModeForm) {
writePS("/Foo exch /Form defineresource pop\n");
} else {
- writePS("%%%%Trailer\n");
+ writePS("%%Trailer\n");
writePS("end\n");
- writePS("%%%%DocumentSuppliedResources:\n");
- writePS("%s", embFontList->getCString());
+ writePS("%%DocumentSuppliedResources:\n");
+ writePS(embFontList->getCString());
if (level == psLevel1Sep || level == psLevel2Sep ||
level == psLevel3Sep) {
- writePS("%%%%DocumentProcessColors:");
+ writePS("%%DocumentProcessColors:");
if (processColors & psProcessCyan) {
writePS(" Cyan");
}
writePS(" Black");
}
writePS("\n");
- writePS("%%%%DocumentCustomColors:");
+ writePS("%%DocumentCustomColors:");
for (cc = customColors; cc; cc = cc->next) {
- writePS(" (%s)", cc->name->getCString());
+ writePSFmt(" (%s)", cc->name->getCString());
}
writePS("\n");
- writePS("%%%%CMYKCustomColor:\n");
+ writePS("%%CMYKCustomColor:\n");
for (cc = customColors; cc; cc = cc->next) {
- writePS("%%%%+ %g %g %g %g (%s)\n",
+ writePSFmt("%%%%+ %g %g %g %g (%s)\n",
cc->c, cc->m, cc->y, cc->k, cc->name->getCString());
}
}
- writePS("%%%%EOF\n");
+ writePS("%%EOF\n");
}
if (fileType == psFile) {
#ifdef MACOS
- ICS_MapRefNumAndAssign((short)f->handle);
+ ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle);
#endif
- fclose(f);
+ fclose((FILE *)outputStream);
}
#ifdef HAVE_POPEN
else if (fileType == psPipe) {
- pclose(f);
+ pclose((FILE *)outputStream);
#ifndef WIN32
signal(SIGPIPE, (SignalFunc)SIG_DFL);
#endif
PSFontParam *fontParam;
GString *psNameStr;
char *psName;
- char type3Name[64];
+ char type3Name[64], buf[16];
UnicodeMap *uMap;
char *charName;
double xs, ys;
// generate PostScript code to set up the font
if (font->isCIDFont()) {
if (level == psLevel3 || level == psLevel3Sep) {
- writePS("/F%d_%d /%s %d pdfMakeFont16L3\n",
- font->getID()->num, font->getID()->gen, psName,
- font->getWMode());
+ writePSFmt("/F%d_%d /%s %d pdfMakeFont16L3\n",
+ font->getID()->num, font->getID()->gen, psName,
+ font->getWMode());
} else {
- writePS("/F%d_%d /%s %d pdfMakeFont16\n",
- font->getID()->num, font->getID()->gen, psName,
- font->getWMode());
+ writePSFmt("/F%d_%d /%s %d pdfMakeFont16\n",
+ font->getID()->num, font->getID()->gen, psName,
+ font->getWMode());
}
} else {
- writePS("/F%d_%d /%s %g %g\n",
- font->getID()->num, font->getID()->gen, psName, xs, ys);
+ writePSFmt("/F%d_%d /%s %g %g\n",
+ font->getID()->num, font->getID()->gen, psName, xs, ys);
for (i = 0; i < 256; i += 8) {
- writePS((i == 0) ? "[ " : " ");
+ writePSFmt((i == 0) ? "[ " : " ");
for (j = 0; j < 8; ++j) {
- charName = ((Gfx8BitFont *)font)->getCharName(i+j);
- // this is a kludge for broken PDF files that encode char 32
- // as .notdef
- if (i+j == 32 && charName && !strcmp(charName, ".notdef")) {
- charName = "space";
+ if (font->getType() == fontTrueType &&
+ !((Gfx8BitFont *)font)->getHasEncoding()) {
+ sprintf(buf, "c%02x", i+j);
+ charName = buf;
+ } else {
+ charName = ((Gfx8BitFont *)font)->getCharName(i+j);
+ // this is a kludge for broken PDF files that encode char 32
+ // as .notdef
+ if (i+j == 32 && charName && !strcmp(charName, ".notdef")) {
+ charName = "space";
+ }
}
- writePS("/%s", charName ? charName : ".notdef");
+ writePS("/");
+ writePSName(charName ? charName : (char *)".notdef");
}
- writePS((i == 256-8) ? "]\n" : "\n");
+ writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n");
}
writePS("pdfMakeFont\n");
}
obj2.free();
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
writePS("cleartomark\n");
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
err1:
strObj.streamClose();
fontFileNames[fontFileNameLen++] = fileName->copy();
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
fclose(fontFile);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
fontFileIDs[fontFileIDLen++] = *id;
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
// convert it to a Type 1 font
fontBuf = font->readEmbFontFile(xref, &fontLen);
t1cFile = new Type1CFontFile(fontBuf, fontLen);
- t1cFile->convertToType1(f);
+ t1cFile->convertToType1(outputFunc, outputStream);
delete t1cFile;
gfree(fontBuf);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
fontFileIDs[fontFileIDLen++] = *id;
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
ttFile = new TrueTypeFontFile(fontBuf, fontLen);
ctu = ((Gfx8BitFont *)font)->getToUnicode();
ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
- ctu, ((Gfx8BitFont *)font)->getHasEncoding(), f);
+ ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
+ outputFunc, outputStream);
ctu->decRefCnt();
delete ttFile;
gfree(fontBuf);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, char *psName) {
fontFileNames[fontFileNameLen++] = fileName->copy();
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
ttFile = new TrueTypeFontFile(fontBuf, fontLen);
ctu = ((Gfx8BitFont *)font)->getToUnicode();
ttFile->convertToType42(psName, ((Gfx8BitFont *)font)->getEncoding(),
- ctu, ((Gfx8BitFont *)font)->getHasEncoding(), f);
+ ctu, ((Gfx8BitFont *)font)->getHasEncoding(),
+ outputFunc, outputStream);
ctu->decRefCnt();
delete ttFile;
gfree(fontBuf);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
fontFileIDs[fontFileIDLen++] = *id;
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
t1cFile = new Type1CFontFile(fontBuf, fontLen);
if (globalParams->getPSLevel() >= psLevel3) {
// Level 3: use a CID font
- t1cFile->convertToCIDType0(psName, f);
+ t1cFile->convertToCIDType0(psName, outputFunc, outputStream);
} else {
// otherwise: use a non-CID composite font
- t1cFile->convertToType0(psName, f);
+ t1cFile->convertToType0(psName, outputFunc, outputStream);
}
delete t1cFile;
gfree(fontBuf);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
fontFileIDs[fontFileIDLen++] = *id;
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
if (globalParams->getPSLevel() >= psLevel3) {
ttFile->convertToCIDType2(psName,
((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(), f);
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
} else {
// otherwise: use a non-CID composite font
ttFile->convertToType0(psName, ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(), f);
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
}
delete ttFile;
gfree(fontBuf);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupType3Font(GfxFont *font, char *psName,
Gfx *gfx;
PDFRectangle box;
double *m;
+ char buf[256];
int i;
// set up resources used by font
}
// beginning comment
- writePS("%%%%BeginResource: font %s\n", psName);
+ writePSFmt("%%%%BeginResource: font %s\n", psName);
embFontList->append("%%+ font ");
embFontList->append(psName);
embFontList->append("\n");
writePS("7 dict begin\n");
writePS("/FontType 3 def\n");
m = font->getFontMatrix();
- writePS("/FontMatrix [%g %g %g %g %g %g] def\n",
- m[0], m[1], m[2], m[3], m[4], m[5]);
+ writePSFmt("/FontMatrix [%g %g %g %g %g %g] def\n",
+ m[0], m[1], m[2], m[3], m[4], m[5]);
m = font->getFontBBox();
- writePS("/FontBBox [%g %g %g %g] def\n",
- m[0], m[1], m[2], m[3]);
+ writePSFmt("/FontBBox [%g %g %g %g] def\n",
+ m[0], m[1], m[2], m[3]);
writePS("/Encoding 256 array def\n");
writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
writePS("/BuildGlyph {\n");
writePS(" 1 index /BuildGlyph get exec\n");
writePS("} bind def\n");
if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) {
- writePS("/CharProcs %d dict def\n", charProcs->getLength());
+ writePSFmt("/CharProcs %d dict def\n", charProcs->getLength());
writePS("CharProcs begin\n");
box.x1 = m[0];
box.y1 = m[1];
box.y2 = m[3];
gfx = new Gfx(xref, this, resDict, &box, gFalse, NULL);
inType3Char = gTrue;
+ t3Cacheable = gFalse;
for (i = 0; i < charProcs->getLength(); ++i) {
- writePS("/%s {\n", charProcs->getKey(i));
+ writePS("/");
+ writePSName(charProcs->getKey(i));
+ writePS(" {\n");
gfx->display(charProcs->getVal(i, &charProc));
charProc.free();
if (t3String) {
if (t3Cacheable) {
- fprintf(f, "%g %g %g %g %g %g setcachedevice\n",
+ sprintf(buf, "%g %g %g %g %g %g setcachedevice\n",
t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY);
} else {
- fprintf(f, "%g %g setcharwidth\n", t3WX, t3WY);
+ sprintf(buf, "%g %g setcharwidth\n", t3WX, t3WY);
}
- fputs(t3String->getCString(), f);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, t3String->getCString(),
+ t3String->getLength());
delete t3String;
t3String = NULL;
}
- fputs("Q\n", f);
+ (*outputFunc)(outputStream, "Q\n", 2);
writePS("} def\n");
}
inType3Char = gFalse;
writePS("end\n");
}
writePS("currentdict end\n");
- writePS("/%s exch definefont pop\n", psName);
+ writePSFmt("/%s exch definefont pop\n", psName);
// ending comment
- writePS("%%%%EndResource\n");
+ writePS("%%EndResource\n");
}
void PSOutputDev::setupImages(Dict *resDict) {
}
} while (c != '~' && c != EOF);
++size;
- writePS("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
+ writePSFmt("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
// write the data into the array
str->reset();
if (col > 225) {
writePS("~> put\n");
++line;
- writePS("dup %d <~", line);
+ writePSFmt("dup %d <~", line);
col = 0;
}
} while (c != '~' && c != EOF);
void PSOutputDev::startPage(int pageNum, GfxState *state) {
int x1, y1, x2, y2, width, height, t;
+
switch (mode) {
case psModePS:
- writePS("%%%%Page: %d %d\n", pageNum, seqPage);
- writePS("%%%%BeginPageSetup\n");
+ writePSFmt("%%%%Page: %d %d\n", pageNum, seqPage);
+ writePS("%%BeginPageSetup\n");
// rotate, translate, and scale page
x1 = (int)(state->getX1() + 0.5);
height = y2 - y1;
if (width > height && width > paperWidth) {
landscape = gTrue;
- writePS("%%%%PageOrientation: %s\n",
- state->getCTM()[0] ? "Landscape" : "Portrait");
+ writePSFmt("%%%%PageOrientation: %s\n",
+ state->getCTM()[0] ? "Landscape" : "Portrait");
writePS("pdfStartPage\n");
writePS("90 rotate\n");
tx = -x1;
height = t;
} else {
landscape = gFalse;
- writePS("%%%%PageOrientation: %s\n",
- state->getCTM()[0] ? "Portrait" : "Landscape");
+ writePSFmt("%%%%PageOrientation: %s\n",
+ state->getCTM()[0] ? "Portrait" : "Landscape");
writePS("pdfStartPage\n");
tx = -x1;
ty = -y1;
ty += (paperHeight - height) / 2;
}
if (tx != 0 || ty != 0) {
- writePS("%g %g translate\n", tx, ty);
+ writePSFmt("%g %g translate\n", tx, ty);
}
if (width > paperWidth || height > paperHeight) {
xScale = (double)paperWidth / (double)width;
} else {
yScale = xScale;
}
- writePS("%0.4f %0.4f scale\n", xScale, xScale);
+ writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
} else {
xScale = yScale = 1;
}
- writePS("%%%%EndPageSetup\n");
+ writePS("%%EndPageSetup\n");
++seqPage;
break;
}
void PSOutputDev::endPage() {
+
if (mode == psModeForm) {
writePS("pdfEndPage\n");
writePS("end end\n");
writePS("end end\n");
} else {
writePS("showpage\n");
- writePS("%%%%PageTrailer\n");
+ writePS("%%PageTrailer\n");
writePS("pdfEndPage\n");
}
}
void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
double m21, double m22, double m31, double m32) {
- writePS("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
+ writePSFmt("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
}
void PSOutputDev::updateLineDash(GfxState *state) {
state->getLineDash(&dash, &length, &start);
writePS("[");
for (i = 0; i < length; ++i)
- writePS("%g%s", dash[i], (i == length-1) ? "" : " ");
- writePS("] %g d\n", start);
+ writePSFmt("%g%s", dash[i], (i == length-1) ? "" : " ");
+ writePSFmt("] %g d\n", start);
}
void PSOutputDev::updateFlatness(GfxState *state) {
- writePS("%d i\n", state->getFlatness());
+ writePSFmt("%d i\n", state->getFlatness());
}
void PSOutputDev::updateLineJoin(GfxState *state) {
- writePS("%d j\n", state->getLineJoin());
+ writePSFmt("%d j\n", state->getLineJoin());
}
void PSOutputDev::updateLineCap(GfxState *state) {
- writePS("%d J\n", state->getLineCap());
+ writePSFmt("%d J\n", state->getLineCap());
}
void PSOutputDev::updateMiterLimit(GfxState *state) {
- writePS("%g M\n", state->getMiterLimit());
+ writePSFmt("%g M\n", state->getMiterLimit());
}
void PSOutputDev::updateLineWidth(GfxState *state) {
- writePS("%g w\n", state->getLineWidth());
+ writePSFmt("%g w\n", state->getLineWidth());
}
void PSOutputDev::updateFillColor(GfxState *state) {
switch (level) {
case psLevel1:
state->getFillGray(&gray);
- writePS("%g g\n", gray);
+ writePSFmt("%g g\n", gray);
break;
case psLevel1Sep:
state->getFillCMYK(&cmyk);
- writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePSFmt("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
break;
case psLevel2:
case psLevel3:
if (state->getFillColorSpace()->getMode() == csDeviceCMYK) {
state->getFillCMYK(&cmyk);
- writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePSFmt("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
} else {
state->getFillRGB(&rgb);
if (rgb.r == rgb.g && rgb.g == rgb.b) {
- writePS("%g g\n", rgb.r);
+ writePSFmt("%g g\n", rgb.r);
} else {
- writePS("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
+ writePSFmt("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
}
}
break;
sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace();
color.c[0] = 1;
sepCS->getCMYK(&color, &cmyk);
- writePS("%g %g %g %g %g (%s) ck\n",
- state->getFillColor()->c[0],
- cmyk.c, cmyk.m, cmyk.y, cmyk.k,
- sepCS->getName()->getCString());
+ writePSFmt("%g %g %g %g %g (%s) ck\n",
+ state->getFillColor()->c[0],
+ cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->getCString());
addCustomColor(sepCS);
} else {
state->getFillCMYK(&cmyk);
- writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePSFmt("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
}
break;
switch (level) {
case psLevel1:
state->getStrokeGray(&gray);
- writePS("%g G\n", gray);
+ writePSFmt("%g G\n", gray);
break;
case psLevel1Sep:
state->getStrokeCMYK(&cmyk);
- writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePSFmt("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
break;
case psLevel2:
case psLevel3:
if (state->getStrokeColorSpace()->getMode() == csDeviceCMYK) {
state->getStrokeCMYK(&cmyk);
- writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePSFmt("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
} else {
state->getStrokeRGB(&rgb);
if (rgb.r == rgb.g && rgb.g == rgb.b) {
- writePS("%g G\n", rgb.r);
+ writePSFmt("%g G\n", rgb.r);
} else {
- writePS("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
+ writePSFmt("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
}
}
break;
sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace();
color.c[0] = 1;
sepCS->getCMYK(&color, &cmyk);
- writePS("%g %g %g %g %g (%s) CK\n",
- state->getStrokeColor()->c[0],
- cmyk.c, cmyk.m, cmyk.y, cmyk.k,
- sepCS->getName()->getCString());
+ writePSFmt("%g %g %g %g %g (%s) CK\n",
+ state->getStrokeColor()->c[0],
+ cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->getCString());
addCustomColor(sepCS);
} else {
state->getStrokeCMYK(&cmyk);
- writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePSFmt("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
}
break;
void PSOutputDev::updateFont(GfxState *state) {
if (state->getFont()) {
- writePS("/F%d_%d %g Tf\n",
- state->getFont()->getID()->num, state->getFont()->getID()->gen,
- state->getFontSize());
+ writePSFmt("/F%d_%d %g Tf\n",
+ state->getFont()->getID()->num, state->getFont()->getID()->gen,
+ state->getFontSize());
}
}
double *mat;
mat = state->getTextMat();
- writePS("[%g %g %g %g %g %g] Tm\n",
- mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+ writePSFmt("[%g %g %g %g %g %g] Tm\n",
+ mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
}
void PSOutputDev::updateCharSpace(GfxState *state) {
- writePS("%g Tc\n", state->getCharSpace());
+ writePSFmt("%g Tc\n", state->getCharSpace());
}
void PSOutputDev::updateRender(GfxState *state) {
int rm;
rm = state->getRender();
- writePS("%d Tr\n", rm);
+ writePSFmt("%d Tr\n", rm);
rm &= 3;
if (rm != 0 && rm != 3) {
t3Cacheable = gFalse;
}
void PSOutputDev::updateRise(GfxState *state) {
- writePS("%g Ts\n", state->getRise());
+ writePSFmt("%g Ts\n", state->getRise());
}
void PSOutputDev::updateWordSpace(GfxState *state) {
- writePS("%g Tw\n", state->getWordSpace());
+ writePSFmt("%g Tw\n", state->getWordSpace());
}
void PSOutputDev::updateHorizScaling(GfxState *state) {
- writePS("%g Tz\n", state->getHorizScaling());
+ writePSFmt("%g Tz\n", state->getHorizScaling());
}
void PSOutputDev::updateTextPos(GfxState *state) {
- writePS("%g %g Td\n", state->getLineX(), state->getLineY());
+ writePSFmt("%g %g Td\n", state->getLineX(), state->getLineY());
}
void PSOutputDev::updateTextShift(GfxState *state, double shift) {
if (state->getFont()->getWMode()) {
- writePS("%g TJmV\n", shift);
+ writePSFmt("%g TJmV\n", shift);
} else {
- writePS("%g TJm\n", shift);
+ writePSFmt("%g TJm\n", shift);
}
}
x3 = subpath->getX(3);
y3 = subpath->getY(3);
if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) {
- writePS("%g %g %g %g re\n",
- x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1,
- fabs(x2 - x0), fabs(y1 - y0));
+ writePSFmt("%g %g %g %g re\n",
+ x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1,
+ fabs(x2 - x0), fabs(y1 - y0));
return;
} else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) {
- writePS("%g %g %g %g re\n",
- x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2,
- fabs(x1 - x0), fabs(y2 - y0));
+ writePSFmt("%g %g %g %g re\n",
+ x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2,
+ fabs(x1 - x0), fabs(y2 - y0));
return;
}
}
for (i = 0; i < n; ++i) {
subpath = path->getSubpath(i);
m = subpath->getNumPoints();
- writePS("%g %g m\n", subpath->getX(0), subpath->getY(0));
+ writePSFmt("%g %g m\n", subpath->getX(0), subpath->getY(0));
j = 1;
while (j < m) {
if (subpath->getCurve(j)) {
- writePS("%g %g %g %g %g %g c\n", subpath->getX(j), subpath->getY(j),
- subpath->getX(j+1), subpath->getY(j+1),
- subpath->getX(j+2), subpath->getY(j+2));
+ writePSFmt("%g %g %g %g %g %g c\n", subpath->getX(j), subpath->getY(j),
+ subpath->getX(j+1), subpath->getY(j+1),
+ subpath->getX(j+2), subpath->getY(j+2));
j += 3;
} else {
- writePS("%g %g l\n", subpath->getX(j), subpath->getY(j));
+ writePSFmt("%g %g l\n", subpath->getX(j), subpath->getY(j));
++j;
}
}
writePSString(s2);
if (font->isCIDFont()) {
if (wMode) {
- writePS(" %d %g Tj16V\n", nChars, dy);
+ writePSFmt(" %d %g Tj16V\n", nChars, dy);
} else {
- writePS(" %d %g Tj16\n", nChars, dx);
+ writePSFmt(" %d %g Tj16\n", nChars, dx);
}
} else {
- writePS(" %g Tj\n", dx);
+ writePSFmt(" %g Tj\n", dx);
}
}
if (font->isCIDFont()) {
// width, height, matrix, bits per component
if (colorMap) {
- writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
- width, height,
- width, -height, height);
+ writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
+ width, height,
+ width, -height, height);
} else {
- writePS("%d %d %s [%d 0 0 %d 0 %d] pdfImM1\n",
- width, height, invert ? "true" : "false",
- width, -height, height);
+ writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1\n",
+ width, height, invert ? "true" : "false",
+ width, -height, height);
}
// image
for (x = 0; x < width; ++x) {
imgStr->getPixel(pixBuf);
colorMap->getGray(pixBuf, &gray);
- writePS("%02x", (int)(gray * 255 + 0.5));
+ writePSFmt("%02x", (int)(gray * 255 + 0.5));
if (++i == 32) {
writePSChar('\n');
i = 0;
i = 0;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; x += 8) {
- writePS("%02x", str->getChar() & 0xff);
+ writePSFmt("%02x", str->getChar() & 0xff);
if (++i == 32) {
writePSChar('\n');
i = 0;
int x, y, i, comp;
// width, height, matrix, bits per component
- writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n",
- width, height,
- width, -height, height);
+ writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n",
+ width, height,
+ width, -height, height);
// allocate a line buffer
lineBuf = (Guchar *)gmalloc(4 * width);
lineBuf[4*x+1] = (int)(255 * cmyk.m + 0.5);
lineBuf[4*x+2] = (int)(255 * cmyk.y + 0.5);
lineBuf[4*x+3] = (int)(255 * cmyk.k + 0.5);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
}
// write one line of each color component
for (comp = 0; comp < 4; ++comp) {
for (x = 0; x < width; ++x) {
- writePS("%02x", lineBuf[4*x + comp]);
+ writePSFmt("%02x", lineBuf[4*x + comp]);
if (++i == 32) {
writePSChar('\n');
i = 0;
GfxColor color;
GfxCMYK cmyk;
int c;
- int i;
+ int line, col, i;
// color space
if (colorMap) {
writePS(" setcolorspace\n");
}
- // set up to use the array created by setupImages()
- if ((mode == psModeForm || inType3Char) && !inlineImg) {
- writePS("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
+ // set up the image data
+ if (mode == psModeForm || inType3Char) {
+ if (inlineImg) {
+ // create an array
+ str = new FixedLengthEncoder(str, len);
+ if (globalParams->getPSASCIIHex()) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ str->reset();
+ line = col = 0;
+ writePS("[<~");
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ writePSChar(c);
+ ++col;
+ } else {
+ writePSChar(c);
+ ++col;
+ for (i = 1; i <= 4; ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || 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);
+ col = 0;
+ }
+ } while (c != '~' && c != EOF);
+ writePS("~>]\n");
+ writePS("0\n");
+ delete str;
+ } else {
+ // set up to use the array already created by setupImages()
+ writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
+ }
}
// image dictionary
writePS("<<\n /ImageType 1\n");
// width, height, matrix, bits per component
- writePS(" /Width %d\n", width);
- writePS(" /Height %d\n", height);
- writePS(" /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height);
- writePS(" /BitsPerComponent %d\n",
- colorMap ? colorMap->getBits() : 1);
+ 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);
// decode
if (colorMap) {
if (colorMap->getColorSpace()->getMode() == csSeparation) {
//~ this is a kludge -- see comment in dumpColorSpaceL2
n = (1 << colorMap->getBits()) - 1;
- writePS("%g %g", colorMap->getDecodeLow(0) * n,
- colorMap->getDecodeHigh(0) * n);
+ writePSFmt("%g %g", colorMap->getDecodeLow(0) * n,
+ colorMap->getDecodeHigh(0) * n);
} else {
numComps = colorMap->getNumPixelComps();
for (i = 0; i < numComps; ++i) {
if (i > 0) {
writePS(" ");
}
- writePS("%g %g", colorMap->getDecodeLow(i),
- colorMap->getDecodeHigh(i));
+ writePSFmt("%g %g", colorMap->getDecodeLow(i),
+ colorMap->getDecodeHigh(i));
}
}
writePS("]\n");
} else {
- writePS(" /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1);
+ writePSFmt(" /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1);
}
if (mode == psModeForm || inType3Char) {
- if (inlineImg) {
-
- // data source
- writePS(" /DataSource <~\n");
-
- // write image data stream, using ASCII85 encode filter
- str = new FixedLengthEncoder(str, len);
- if (globalParams->getPSASCIIHex()) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
- str->reset();
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- writePSChar('\n');
- delete str;
-
- } else {
- writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
- }
+ // data source
+ writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
// end of image dictionary
- writePS(">>\n%s\n", colorMap ? "image" : "imagemask");
+ writePSFmt(">>\n%s\n", colorMap ? "image" : "imagemask");
// get rid of the array and index
- if (!inlineImg) {
- writePS("pop pop\n");
- }
+ writePS("pop pop\n");
} else {
useCompressed = gTrue;
}
if (useASCII) {
- writePS(" /ASCII%sDecode filter\n",
- globalParams->getPSASCIIHex() ? "Hex" : "85");
+ writePSFmt(" /ASCII%sDecode filter\n",
+ globalParams->getPSASCIIHex() ? "Hex" : "85");
}
if (useRLE) {
writePS(" /RunLengthDecode filter\n");
}
if (useCompressed) {
- writePS("%s", s->getCString());
+ writePS(s->getCString());
}
if (s) {
delete s;
// +6/7 for "pdfIm\n" / "pdfImM\n"
// +8 for newline + trailer
n += colorMap ? 14 : 15;
- writePS("%%%%BeginData: %d Hex Bytes\n", n);
+ writePSFmt("%%%%BeginData: %d Hex Bytes\n", n);
}
#endif
if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap &&
color.c[0] = 1;
sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
sepCS->getCMYK(&color, &cmyk);
- writePS("%g %g %g %g (%s) pdfImSep\n",
- cmyk.c, cmyk.m, cmyk.y, cmyk.k, sepCS->getName()->getCString());
+ writePSFmt("%g %g %g %g (%s) pdfImSep\n",
+ cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->getCString());
} else {
- writePS("%s\n", colorMap ? "pdfIm" : "pdfImM");
+ writePSFmt("%s\n", colorMap ? "pdfIm" : "pdfImM");
}
// copy the stream data
// add newline and trailer to the end
writePSChar('\n');
- writePS("%%-EOD-\n");
+ writePS("%-EOD-\n");
#if OPI_SUPPORT
if (opi13Nest) {
- writePS("%%%%EndData\n");
+ writePS("%%EndData\n");
}
#endif
GfxLabColorSpace *labCS;
GfxIndexedColorSpace *indexedCS;
GfxSeparationColorSpace *separationCS;
- Guchar *lookup;
+ GfxColorSpace *baseCS;
+ Guchar *lookup, *p;
double x[gfxColorMaxComps], y[gfxColorMaxComps];
GfxColor color;
GfxCMYK cmyk;
- int n, numComps;
+ Function *func;
+ int n, numComps, numAltComps;
+ int byte;
int i, j, k;
switch (colorSpace->getMode()) {
case csCalGray:
calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
writePS("[/CIEBasedA <<\n");
- writePS(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
- writePS(" /MatrixA [%g %g %g]\n",
- calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
- calGrayCS->getWhiteZ());
- writePS(" /WhitePoint [%g %g %g]\n",
- calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
- calGrayCS->getWhiteZ());
- writePS(" /BlackPoint [%g %g %g]\n",
- calGrayCS->getBlackX(), calGrayCS->getBlackY(),
- calGrayCS->getBlackZ());
+ writePSFmt(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
+ writePSFmt(" /MatrixA [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ calGrayCS->getBlackX(), calGrayCS->getBlackY(),
+ calGrayCS->getBlackZ());
writePS(">>]");
processColors |= psProcessBlack;
break;
case csCalRGB:
calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
writePS("[/CIEBasedABC <<\n");
- writePS(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
- calRGBCS->getGammaR(), calRGBCS->getGammaG(),
- calRGBCS->getGammaB());
- writePS(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
- calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
- calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
- calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
- calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
- calRGBCS->getMatrix()[8]);
- writePS(" /WhitePoint [%g %g %g]\n",
- calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
- calRGBCS->getWhiteZ());
- writePS(" /BlackPoint [%g %g %g]\n",
- calRGBCS->getBlackX(), calRGBCS->getBlackY(),
- calRGBCS->getBlackZ());
+ writePSFmt(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
+ calRGBCS->getGammaR(), calRGBCS->getGammaG(),
+ calRGBCS->getGammaB());
+ writePSFmt(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
+ calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
+ calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
+ calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
+ calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
+ calRGBCS->getMatrix()[8]);
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
+ calRGBCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ calRGBCS->getBlackX(), calRGBCS->getBlackY(),
+ calRGBCS->getBlackZ());
writePS(">>]");
processColors |= psProcessCMYK;
break;
case csLab:
labCS = (GfxLabColorSpace *)colorSpace;
writePS("[/CIEBasedABC <<\n");
- writePS(" /RangeABC [0 100 %g %g %g %g]\n",
- labCS->getAMin(), labCS->getAMax(),
- labCS->getBMin(), labCS->getBMax());
+ writePSFmt(" /RangeABC [0 100 %g %g %g %g]\n",
+ labCS->getAMin(), labCS->getAMax(),
+ labCS->getBMin(), labCS->getBMax());
writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
writePS(" /DecodeLMN\n");
writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
- writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
- labCS->getWhiteX());
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteX());
writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
- writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
- labCS->getWhiteY());
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteY());
writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
- writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
- labCS->getWhiteZ());
- writePS(" /WhitePoint [%g %g %g]\n",
- labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
- writePS(" /BlackPoint [%g %g %g]\n",
- labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
+ labCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
writePS(">>]");
processColors |= psProcessCMYK;
break;
case csIndexed:
indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ baseCS = indexedCS->getBase();
writePS("[/Indexed ");
- dumpColorSpaceL2(indexedCS->getBase());
+ dumpColorSpaceL2(baseCS);
n = indexedCS->getIndexHigh();
- numComps = indexedCS->getBase()->getNComps();
+ numComps = baseCS->getNComps();
lookup = indexedCS->getLookup();
- writePS(" %d <\n", n);
- for (i = 0; i <= n; i += 8) {
- writePS(" ");
- for (j = i; j < i+8 && j <= n; ++j) {
- for (k = 0; k < numComps; ++k) {
- writePS("%02x", lookup[j * numComps + k]);
+ writePSFmt(" %d <\n", n);
+ if (baseCS->getMode() == csDeviceN) {
+ func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
+ numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps();
+ p = lookup;
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ x[k] = *p++ / 255.0;
+ }
+ func->transform(x, y);
+ for (k = 0; k < numAltComps; ++k) {
+ byte = (int)(y[k] * 255 + 0.5);
+ if (byte < 0) {
+ byte = 0;
+ } else if (byte > 255) {
+ byte = 255;
+ }
+ writePSFmt("%02x", byte);
+ }
+ color.c[0] = j;
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
}
- color.c[0] = j;
- indexedCS->getCMYK(&color, &cmyk);
- addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ writePS("\n");
+ }
+ } else {
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ writePSFmt("%02x", lookup[j * numComps + k]);
+ }
+ color.c[0] = j;
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ writePS("\n");
}
- writePS("\n");
}
writePS(">]");
break;
x[0] = (double)j / 255.0;
separationCS->getFunc()->transform(x, y);
for (k = 0; k < numComps; ++k) {
- writePS("%02x", (int)(255 * y[k] + 0.5));
+ writePSFmt("%02x", (int)(255 * y[k] + 0.5));
}
}
writePS("\n");
int w, h;
int i;
- writePS("%%%%BeginOPI: 2.0\n");
- writePS("%%%%Distilled\n");
+ writePS("%%BeginOPI: 2.0\n");
+ writePS("%%Distilled\n");
dict->lookup("F", &obj1);
if (getFileSpec(&obj1, &obj2)) {
- writePS("%%%%ImageFileName: %s\n",
- obj2.getString()->getCString());
+ writePSFmt("%%%%ImageFileName: %s\n",
+ obj2.getString()->getCString());
obj2.free();
}
obj1.free();
dict->lookup("MainImage", &obj1);
if (obj1.isString()) {
- writePS("%%%%MainImage: %s\n", obj1.getString()->getCString());
+ writePSFmt("%%%%MainImage: %s\n", obj1.getString()->getCString());
}
obj1.free();
obj1.arrayGet(1, &obj2);
height = obj2.getNum();
obj2.free();
- writePS("%%%%ImageDimensions: %g %g\n", width, height);
+ writePSFmt("%%%%ImageDimensions: %g %g\n", width, height);
}
obj1.free();
obj1.arrayGet(3, &obj2);
bottom = obj2.getNum();
obj2.free();
- writePS("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom);
+ writePSFmt("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom);
}
obj1.free();
dict->lookup("Overprint", &obj1);
if (obj1.isBool()) {
- writePS("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
+ writePSFmt("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
}
obj1.free();
dict->lookup("Inks", &obj1);
if (obj1.isName()) {
- writePS("%%%%ImageInks: %s\n", obj1.getName());
+ writePSFmt("%%%%ImageInks: %s\n", obj1.getName());
} else if (obj1.isArray() && obj1.arrayGetLength() >= 1) {
obj1.arrayGet(0, &obj2);
if (obj2.isName()) {
- writePS("%%%%ImageInks: %s %d",
- obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
+ writePSFmt("%%%%ImageInks: %s %d",
+ obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) {
obj1.arrayGet(i, &obj3);
obj1.arrayGet(i+1, &obj4);
if (obj3.isString() && obj4.isNum()) {
writePS(" ");
writePSString(obj3.getString());
- writePS(" %g", obj4.getNum());
+ writePSFmt(" %g", obj4.getNum());
}
obj3.free();
obj4.free();
writePS("gsave\n");
- writePS("%%%%BeginIncludedImage\n");
+ writePS("%%BeginIncludedImage\n");
dict->lookup("IncludedImageDimensions", &obj1);
if (obj1.isArray() && obj1.arrayGetLength() == 2) {
obj1.arrayGet(1, &obj2);
h = obj2.getInt();
obj2.free();
- writePS("%%%%IncludedImageDimensions: %d %d\n", w, h);
+ writePSFmt("%%%%IncludedImageDimensions: %d %d\n", w, h);
}
obj1.free();
dict->lookup("IncludedImageQuality", &obj1);
if (obj1.isNum()) {
- writePS("%%%%IncludedImageQuality: %g\n", obj1.getNum());
+ writePSFmt("%%%%IncludedImageQuality: %g\n", obj1.getNum());
}
obj1.free();
dict->lookup("F", &obj1);
if (getFileSpec(&obj1, &obj2)) {
- writePS("%%ALDImageFileName: %s\n",
- obj2.getString()->getCString());
+ writePSFmt("%%ALDImageFileName: %s\n",
+ obj2.getString()->getCString());
obj2.free();
}
obj1.free();
obj1.arrayGet(3, &obj2);
bottom = obj2.getInt();
obj2.free();
- writePS("%%ALDImageCropRect: %d %d %d %d\n", left, top, right, bottom);
+ writePSFmt("%%ALDImageCropRect: %d %d %d %d\n", left, top, right, bottom);
}
obj1.free();
obj2.free();
obj1.arrayGet(4, &obj2);
if (obj2.isString()) {
- writePS("%%ALDImageColor: %g %g %g %g ", c, m, y, k);
+ writePSFmt("%%ALDImageColor: %g %g %g %g ", c, m, y, k);
writePSString(obj2.getString());
writePS("\n");
}
dict->lookup("ColorType", &obj1);
if (obj1.isName()) {
- writePS("%%ALDImageColorType: %s\n", obj1.getName());
+ writePSFmt("%%ALDImageColorType: %s\n", obj1.getName());
}
obj1.free();
obj1.arrayGet(3, &obj2);
lry = obj2.getNum();
obj2.free();
- writePS("%%ALDImageCropFixed: %g %g %g %g\n", ulx, uly, lrx, lry);
+ writePSFmt("%%ALDImageCropFixed: %g %g %g %g\n", ulx, uly, lrx, lry);
}
obj1.free();
dict->lookup("GrayMap", &obj1);
if (obj1.isArray()) {
- writePS("%%ALDImageGrayMap:");
+ writePS("%ALDImageGrayMap:");
for (i = 0; i < obj1.arrayGetLength(); i += 16) {
if (i > 0) {
- writePS("\n%%%%+");
+ writePS("\n%%+");
}
for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) {
obj1.arrayGet(i+j, &obj2);
- writePS(" %d", obj2.getInt());
+ writePSFmt(" %d", obj2.getInt());
obj2.free();
}
}
dict->lookup("ID", &obj1);
if (obj1.isString()) {
- writePS("%%ALDImageID: %s\n", obj1.getString()->getCString());
+ writePSFmt("%%ALDImageID: %s\n", obj1.getString()->getCString());
}
obj1.free();
obj1.arrayGet(1, &obj2);
bits = obj2.getInt();
obj2.free();
- writePS("%%ALDImageType: %d %d\n", samples, bits);
+ writePSFmt("%%ALDImageType: %d %d\n", samples, bits);
}
obj1.free();
dict->lookup("Overprint", &obj1);
if (obj1.isBool()) {
- writePS("%%ALDImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
+ writePSFmt("%%ALDImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
}
obj1.free();
opiTransform(state, ulx, uly, &tulx, &tuly);
opiTransform(state, urx, ury, &turx, &tury);
opiTransform(state, lrx, lry, &tlrx, &tlry);
- writePS("%%ALDImagePosition: %g %g %g %g %g %g %g %g\n",
- tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
+ writePSFmt("%%ALDImagePosition: %g %g %g %g %g %g %g %g\n",
+ tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
obj2.free();
}
obj1.free();
obj1.arrayGet(1, &obj2);
vert = obj2.getNum();
obj2.free();
- writePS("%%ALDImageResoution: %g %g\n", horiz, vert);
+ writePSFmt("%%ALDImageResoution: %g %g\n", horiz, vert);
obj2.free();
}
obj1.free();
obj1.arrayGet(1, &obj2);
height = obj2.getInt();
obj2.free();
- writePS("%%ALDImageDimensions: %d %d\n", width, height);
+ writePSFmt("%%ALDImageDimensions: %d %d\n", width, height);
}
obj1.free();
dict->lookup("Tint", &obj1);
if (obj1.isNum()) {
- writePS("%%ALDImageTint: %g\n", obj1.getNum());
+ writePSFmt("%%ALDImageTint: %g\n", obj1.getNum());
}
obj1.free();
dict->lookup("Transparency", &obj1);
if (obj1.isBool()) {
- writePS("%%ALDImageTransparency: %s\n", obj1.getBool() ? "true" : "false");
+ writePSFmt("%%ALDImageTransparency: %s\n", obj1.getBool() ? "true" : "false");
}
obj1.free();
- writePS("%%%%BeginObject: image\n");
+ writePS("%%BeginObject: image\n");
writePS("opiMatrix2 setmatrix\n");
++opi13Nest;
}
if (globalParams->getPSOPI()) {
opiDict->lookup("2.0", &dict);
if (dict.isDict()) {
- writePS("%%%%EndIncludedImage\n");
- writePS("%%%%EndOPI\n");
+ writePS("%%EndIncludedImage\n");
+ writePS("%%EndOPI\n");
writePS("grestore\n");
--opi20Nest;
dict.free();
dict.free();
opiDict->lookup("1.3", &dict);
if (dict.isDict()) {
- writePS("%%%%EndObject\n");
+ writePS("%%EndObject\n");
writePS("restore\n");
--opi13Nest;
}
#endif // OPI_SUPPORT
void PSOutputDev::type3D0(GfxState *state, double wx, double wy) {
- writePS("%g %g setcharwidth\n", wx, wy);
+ writePSFmt("%g %g setcharwidth\n", wx, wy);
writePS("q\n");
}
str->close();
}
-void PSOutputDev::writePS(const char *fmt, ...) {
+void PSOutputDev::writePSChar(char c) {
+ if (t3String) {
+ t3String->append(c);
+ } else {
+ (*outputFunc)(outputStream, &c, 1);
+ }
+}
+
+void PSOutputDev::writePS(char *s) {
+ if (t3String) {
+ t3String->append(s);
+ } else {
+ (*outputFunc)(outputStream, s, strlen(s));
+ }
+}
+
+void PSOutputDev::writePSFmt(const char *fmt, ...) {
va_list args;
char buf[512];
va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
if (t3String) {
- vsprintf(buf, fmt, args);
t3String->append(buf);
} else {
- vfprintf(f, fmt, args);
+ (*outputFunc)(outputStream, buf, strlen(buf));
}
- va_end(args);
}
void PSOutputDev::writePSString(GString *s) {
writePSChar('\\');
writePSChar((char)*p);
} else if (*p < 0x20 || *p >= 0x80) {
+ sprintf(buf, "\\%03o", *p);
if (t3String) {
- sprintf(buf, "\\%03o", *p);
t3String->append(buf);
} else {
- fprintf(f, "\\%03o", *p);
+ (*outputFunc)(outputStream, buf, strlen(buf));
}
} else {
writePSChar((char)*p);
writePSChar(')');
}
-void PSOutputDev::writePSChar(char c) {
- if (t3String) {
- t3String->append(c);
- } else {
- fputc(c, f);
+void PSOutputDev::writePSName(char *s) {
+ char *p;
+ char c;
+
+ p = s;
+ while ((c = *p++)) {
+ if (c <= (char)0x20 || c >= (char)0x7f ||
+ c == '(' || c == ')' || c == '<' || c == '>' ||
+ c == '[' || c == ']' || c == '{' || c == '}' ||
+ c == '/' || c == '%') {
+ writePSFmt("#%02x", c & 0xff);
+ } else {
+ writePSChar(c);
+ }
}
}
#ifndef PSOUTPUTDEV_H
#define PSOUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
enum PSFileType {
psFile, // write to file
psPipe, // write to pipe
- psStdout // write to stdout
+ psStdout, // write to stdout
+ psGeneric // write to a generic stream
};
+typedef void (*PSOutputFunc)(void *stream, char *data, int len);
+
class PSOutputDev: public OutputDev {
public:
PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog,
int firstPage, int lastPage, PSOutMode modeA);
+ // 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);
+
// Destructor -- writes the trailer and closes the file.
virtual ~PSOutputDev();
//----- PostScript XObjects
virtual void psXObject(Stream *psStream, Stream *level1Stream);
+
private:
+ void init(PSOutputFunc outputFuncA, void *outputStreamA,
+ PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA);
void setupResources(Dict *resDict);
void setupFonts(Dict *resDict);
void setupFont(GfxFont *font, Dict *parentResDict);
double *x1, double *y1);
GBool getFileSpec(Object *fileSpec, Object *fileName);
#endif
- void writePS(const char *fmt, ...);
- void writePSString(GString *s);
void writePSChar(char c);
+ void writePS(char *s);
+ void writePSFmt(const char *fmt, ...);
+ void writePSString(GString *s);
+ void writePSName(char *s);
GString *filterPSName(GString *name);
PSLevel level; // PostScript level (1, 2, separation)
int paperWidth; // width of paper, in pts
int paperHeight; // height of paper, in pts
- FILE *f; // PostScript file
+ PSOutputFunc outputFunc;
+ void *outputStream;
PSFileType fileType; // file / pipe / stdout
int seqPage; // current sequential page number
#endif
GBool ok; // set up ok?
+
};
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
+#include "GlobalParams.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
// Page
//------------------------------------------------------------------------
-Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
- GBool printCommandsA) {
-
+Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
ok = gTrue;
xref = xrefA;
num = numA;
- printCommands = printCommandsA;
// get attributes
attrs = attrsA;
}
void Page::display(OutputDev *out, double dpi, int rotate,
- Links *links, Catalog *catalog) {
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ displaySlice(out, dpi, rotate, -1, -1, -1, -1, links, catalog,
+ abortCheckCbk, abortCheckCbkData);
+}
+
+void Page::displaySlice(OutputDev *out, double dpi, int rotate,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
#ifndef PDF_PARSER_ONLY
- PDFRectangle *box, *cropBox;
+ PDFRectangle *mediaBox, *cropBox;
+ PDFRectangle box;
Gfx *gfx;
Object obj;
Link *link;
- int i;
Annots *annotList;
+ double k;
+ int i;
- box = getBox();
+ rotate += getRotate();
+ if (rotate >= 360) {
+ rotate -= 360;
+ } else if (rotate < 0) {
+ rotate += 360;
+ }
+
+ mediaBox = getBox();
+ if (sliceW >= 0 && sliceH >= 0) {
+ k = 72.0 / dpi;
+ if (rotate == 90) {
+ if (out->upsideDown()) {
+ box.x1 = mediaBox->x1 + k * sliceY;
+ box.x2 = mediaBox->x1 + k * (sliceY + sliceH);
+ } else {
+ box.x1 = mediaBox->x2 - k * (sliceY + sliceH);
+ box.x2 = mediaBox->x2 - k * sliceY;
+ }
+ box.y1 = mediaBox->y1 + k * sliceX;
+ box.y2 = mediaBox->y1 + k * (sliceX + sliceW);
+ } else if (rotate == 180) {
+ box.x1 = mediaBox->x2 - k * (sliceX + sliceW);
+ box.x2 = mediaBox->x2 - k * sliceX;
+ if (out->upsideDown()) {
+ box.y1 = mediaBox->y1 + k * sliceY;
+ box.y2 = mediaBox->y1 + k * (sliceY + sliceH);
+ } else {
+ box.y1 = mediaBox->y2 - k * (sliceY + sliceH);
+ box.y2 = mediaBox->y2 - k * sliceY;
+ }
+ } else if (rotate == 270) {
+ if (out->upsideDown()) {
+ box.x1 = mediaBox->x2 - k * (sliceY + sliceH);
+ box.x2 = mediaBox->x2 - k * sliceY;
+ } else {
+ box.x1 = mediaBox->x1 + k * sliceY;
+ box.x2 = mediaBox->x1 + k * (sliceY + sliceH);
+ }
+ box.y1 = mediaBox->y2 - k * (sliceX + sliceW);
+ box.y2 = mediaBox->y2 - k * sliceX;
+ } else {
+ box.x1 = mediaBox->x1 + k * sliceX;
+ box.x2 = mediaBox->x1 + k * (sliceX + sliceW);
+ if (out->upsideDown()) {
+ box.y1 = mediaBox->y2 - k * (sliceY + sliceH);
+ box.y2 = mediaBox->y2 - k * sliceY;
+ } else {
+ box.y1 = mediaBox->y1 + k * sliceY;
+ box.y2 = mediaBox->y1 + k * (sliceY + sliceH);
+ }
+ }
+ } else {
+ box = *mediaBox;
+ }
cropBox = getCropBox();
- if (printCommands) {
+ if (globalParams->getPrintCommands()) {
printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
- box->x1, box->y1, box->x2, box->y2);
+ box.x1, box.y1, box.x2, box.y2);
if (isCropped()) {
printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
printf("***** Rotate = %d\n", attrs->getRotate());
}
- rotate += getRotate();
- if (rotate >= 360) {
- rotate -= 360;
- } else if (rotate < 0) {
- rotate += 360;
- }
gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
- dpi, box, isCropped(), cropBox, rotate, printCommands);
+ dpi, &box, isCropped(), cropBox, rotate,
+ abortCheckCbk, abortCheckCbkData);
contents.fetch(xref, &obj);
if (!obj.isNull()) {
gfx->display(&obj);
annotList = new Annots(xref, annots.fetch(xref, &obj));
obj.free();
if (annotList->getNumAnnots() > 0) {
- if (printCommands) {
+ if (globalParams->getPrintCommands()) {
printf("***** Annotations\n");
}
for (i = 0; i < annotList->getNumAnnots(); ++i) {
#ifndef PAGE_H
#define PAGE_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//------------------------------------------------------------------------
-struct PDFRectangle {
+class PDFRectangle {
+public:
double x1, y1, x2, y2;
+
+ PDFRectangle() { x1 = y1 = x2 = y2 = 0; }
+ PDFRectangle(double x1A, double y1A, double x2A, double y2A)
+ { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
+ GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
};
//------------------------------------------------------------------------
public:
// Constructor.
- Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
- GBool printCommandsA);
+ Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA);
// Destructor.
~Page();
// Display a page.
void display(OutputDev *out, double dpi, int rotate,
- Links *links, Catalog *catalog);
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display part of a page.
+ void displaySlice(OutputDev *out, double dpi, int rotate,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
private:
PageAttrs *attrs; // page attributes
Object annots; // annotations array
Object contents; // page contents
- GBool printCommands; // print the drawing commands (for debugging)
GBool ok; // true if page is valid
};
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
} else {
key = copyString(buf1.getName());
shift();
- if (buf1.isEOF() || buf1.isError())
+ if (buf1.isEOF() || buf1.isError()) {
+ gfree(key);
break;
+ }
#ifndef NO_DECRYPTION
obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
#else
void Parser::shift() {
if (inlineImg > 0) {
- ++inlineImg;
+ if (inlineImg < 2) {
+ ++inlineImg;
+ } else {
+ // in a damaged content stream, if 'ID' shows up in the middle
+ // of a dictionary, we need to reset
+ inlineImg = 0;
+ }
} else if (buf2.isCmd("ID")) {
lexer->skipChar(); // skip char after 'ID' command
inlineImg = 1;
#ifndef PARSER_H
#define PARSER_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "Decrypt.h"
#endif
#include "Stream.h"
+#include "JBIG2Stream.h"
#include "Stream-CCITT.h"
#ifdef __DJGPP__
#endif
#ifdef VMS
-#if (__VMS_VER < 70000000)
-extern "C" int unlink(char *filename);
-#endif
#ifdef __GNUC__
#define SEEK_SET 0
#define SEEK_CUR 1
#endif
#endif
-#ifdef MACOS
-#include "StuffItEngineLib.h"
-#endif
-
//------------------------------------------------------------------------
// Stream (base class)
//------------------------------------------------------------------------
int encoding;
GBool endOfLine, byteAlign, endOfBlock, black;
int columns, rows;
- Object obj;
+ Object globals, obj;
if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
str = new ASCIIHexStream(str);
obj.free();
}
str = new FlateStream(str, pred, columns, colors, bits);
+ } else if (!strcmp(name, "JBIG2Decode")) {
+ if (params->isDict()) {
+ params->dictLookup("JBIG2Globals", &globals);
+ }
+ str = new JBIG2Stream(str, &globals);
+ globals.free();
} else {
error(getPos(), "Unknown filter '%s'", name);
str = new EOFStream(str);
}
GBool ImageStream::getPixel(Guchar *pix) {
+ int i;
+
+ if (imgIdx >= nVals) {
+ getLine();
+ imgIdx = 0;
+ }
+ for (i = 0; i < nComps; ++i) {
+ pix[i] = imgLine[imgIdx++];
+ }
+ return gTrue;
+}
+
+Guchar *ImageStream::getLine() {
Gulong buf, bitMask;
int bits;
int c;
int i;
- if (imgIdx >= nVals) {
-
- // read one line of image pixels
- if (nBits == 1) {
- for (i = 0; i < nVals; i += 8) {
- c = str->getChar();
- imgLine[i+0] = (Guchar)((c >> 7) & 1);
- imgLine[i+1] = (Guchar)((c >> 6) & 1);
- imgLine[i+2] = (Guchar)((c >> 5) & 1);
- imgLine[i+3] = (Guchar)((c >> 4) & 1);
- imgLine[i+4] = (Guchar)((c >> 3) & 1);
- imgLine[i+5] = (Guchar)((c >> 2) & 1);
- imgLine[i+6] = (Guchar)((c >> 1) & 1);
- imgLine[i+7] = (Guchar)(c & 1);
- }
- } else if (nBits == 8) {
- for (i = 0; i < nVals; ++i) {
- imgLine[i] = str->getChar();
- }
- } else {
- bitMask = (1 << nBits) - 1;
- buf = 0;
- bits = 0;
- for (i = 0; i < nVals; ++i) {
- if (bits < nBits) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bits += 8;
- }
- imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
- bits -= nBits;
+ if (nBits == 1) {
+ for (i = 0; i < nVals; i += 8) {
+ c = str->getChar();
+ imgLine[i+0] = (Guchar)((c >> 7) & 1);
+ imgLine[i+1] = (Guchar)((c >> 6) & 1);
+ imgLine[i+2] = (Guchar)((c >> 5) & 1);
+ imgLine[i+3] = (Guchar)((c >> 4) & 1);
+ imgLine[i+4] = (Guchar)((c >> 3) & 1);
+ imgLine[i+5] = (Guchar)((c >> 2) & 1);
+ imgLine[i+6] = (Guchar)((c >> 1) & 1);
+ imgLine[i+7] = (Guchar)(c & 1);
+ }
+ } else if (nBits == 8) {
+ for (i = 0; i < nVals; ++i) {
+ imgLine[i] = str->getChar();
+ }
+ } else {
+ bitMask = (1 << nBits) - 1;
+ buf = 0;
+ bits = 0;
+ for (i = 0; i < nVals; ++i) {
+ if (bits < nBits) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bits += 8;
}
+ imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
+ bits -= nBits;
}
-
- // reset to start of line
- imgIdx = 0;
}
-
- for (i = 0; i < nComps; ++i)
- pix[i] = imgLine[imgIdx++];
- return gTrue;
+ return imgLine;
}
void ImageStream::skipLine() {
}
void FileStream::reset() {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ savePos = (Guint)ftello(f);
+ fseeko(f, start, SEEK_SET);
+#elif HAVE_FSEEK64
savePos = (Guint)ftell64(f);
fseek64(f, start, SEEK_SET);
#else
void FileStream::close() {
if (saved) {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, savePos, SEEK_SET);
+#elif HAVE_FSEEK64
fseek64(f, savePos, SEEK_SET);
#else
fseek(f, savePos, SEEK_SET);
Guint size;
if (dir >= 0) {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, pos, SEEK_SET);
+#elif HAVE_FSEEK64
fseek64(f, pos, SEEK_SET);
#else
fseek(f, pos, SEEK_SET);
#endif
bufPos = pos;
} else {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, 0, SEEK_END);
+ size = (Guint)ftello(f);
+#elif HAVE_FSEEK64
fseek64(f, 0, SEEK_END);
size = (Guint)ftell64(f);
#else
//~ work around a bug in cygwin's implementation of fseek
rewind(f);
#endif
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftello(f);
+#elif HAVE_FSEEK64
fseek64(f, -(int)pos, SEEK_END);
bufPos = (Guint)ftell64(f);
#else
pred = NULL;
}
early = earlyA;
- zPipe = NULL;
- bufPtr = bufEnd = buf;
+ eof = gFalse;
+ inputBits = 0;
+ clearTable();
}
LZWStream::~LZWStream() {
- if (zPipe) {
-#ifdef HAVE_POPEN
- pclose(zPipe);
-#else
- fclose(zPipe);
-#endif
- zPipe = NULL;
- unlink(zName->getCString());
- delete zName;
- }
if (pred) {
delete pred;
}
if (pred) {
return pred->getChar();
}
- return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex++];
}
int LZWStream::lookChar() {
if (pred) {
return pred->lookChar();
}
- return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex];
}
int LZWStream::getRawChar() {
- return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex++];
}
void LZWStream::reset() {
- FILE *f;
- GString *zCmd;
+ str->reset();
+ eof = gFalse;
+ inputBits = 0;
+ clearTable();
+}
- //----- close old LZW stream
- if (zPipe) {
-#ifdef HAVE_POPEN
- pclose(zPipe);
-#else
- fclose(zPipe);
-#endif
- zPipe = NULL;
- unlink(zName->getCString());
- delete zName;
- }
+GBool LZWStream::processNextCode() {
+ int code;
+ int nextLength;
+ int i, j;
- //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
- // to run gzip
-#if __DJGPP__
- if (!setDJSYSFLAGS) {
- setenv("DJSYSFLAGS", "0x0002", 0);
- setDJSYSFLAGS = gTrue;
+ // check for EOF
+ if (eof) {
+ return gFalse;
}
-#endif
- //----- create the .Z file
- if (!openTempFile(&zName, &f, "wb", ".Z")) {
- error(getPos(), "Couldn't create temporary file for LZW stream");
- return;
- }
- dumpFile(f);
- fclose(f);
-
- //----- execute uncompress / gzip
- zCmd = new GString(uncompressCmd);
- zCmd->append(' ');
- zCmd->append(zName);
-#if defined(MACOS)
- long magicCookie;
- // first we open the engine up
- OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
- // if we found it - let's use it!
- if (!err && magicCookie) {
- // make sure we have the correct version of the Engine
- if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
- FSSpec myFSS;
- Str255 pName;
- strcpy((char *)pName, zName->getCString());
- c2pstr((char *)pName);
- FSMakeFSSpec(0, 0, pName, &myFSS);
- short ftype = DetermineFileType(magicCookie, &myFSS);
- OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
- NULL, NULL, kCreateFolderNever,
- kDeleteOriginal, kTextConvertSmart);
- }
- }
-#elif defined(HAVE_POPEN)
- if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
- error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
- unlink(zName->getCString());
- delete zName;
- return;
- }
-#else // HAVE_POPEN
- if (!executeCommand(zCmd->getCString())) {
- error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
- unlink(zName->getCString());
- delete zName;
- return;
+ // check for eod and clear-table codes
+ start:
+ code = getCode();
+ if (code == EOF || code == 257) {
+ eof = gTrue;
+ return gFalse;
}
- zName->del(zName->getLength() - 2, 2);
- if (!(zPipe = fopen(zName->getCString(), "rb"))) {
- error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
- unlink(zName->getCString());
- delete zName;
- return;
+ if (code == 256) {
+ clearTable();
+ goto start;
+ }
+ if (nextCode >= 4097) {
+ error(getPos(), "Bad LZW stream - expected clear-table code");
+ clearTable();
+ }
+
+ // process the next code
+ nextLength = seqLength + 1;
+ if (code < 256) {
+ seqBuf[0] = code;
+ seqLength = 1;
+ } else if (code < nextCode) {
+ seqLength = table[code].length;
+ for (i = seqLength - 1, j = code; i > 0; --i) {
+ seqBuf[i] = table[j].tail;
+ j = table[j].head;
+ }
+ seqBuf[0] = j;
+ } else if (code == nextCode) {
+ seqBuf[seqLength] = newChar;
+ ++seqLength;
+ } else {
+ error(getPos(), "Bad LZW stream - unexpected code");
+ eof = gTrue;
+ return gFalse;
}
-#endif // HAVE_POPEN
-
- //----- clean up
- delete zCmd;
+ newChar = seqBuf[0];
+ if (first) {
+ first = gFalse;
+ } else {
+ table[nextCode].length = nextLength;
+ table[nextCode].head = prevCode;
+ table[nextCode].tail = newChar;
+ ++nextCode;
+ if (nextCode + early == 512)
+ nextBits = 10;
+ else if (nextCode + early == 1024)
+ nextBits = 11;
+ else if (nextCode + early == 2048)
+ nextBits = 12;
+ }
+ prevCode = code;
+
+ // reset buffer
+ seqIndex = 0;
- //----- initialize buffer
- bufPtr = bufEnd = buf;
+ return gTrue;
}
-void LZWStream::dumpFile(FILE *f) {
- int outCodeBits; // size of output code
- int outBits; // max output code
- int outBuf[8]; // output buffer
- int outData; // temporary output buffer
- int inCode, outCode; // input and output codes
- int nextCode; // next code index
- GBool eof; // set when EOF is reached
- GBool clear; // set if table needs to be cleared
- GBool first; // indicates first code word after clear
- int i, j;
-
- str->reset();
-
- // magic number
- fputc(0x1f, f);
- fputc(0x9d, f);
-
- // max code length, block mode flag
- fputc(0x8c, f);
-
- // init input side
- inCodeBits = 9;
- inputBuf = 0;
- inputBits = 0;
- eof = gFalse;
-
- // init output side
- outCodeBits = 9;
-
- // clear table
- first = gTrue;
+void LZWStream::clearTable() {
nextCode = 258;
-
- clear = gFalse;
- do {
- for (i = 0; i < 8; ++i) {
- // check for table overflow
- if (nextCode + early > 0x1001) {
- inCode = 256;
-
- // read input code
- } else {
- do {
- inCode = getCode();
- if (inCode == EOF) {
- eof = gTrue;
- inCode = 0;
- }
- } while (first && inCode == 256);
- }
-
- // compute output code
- if (inCode < 256) {
- outCode = inCode;
- } else if (inCode == 256) {
- outCode = 256;
- clear = gTrue;
- } else if (inCode == 257) {
- outCode = 0;
- eof = gTrue;
- } else {
- outCode = inCode - 1;
- }
- outBuf[i] = outCode;
-
- // next code index
- if (first)
- first = gFalse;
- else
- ++nextCode;
-
- // check input code size
- if (nextCode + early == 0x200)
- inCodeBits = 10;
- else if (nextCode + early == 0x400) {
- inCodeBits = 11;
- } else if (nextCode + early == 0x800) {
- inCodeBits = 12;
- }
-
- // check for eof/clear
- if (eof)
- break;
- if (clear) {
- i = 8;
- break;
- }
- }
-
- // write output block
- outData = 0;
- outBits = 0;
- j = 0;
- while (j < i || outBits > 0) {
- if (outBits < 8 && j < i) {
- outData = outData | (outBuf[j++] << outBits);
- outBits += outCodeBits;
- }
- fputc(outData & 0xff, f);
- outData >>= 8;
- outBits -= 8;
- }
-
- // check output code size
- if (nextCode - 1 == 512 ||
- nextCode - 1 == 1024 ||
- nextCode - 1 == 2048 ||
- nextCode - 1 == 4096) {
- outCodeBits = inCodeBits;
- }
-
- // clear table if necessary
- if (clear) {
- inCodeBits = 9;
- outCodeBits = 9;
- first = gTrue;
- nextCode = 258;
- clear = gFalse;
- }
- } while (!eof);
+ nextBits = 9;
+ seqIndex = seqLength = 0;
+ first = gTrue;
}
int LZWStream::getCode() {
int c;
int code;
- while (inputBits < inCodeBits) {
+ while (inputBits < nextBits) {
if ((c = str->getChar()) == EOF)
return EOF;
inputBuf = (inputBuf << 8) | (c & 0xff);
inputBits += 8;
}
- code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
- inputBits -= inCodeBits;
+ code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
+ inputBits -= nextBits;
return code;
}
-GBool LZWStream::fillBuf() {
- int n;
-
- if (!zPipe)
- return gFalse;
- if ((n = fread(buf, 1, 256, zPipe)) < 256) {
-#ifdef HAVE_POPEN
- pclose(zPipe);
-#else
- fclose(zPipe);
-#endif
- zPipe = NULL;
- unlink(zName->getCString());
- delete zName;
- }
- bufPtr = buf;
- bufEnd = buf + n;
- return n > 0;
-}
-
GString *LZWStream::getPSFilter(char *indent) {
GString *s;
//------------------------------------------------------------------------
// IDCT constants (20.12 fixed point format)
-#ifndef FP_IDCT
#define dctCos1 4017 // cos(pi/16)
#define dctSin1 799 // sin(pi/16)
#define dctCos3 3406 // cos(3*pi/16)
#define dctSin6 3784 // sin(6*pi/16)
#define dctSqrt2 5793 // sqrt(2)
#define dctSqrt1d2 2896 // sqrt(2) / 2
-#endif
-
-// IDCT constants
-#ifdef FP_IDCT
-#define dctCos1 0.98078528 // cos(pi/16)
-#define dctSin1 0.19509032 // sin(pi/16)
-#define dctCos3 0.83146961 // cos(3*pi/16)
-#define dctSin3 0.55557023 // sin(3*pi/16)
-#define dctCos6 0.38268343 // cos(6*pi/16)
-#define dctSin6 0.92387953 // sin(6*pi/16)
-#define dctSqrt2 1.41421356 // sqrt(2)
-#define dctSqrt1d2 0.70710678 // sqrt(2) / 2
-#endif
// color conversion parameters (16.16 fixed point format)
#define dctCrToR 91881 // 1.4020
FilterStream(strA) {
int i, j;
+ progressive = interleaved = gFalse;
width = height = 0;
mcuWidth = mcuHeight = 0;
numComps = 0;
comp = 0;
x = y = dy = 0;
- for (i = 0; i < 4; ++i)
- for (j = 0; j < 32; ++j)
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 32; ++j) {
rowBuf[i][j] = NULL;
+ }
+ frameBuf[i] = NULL;
+ }
if (!dctClipInit) {
for (i = -256; i < 0; ++i)
int i, j;
delete str;
- for (i = 0; i < numComps; ++i)
- for (j = 0; j < mcuHeight; ++j)
- gfree(rowBuf[i][j]);
+ if (progressive || !interleaved) {
+ for (i = 0; i < numComps; ++i) {
+ gfree(frameBuf[i]);
+ }
+ } else {
+ for (i = 0; i < numComps; ++i) {
+ for (j = 0; j < mcuHeight; ++j) {
+ gfree(rowBuf[i][j]);
+ }
+ }
+ }
}
void DCTStream::reset() {
+ int minHSample, minVSample;
+ int i, j;
+
str->reset();
+
+ progressive = interleaved = gFalse;
+ width = height = 0;
+ numComps = 0;
+ numQuantTables = 0;
+ numDCHuffTables = 0;
+ numACHuffTables = 0;
+ colorXform = 0;
+ gotAdobeMarker = gFalse;
+ restartInterval = 0;
+
if (!readHeader()) {
y = height;
return;
}
- restartMarker = 0xd0;
- restart();
+
+ // compute MCU size
+ mcuWidth = minHSample = compInfo[0].hSample;
+ mcuHeight = minVSample = compInfo[0].vSample;
+ for (i = 1; i < numComps; ++i) {
+ if (compInfo[i].hSample < minHSample)
+ minHSample = compInfo[i].hSample;
+ if (compInfo[i].vSample < minVSample)
+ minVSample = compInfo[i].vSample;
+ if (compInfo[i].hSample > mcuWidth)
+ mcuWidth = compInfo[i].hSample;
+ if (compInfo[i].vSample > mcuHeight)
+ mcuHeight = compInfo[i].vSample;
+ }
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].hSample /= minHSample;
+ compInfo[i].vSample /= minVSample;
+ }
+ mcuWidth = (mcuWidth / minHSample) * 8;
+ mcuHeight = (mcuHeight / minVSample) * 8;
+
+ // figure out color transform
+ if (!gotAdobeMarker && numComps == 3) {
+ if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
+ colorXform = 1;
+ }
+ }
+
+ if (progressive || !interleaved) {
+
+ // allocate a buffer for the whole image
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
+ bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
+ for (i = 0; i < numComps; ++i) {
+ frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
+ memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
+ }
+
+ // read the image data
+ do {
+ restartMarker = 0xd0;
+ restart();
+ readScan();
+ } while (readHeader());
+
+ // decode
+ decodeImage();
+
+ // initialize counters
+ comp = 0;
+ x = 0;
+ y = 0;
+
+ } else {
+
+ // allocate a buffer for one row of MCUs
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
+ for (i = 0; i < numComps; ++i) {
+ for (j = 0; j < mcuHeight; ++j) {
+ rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
+ }
+ }
+
+ // initialize counters
+ comp = 0;
+ x = 0;
+ y = 0;
+ dy = mcuHeight;
+
+ restartMarker = 0xd0;
+ restart();
+ }
}
int DCTStream::getChar() {
int c;
- c = lookChar();
- if (c == EOF)
+ if (y >= height) {
return EOF;
- if (++comp == numComps) {
- comp = 0;
- if (++x == width) {
+ }
+ if (progressive || !interleaved) {
+ c = frameBuf[comp][y * bufWidth + x];
+ if (++comp == numComps) {
+ comp = 0;
+ if (++x == width) {
+ x = 0;
+ ++y;
+ }
+ }
+ } else {
+ if (dy >= mcuHeight) {
+ if (!readMCURow()) {
+ y = height;
+ return EOF;
+ }
+ comp = 0;
x = 0;
- ++y;
- ++dy;
+ dy = 0;
+ }
+ c = rowBuf[comp][dy][x];
+ if (++comp == numComps) {
+ comp = 0;
+ if (++x == width) {
+ x = 0;
+ ++y;
+ ++dy;
+ if (y == height) {
+ readTrailer();
+ }
+ }
}
}
- if (y == height)
- readTrailer();
return c;
}
int DCTStream::lookChar() {
- if (y >= height)
+ if (y >= height) {
return EOF;
- if (dy >= mcuHeight) {
- if (!readMCURow()) {
- y = height;
- return EOF;
+ }
+ if (progressive || !interleaved) {
+ return frameBuf[comp][y * bufWidth + x];
+ } else {
+ if (dy >= mcuHeight) {
+ if (!readMCURow()) {
+ y = height;
+ return EOF;
+ }
+ comp = 0;
+ x = 0;
+ dy = 0;
}
- comp = 0;
- x = 0;
- dy = 0;
+ return rowBuf[comp][dy][x];
}
- return rowBuf[comp][dy][x];
}
void DCTStream::restart() {
inputBits = 0;
restartCtr = restartInterval;
- for (i = 0; i < numComps; ++i)
+ for (i = 0; i < numComps; ++i) {
compInfo[i].prevDC = 0;
+ }
+ eobRun = 0;
}
+// Read one row of MCUs from a sequential JPEG stream.
GBool DCTStream::readMCURow() {
- Guchar data[64];
+ int data1[64];
+ Guchar data2[64];
Guchar *p1, *p2;
int pY, pCb, pCr, pR, pG, pB;
int h, v, horiz, vert, hSub, vSub;
vSub = vert / 8;
for (y2 = 0; y2 < mcuHeight; y2 += vert) {
for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
- if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
- &acHuffTables[compInfo[cc].acHuffTable],
- quantTables[compInfo[cc].quantTable],
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
&compInfo[cc].prevDC,
- data))
+ data1)) {
return gFalse;
+ }
+ transformDataUnit(quantTables[compInfo[cc].quantTable],
+ data1, data2);
if (hSub == 1 && vSub == 1) {
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
p1 = &rowBuf[cc][y2+y3][x1+x2];
- p1[0] = data[i];
- p1[1] = data[i+1];
- p1[2] = data[i+2];
- p1[3] = data[i+3];
- p1[4] = data[i+4];
- p1[5] = data[i+5];
- p1[6] = data[i+6];
- p1[7] = data[i+7];
+ p1[0] = data2[i];
+ p1[1] = data2[i+1];
+ p1[2] = data2[i+2];
+ p1[3] = data2[i+3];
+ p1[4] = data2[i+4];
+ p1[5] = data2[i+5];
+ p1[6] = data2[i+6];
+ p1[7] = data2[i+7];
}
} else if (hSub == 2 && vSub == 2) {
for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
p1 = &rowBuf[cc][y2+y3][x1+x2];
p2 = &rowBuf[cc][y2+y3+1][x1+x2];
- p1[0] = p1[1] = p2[0] = p2[1] = data[i];
- p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
- p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
- p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
- p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
- p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
- p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
- p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
+ p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
+ p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
+ p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
+ p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
+ p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
+ p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
+ p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
+ p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
}
} else {
i = 0;
for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
for (y5 = 0; y5 < vSub; ++y5)
for (x5 = 0; x5 < hSub; ++x5)
- rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
+ rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
++i;
}
}
return gTrue;
}
-// This IDCT algorithm is taken from:
-// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
-// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
-// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
-// 988-991.
-// The stage numbers mentioned in the comments refer to Figure 1 in this
-// paper.
-#ifndef FP_IDCT
-GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- Guchar quantTable[64], int *prevDC,
- Guchar data[64]) {
- int tmp1[64];
- int v0, v1, v2, v3, v4, v5, v6, v7, t;
- int run, size, amp;
+// Read one scan from a progressive or non-interleaved JPEG stream.
+void DCTStream::readScan() {
+ int data[64];
+ int x1, y1, dy1, x2, y2, y3, cc, i;
+ int h, v, horiz, vert, hSub, vSub;
+ int *p1;
int c;
- int i, j;
- // Huffman decode and dequantize
- size = readHuffSym(dcHuffTable);
- if (size == 9999)
- return gFalse;
- if (size > 0) {
- amp = readAmp(size);
- if (amp == 9999)
- return gFalse;
+ if (scanInfo.numComps == 1) {
+ for (cc = 0; cc < numComps; ++cc) {
+ if (scanInfo.comp[cc]) {
+ break;
+ }
+ }
+ dy1 = mcuHeight / compInfo[cc].vSample;
+ } else {
+ dy1 = mcuHeight;
+ }
+
+ for (y1 = 0; y1 < bufHeight; y1 += dy1) {
+ for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
+
+ // deal with restart marker
+ if (restartInterval > 0 && restartCtr == 0) {
+ c = readMarker();
+ if (c != restartMarker) {
+ error(getPos(), "Bad DCT data: incorrect restart marker");
+ return;
+ }
+ if (++restartMarker == 0xd8) {
+ restartMarker = 0xd0;
+ }
+ restart();
+ }
+
+ // read one MCU
+ for (cc = 0; cc < numComps; ++cc) {
+ if (!scanInfo.comp[cc]) {
+ continue;
+ }
+
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ hSub = horiz / 8;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < dy1; y2 += vert) {
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
+
+ // pull out the current values
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ data[i] = p1[0];
+ data[i+1] = p1[1];
+ data[i+2] = p1[2];
+ data[i+3] = p1[3];
+ data[i+4] = p1[4];
+ data[i+5] = p1[5];
+ data[i+6] = p1[6];
+ data[i+7] = p1[7];
+ p1 += bufWidth * vSub;
+ }
+
+ // read one data unit
+ if (progressive) {
+ if (!readProgressiveDataUnit(
+ &dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data)) {
+ return;
+ }
+ } else {
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data)) {
+ return;
+ }
+ }
+
+ // add the data unit into frameBuf
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1[0] = data[i];
+ p1[1] = data[i+1];
+ p1[2] = data[i+2];
+ p1[3] = data[i+3];
+ p1[4] = data[i+4];
+ p1[5] = data[i+5];
+ p1[6] = data[i+6];
+ p1[7] = data[i+7];
+ p1 += bufWidth * vSub;
+ }
+ }
+ }
+ }
+ --restartCtr;
+ }
+ }
+}
+
+// Read one data unit from a sequential JPEG stream.
+GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]) {
+ int run, size, amp;
+ int c;
+ int i, j;
+
+ if ((size = readHuffSym(dcHuffTable)) == 9999) {
+ return gFalse;
+ }
+ if (size > 0) {
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
} else {
amp = 0;
}
- tmp1[0] = (*prevDC += amp) * quantTable[0];
- for (i = 1; i < 64; ++i)
- tmp1[i] = 0;
+ data[0] = *prevDC += amp;
+ for (i = 1; i < 64; ++i) {
+ data[i] = 0;
+ }
i = 1;
while (i < 64) {
run = 0;
- while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
+ while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
run += 0x10;
- if (c == 9999)
+ }
+ if (c == 9999) {
return gFalse;
+ }
if (c == 0x00) {
break;
} else {
run += (c >> 4) & 0x0f;
size = c & 0x0f;
amp = readAmp(size);
- if (amp == 9999)
+ if (amp == 9999) {
return gFalse;
+ }
i += run;
j = dctZigZag[i++];
- tmp1[j] = amp * quantTable[j];
+ data[j] = amp;
+ }
+ }
+ return gTrue;
+}
+
+// Read one data unit from a sequential JPEG stream.
+GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]) {
+ int run, size, amp, bit, c;
+ int i, j, k;
+
+ // get the DC coefficient
+ i = scanInfo.firstCoeff;
+ if (i == 0) {
+ if (scanInfo.ah == 0) {
+ if ((size = readHuffSym(dcHuffTable)) == 9999) {
+ return gFalse;
+ }
+ if (size > 0) {
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ } else {
+ amp = 0;
+ }
+ data[0] += (*prevDC += amp) << scanInfo.al;
+ } else {
+ if ((bit = readBit()) == 9999) {
+ return gFalse;
+ }
+ data[0] += bit << scanInfo.al;
+ }
+ ++i;
+ }
+ if (scanInfo.lastCoeff == 0) {
+ return gTrue;
+ }
+
+ // check for an EOB run
+ if (eobRun > 0) {
+ while (i <= scanInfo.lastCoeff) {
+ j = dctZigZag[i++];
+ if (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
}
+ --eobRun;
+ return gTrue;
+ }
+
+ // read the AC coefficients
+ while (i <= scanInfo.lastCoeff) {
+ if ((c = readHuffSym(acHuffTable)) == 9999) {
+ return gFalse;
+ }
+
+ // ZRL
+ if (c == 0xf0) {
+ k = 0;
+ while (k < 16) {
+ j = dctZigZag[i++];
+ if (data[j] == 0) {
+ ++k;
+ } else {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+
+ // EOB run
+ } else if ((c & 0x0f) == 0x00) {
+ j = c >> 4;
+ eobRun = 0;
+ for (k = 0; k < j; ++k) {
+ if ((bit = readBit()) == EOF) {
+ return 9999;
+ }
+ eobRun = (eobRun << 1) | bit;
+ }
+ eobRun += 1 << j;
+ while (i <= scanInfo.lastCoeff) {
+ j = dctZigZag[i++];
+ if (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+ --eobRun;
+ break;
+
+ // zero run and one AC coefficient
+ } else {
+ run = (c >> 4) & 0x0f;
+ size = c & 0x0f;
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ k = 0;
+ do {
+ j = dctZigZag[i++];
+ while (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ j = dctZigZag[i++];
+ }
+ ++k;
+ } while (k <= run);
+ data[j] = amp << scanInfo.al;
+ }
+ }
+
+ return gTrue;
+}
+
+// Decode a progressive JPEG image.
+void DCTStream::decodeImage() {
+ int dataIn[64];
+ Guchar dataOut[64];
+ Guchar *quantTable;
+ int pY, pCb, pCr, pR, pG, pB;
+ int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
+ int h, v, horiz, vert, hSub, vSub;
+ int *p0, *p1, *p2;
+
+ for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
+ for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
+ for (cc = 0; cc < numComps; ++cc) {
+ quantTable = quantTables[compInfo[cc].quantTable];
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ hSub = horiz / 8;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < mcuHeight; y2 += vert) {
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
+
+ // pull out the coded data unit
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ dataIn[i] = p1[0];
+ dataIn[i+1] = p1[1];
+ dataIn[i+2] = p1[2];
+ dataIn[i+3] = p1[3];
+ dataIn[i+4] = p1[4];
+ dataIn[i+5] = p1[5];
+ dataIn[i+6] = p1[6];
+ dataIn[i+7] = p1[7];
+ p1 += bufWidth * vSub;
+ }
+
+ // transform
+ transformDataUnit(quantTable, dataIn, dataOut);
+
+ // store back into frameBuf, doing replication for
+ // subsampled components
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ if (hSub == 1 && vSub == 1) {
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1[0] = dataOut[i] & 0xff;
+ p1[1] = dataOut[i+1] & 0xff;
+ p1[2] = dataOut[i+2] & 0xff;
+ p1[3] = dataOut[i+3] & 0xff;
+ p1[4] = dataOut[i+4] & 0xff;
+ p1[5] = dataOut[i+5] & 0xff;
+ p1[6] = dataOut[i+6] & 0xff;
+ p1[7] = dataOut[i+7] & 0xff;
+ p1 += bufWidth;
+ }
+ } else if (hSub == 2 && vSub == 2) {
+ p2 = p1 + bufWidth;
+ for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
+ p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
+ p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
+ p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
+ p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
+ p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
+ p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
+ p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
+ p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
+ p1 += bufWidth * 2;
+ p2 += bufWidth * 2;
+ }
+ } else {
+ i = 0;
+ for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
+ for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
+ p2 = p1 + x4;
+ for (y5 = 0; y5 < vSub; ++y5) {
+ for (x5 = 0; x5 < hSub; ++x5) {
+ p2[x5] = dataOut[i] & 0xff;
+ }
+ p2 += bufWidth;
+ }
+ ++i;
+ }
+ p1 += bufWidth * vSub;
+ }
+ }
+ }
+ }
+ }
+
+ // color space conversion
+ if (colorXform) {
+ // convert YCbCr to RGB
+ if (numComps == 3) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = *p0;
+ pCb = *p1 - 128;
+ pCr = *p2 - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ *p0++ = dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
+ 32768) >> 16;
+ *p1++ = dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ *p2++ = dctClip[dctClipOffset + pB];
+ }
+ }
+ // convert YCbCrK to CMYK (K is passed through unchanged)
+ } else if (numComps == 4) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = *p0;
+ pCb = *p1 - 128;
+ pCr = *p2 - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ *p0++ = 255 - dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
+ 32768) >> 16;
+ *p1++ = 255 - dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ *p2++ = 255 - dctClip[dctClipOffset + pB];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Transform one data unit -- this performs the dequantization and
+// IDCT steps. This IDCT algorithm is taken from:
+// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
+// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
+// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
+// 988-991.
+// The stage numbers mentioned in the comments refer to Figure 1 in this
+// paper.
+void DCTStream::transformDataUnit(Guchar *quantTable,
+ int dataIn[64], Guchar dataOut[64]) {
+ int v0, v1, v2, v3, v4, v5, v6, v7, t;
+ int *p;
+ int i;
+
+ // dequant
+ for (i = 0; i < 64; ++i) {
+ dataIn[i] *= quantTable[i];
}
// inverse DCT on rows
for (i = 0; i < 64; i += 8) {
+ p = dataIn + i;
+
+ // check for all-zero AC coefficients
+ if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
+ p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
+ t = (dctSqrt2 * p[0] + 512) >> 10;
+ p[0] = t;
+ p[1] = t;
+ p[2] = t;
+ p[3] = t;
+ p[4] = t;
+ p[5] = t;
+ p[6] = t;
+ p[7] = t;
+ continue;
+ }
// stage 4
- v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
- v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
- v2 = tmp1[i+2];
- v3 = tmp1[i+6];
- v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
- v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
- v5 = tmp1[i+3] << 4;
- v6 = tmp1[i+5] << 4;
+ v0 = (dctSqrt2 * p[0] + 128) >> 8;
+ v1 = (dctSqrt2 * p[4] + 128) >> 8;
+ v2 = p[2];
+ v3 = p[6];
+ v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
+ v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
+ v5 = p[3] << 4;
+ v6 = p[5] << 4;
// stage 3
t = (v0 - v1+ 1) >> 1;
v6 = t;
// stage 1
- tmp1[i+0] = v0 + v7;
- tmp1[i+7] = v0 - v7;
- tmp1[i+1] = v1 + v6;
- tmp1[i+6] = v1 - v6;
- tmp1[i+2] = v2 + v5;
- tmp1[i+5] = v2 - v5;
- tmp1[i+3] = v3 + v4;
- tmp1[i+4] = v3 - v4;
+ p[0] = v0 + v7;
+ p[7] = v0 - v7;
+ p[1] = v1 + v6;
+ p[6] = v1 - v6;
+ p[2] = v2 + v5;
+ p[5] = v2 - v5;
+ p[3] = v3 + v4;
+ p[4] = v3 - v4;
}
// inverse DCT on columns
for (i = 0; i < 8; ++i) {
+ p = dataIn + i;
+
+ // check for all-zero AC coefficients
+ if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
+ p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
+ t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
+ p[0*8] = t;
+ p[1*8] = t;
+ p[2*8] = t;
+ p[3*8] = t;
+ p[4*8] = t;
+ p[5*8] = t;
+ p[6*8] = t;
+ p[7*8] = t;
+ continue;
+ }
// stage 4
- v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
- v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
- v2 = tmp1[2*8+i];
- v3 = tmp1[6*8+i];
- v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
- v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
- v5 = tmp1[3*8+i];
- v6 = tmp1[5*8+i];
+ v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
+ v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
+ v2 = p[2*8];
+ v3 = p[6*8];
+ v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
+ v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
+ v5 = p[3*8];
+ v6 = p[5*8];
// stage 3
t = (v0 - v1 + 1) >> 1;
v6 = t;
// stage 1
- tmp1[0*8+i] = v0 + v7;
- tmp1[7*8+i] = v0 - v7;
- tmp1[1*8+i] = v1 + v6;
- tmp1[6*8+i] = v1 - v6;
- tmp1[2*8+i] = v2 + v5;
- tmp1[5*8+i] = v2 - v5;
- tmp1[3*8+i] = v3 + v4;
- tmp1[4*8+i] = v3 - v4;
+ p[0*8] = v0 + v7;
+ p[7*8] = v0 - v7;
+ p[1*8] = v1 + v6;
+ p[6*8] = v1 - v6;
+ p[2*8] = v2 + v5;
+ p[5*8] = v2 - v5;
+ p[3*8] = v3 + v4;
+ p[4*8] = v3 - v4;
}
// convert to 8-bit integers
- for (i = 0; i < 64; ++i)
- data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
-
- return gTrue;
-}
-#endif
-
-#ifdef FP_IDCT
-GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
- DCTHuffTable *acHuffTable,
- Guchar quantTable[64], int *prevDC,
- Guchar data[64]) {
- double tmp1[64];
- double v0, v1, v2, v3, v4, v5, v6, v7, t;
- int run, size, amp;
- int c;
- int i, j;
-
- // Huffman decode and dequantize
- size = readHuffSym(dcHuffTable);
- if (size == 9999)
- return gFalse;
- if (size > 0) {
- amp = readAmp(size);
- if (amp == 9999)
- return gFalse;
- } else {
- amp = 0;
- }
- tmp1[0] = (*prevDC += amp) * quantTable[0];
- for (i = 1; i < 64; ++i)
- tmp1[i] = 0;
- i = 1;
- while (i < 64) {
- run = 0;
- while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
- run += 0x10;
- if (c == 9999)
- return gFalse;
- if (c == 0x00) {
- break;
- } else {
- run += (c >> 4) & 0x0f;
- size = c & 0x0f;
- amp = readAmp(size);
- if (amp == 9999)
- return gFalse;
- i += run;
- j = dctZigZag[i++];
- tmp1[j] = amp * quantTable[j];
- }
- }
-
- // inverse DCT on rows
- for (i = 0; i < 64; i += 8) {
-
- // stage 4
- v0 = dctSqrt2 * tmp1[i+0];
- v1 = dctSqrt2 * tmp1[i+4];
- v2 = tmp1[i+2];
- v3 = tmp1[i+6];
- v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
- v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
- v5 = tmp1[i+3];
- v6 = tmp1[i+5];
-
- // stage 3
- t = 0.5 * (v0 - v1);
- v0 = 0.5 * (v0 + v1);
- v1 = t;
- t = v2 * dctSin6 + v3 * dctCos6;
- v2 = v2 * dctCos6 - v3 * dctSin6;
- v3 = t;
- t = 0.5 * (v4 - v6);
- v4 = 0.5 * (v4 + v6);
- v6 = t;
- t = 0.5 * (v7 + v5);
- v5 = 0.5 * (v7 - v5);
- v7 = t;
-
- // stage 2
- t = 0.5 * (v0 - v3);
- v0 = 0.5 * (v0 + v3);
- v3 = t;
- t = 0.5 * (v1 - v2);
- v1 = 0.5 * (v1 + v2);
- v2 = t;
- t = v4 * dctSin3 + v7 * dctCos3;
- v4 = v4 * dctCos3 - v7 * dctSin3;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1;
- v5 = v5 * dctCos1 - v6 * dctSin1;
- v6 = t;
-
- // stage 1
- tmp1[i+0] = v0 + v7;
- tmp1[i+7] = v0 - v7;
- tmp1[i+1] = v1 + v6;
- tmp1[i+6] = v1 - v6;
- tmp1[i+2] = v2 + v5;
- tmp1[i+5] = v2 - v5;
- tmp1[i+3] = v3 + v4;
- tmp1[i+4] = v3 - v4;
+ for (i = 0; i < 64; ++i) {
+ dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
}
-
- // inverse DCT on columns
- for (i = 0; i < 8; ++i) {
-
- // stage 4
- v0 = dctSqrt2 * tmp1[0*8+i];
- v1 = dctSqrt2 * tmp1[4*8+i];
- v2 = tmp1[2*8+i];
- v3 = tmp1[6*8+i];
- v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
- v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
- v5 = tmp1[3*8+i];
- v6 = tmp1[5*8+i];
-
- // stage 3
- t = 0.5 * (v0 - v1);
- v0 = 0.5 * (v0 + v1);
- v1 = t;
- t = v2 * dctSin6 + v3 * dctCos6;
- v2 = v2 * dctCos6 - v3 * dctSin6;
- v3 = t;
- t = 0.5 * (v4 - v6);
- v4 = 0.5 * (v4 + v6);
- v6 = t;
- t = 0.5 * (v7 + v5);
- v5 = 0.5 * (v7 - v5);
- v7 = t;
-
- // stage 2
- t = 0.5 * (v0 - v3);
- v0 = 0.5 * (v0 + v3);
- v3 = t;
- t = 0.5 * (v1 - v2);
- v1 = 0.5 * (v1 + v2);
- v2 = t;
- t = v4 * dctSin3 + v7 * dctCos3;
- v4 = v4 * dctCos3 - v7 * dctSin3;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1;
- v5 = v5 * dctCos1 - v6 * dctSin1;
- v6 = t;
-
- // stage 1
- tmp1[0*8+i] = v0 + v7;
- tmp1[7*8+i] = v0 - v7;
- tmp1[1*8+i] = v1 + v6;
- tmp1[6*8+i] = v1 - v6;
- tmp1[2*8+i] = v2 + v5;
- tmp1[5*8+i] = v2 - v5;
- tmp1[3*8+i] = v3 + v4;
- tmp1[4*8+i] = v3 - v4;
- }
-
- // convert to 8-bit integers
- for (i = 0; i < 64; ++i)
- data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
-
- return gTrue;
}
-#endif
int DCTStream::readHuffSym(DCTHuffTable *table) {
Gushort code;
GBool DCTStream::readHeader() {
GBool doScan;
- int minHSample, minVSample;
- int bufWidth;
int n;
int c = 0;
- int i, j;
-
- width = height = 0;
- numComps = 0;
- numQuantTables = 0;
- numDCHuffTables = 0;
- numACHuffTables = 0;
- colorXform = 0;
- gotAdobeMarker = gFalse;
- restartInterval = 0;
+ int i;
// read headers
doScan = gFalse;
c = readMarker();
switch (c) {
case 0xc0: // SOF0
- if (!readFrameInfo())
+ if (!readBaselineSOF()) {
+ return gFalse;
+ }
+ break;
+ case 0xc2: // SOF2
+ if (!readProgressiveSOF()) {
return gFalse;
+ }
break;
case 0xc4: // DHT
- if (!readHuffmanTables())
+ if (!readHuffmanTables()) {
return gFalse;
+ }
break;
case 0xd8: // SOI
break;
+ case 0xd9: // EOI
+ return gFalse;
+ break;
case 0xda: // SOS
- if (!readScanInfo())
+ if (!readScanInfo()) {
return gFalse;
+ }
doScan = gTrue;
break;
case 0xdb: // DQT
- if (!readQuantTables())
+ if (!readQuantTables()) {
return gFalse;
+ }
break;
case 0xdd: // DRI
- if (!readRestartInterval())
+ if (!readRestartInterval()) {
return gFalse;
+ }
break;
case 0xee: // APP14
- if (!readAdobeMarker())
+ if (!readAdobeMarker()) {
return gFalse;
+ }
break;
case EOF:
error(getPos(), "Bad DCT header");
// skip APPn / COM / etc.
if (c >= 0xe0) {
n = read16() - 2;
- for (i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i) {
str->getChar();
+ }
} else {
error(getPos(), "Unknown DCT marker <%02x>", c);
return gFalse;
}
}
- // compute MCU size
- mcuWidth = minHSample = compInfo[0].hSample;
- mcuHeight = minVSample = compInfo[0].vSample;
- for (i = 1; i < numComps; ++i) {
- if (compInfo[i].hSample < minHSample)
- minHSample = compInfo[i].hSample;
- if (compInfo[i].vSample < minVSample)
- minVSample = compInfo[i].vSample;
- if (compInfo[i].hSample > mcuWidth)
- mcuWidth = compInfo[i].hSample;
- if (compInfo[i].vSample > mcuHeight)
- mcuHeight = compInfo[i].vSample;
- }
- for (i = 0; i < numComps; ++i) {
- compInfo[i].hSample /= minHSample;
- compInfo[i].vSample /= minVSample;
- }
- mcuWidth = (mcuWidth / minHSample) * 8;
- mcuHeight = (mcuHeight / minVSample) * 8;
+ return gTrue;
+}
- // allocate buffers
- bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
- for (i = 0; i < numComps; ++i)
- for (j = 0; j < mcuHeight; ++j)
- rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
+GBool DCTStream::readBaselineSOF() {
+ int length;
+ int prec;
+ int i;
+ int c;
- // figure out color transform
- if (!gotAdobeMarker && numComps == 3) {
- if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
- colorXform = 1;
- }
+ length = read16();
+ prec = str->getChar();
+ height = read16();
+ width = read16();
+ numComps = str->getChar();
+ if (prec != 8) {
+ error(getPos(), "Bad DCT precision %d", prec);
+ return gFalse;
}
-
- // initialize counters
- comp = 0;
- x = 0;
- y = 0;
- dy = mcuHeight;
-
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].id = str->getChar();
+ c = str->getChar();
+ compInfo[i].hSample = (c >> 4) & 0x0f;
+ compInfo[i].vSample = c & 0x0f;
+ compInfo[i].quantTable = str->getChar();
+ }
+ progressive = gFalse;
return gTrue;
}
-GBool DCTStream::readFrameInfo() {
+GBool DCTStream::readProgressiveSOF() {
int length;
int prec;
int i;
int c;
- length = read16() - 2;
+ length = read16();
prec = str->getChar();
height = read16();
width = read16();
numComps = str->getChar();
- length -= 6;
if (prec != 8) {
error(getPos(), "Bad DCT precision %d", prec);
return gFalse;
}
for (i = 0; i < numComps; ++i) {
compInfo[i].id = str->getChar();
- compInfo[i].inScan = gFalse;
c = str->getChar();
compInfo[i].hSample = (c >> 4) & 0x0f;
compInfo[i].vSample = c & 0x0f;
compInfo[i].quantTable = str->getChar();
- compInfo[i].dcHuffTable = 0;
- compInfo[i].acHuffTable = 0;
}
+ progressive = gTrue;
return gTrue;
}
GBool DCTStream::readScanInfo() {
int length;
- int scanComps, id, c;
+ int id, c;
int i, j;
length = read16() - 2;
- scanComps = str->getChar();
+ scanInfo.numComps = str->getChar();
--length;
- if (length != 2 * scanComps + 3) {
+ if (length != 2 * scanInfo.numComps + 3) {
error(getPos(), "Bad DCT scan info block");
return gFalse;
}
- for (i = 0; i < scanComps; ++i) {
+ interleaved = scanInfo.numComps == numComps;
+ for (j = 0; j < numComps; ++j) {
+ scanInfo.comp[j] = gFalse;
+ }
+ for (i = 0; i < scanInfo.numComps; ++i) {
id = str->getChar();
for (j = 0; j < numComps; ++j) {
- if (id == compInfo[j].id)
+ if (id == compInfo[j].id) {
break;
+ }
}
if (j == numComps) {
error(getPos(), "Bad DCT component ID in scan info block");
return gFalse;
}
- compInfo[j].inScan = gTrue;
+ scanInfo.comp[j] = gTrue;
c = str->getChar();
- compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
- compInfo[j].acHuffTable = c & 0x0f;
+ scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
+ scanInfo.acHuffTable[j] = c & 0x0f;
}
- str->getChar();
- str->getChar();
- str->getChar();
+ scanInfo.firstCoeff = str->getChar();
+ scanInfo.lastCoeff = str->getChar();
+ c = str->getChar();
+ scanInfo.ah = (c >> 4) & 0x0f;
+ scanInfo.al = c & 0x0f;
return gTrue;
}
int c;
length = read16();
- if (length != 14)
+ if (length < 14) {
goto err;
+ }
for (i = 0; i < 12; ++i) {
- if ((c = str->getChar()) == EOF)
+ if ((c = str->getChar()) == EOF) {
goto err;
+ }
buf[i] = c;
}
- if (strncmp(buf, "Adobe", 5))
+ if (strncmp(buf, "Adobe", 5)) {
goto err;
+ }
colorXform = buf[11];
gotAdobeMarker = gTrue;
+ for (i = 14; i < length; ++i) {
+ if (str->getChar() == EOF) {
+ goto err;
+ }
+ }
return gTrue;
err:
} else {
pred = NULL;
}
+ litCodeTab.codes = NULL;
+ distCodeTab.codes = NULL;
}
FlateStream::~FlateStream() {
+ gfree(litCodeTab.codes);
+ gfree(distCodeTab.codes);
if (pred) {
delete pred;
}
int c;
int check;
+ // free the code tables from the previous block
+ gfree(litCodeTab.codes);
+ litCodeTab.codes = NULL;
+ gfree(distCodeTab.codes);
+ distCodeTab.codes = NULL;
+
// read block header
blockHdr = getCodeWord(3);
if (blockHdr & 1)
// compressed block with dynamic codes
} else if (blockHdr == 2) {
compressedBlock = gTrue;
- if (!readDynamicCodes())
+ if (!readDynamicCodes()) {
goto err;
+ }
// unknown block type
} else {
void FlateStream::loadFixedCodes() {
int i;
- // set up code arrays
- litCodeTab.codes = allCodes;
- distCodeTab.codes = allCodes + flateMaxLitCodes;
-
- // initialize literal code table
- for (i = 0; i <= 143; ++i)
- litCodeTab.codes[i].len = 8;
- for (i = 144; i <= 255; ++i)
- litCodeTab.codes[i].len = 9;
- for (i = 256; i <= 279; ++i)
- litCodeTab.codes[i].len = 7;
- for (i = 280; i <= 287; ++i)
- litCodeTab.codes[i].len = 8;
- compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
-
- // initialize distance code table
- for (i = 0; i <= 5; ++i) {
- distCodeTab.start[i] = 0;
+ // build the literal code table
+ for (i = 0; i <= 143; ++i) {
+ codeLengths[i] = 8;
+ }
+ for (i = 144; i <= 255; ++i) {
+ codeLengths[i] = 9;
}
- for (i = 6; i <= flateMaxHuffman+1; ++i) {
- distCodeTab.start[i] = flateMaxDistCodes;
+ for (i = 256; i <= 279; ++i) {
+ codeLengths[i] = 7;
}
+ for (i = 280; i <= 287; ++i) {
+ codeLengths[i] = 8;
+ }
+ compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
+
+ // build the distance code table
for (i = 0; i < flateMaxDistCodes; ++i) {
- distCodeTab.codes[i].len = 5;
- distCodeTab.codes[i].code = i;
- distCodeTab.codes[i].val = i;
+ codeLengths[i] = 5;
}
+ compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
}
GBool FlateStream::readDynamicCodes() {
int numCodeLenCodes;
int numLitCodes;
int numDistCodes;
- FlateCode codeLenCodes[flateMaxCodeLenCodes];
+ int codeLenCodeLengths[flateMaxCodeLenCodes];
FlateHuffmanTab codeLenCodeTab;
int len, repeat, code;
int i;
// read lengths
- if ((numLitCodes = getCodeWord(5)) == EOF)
+ if ((numLitCodes = getCodeWord(5)) == EOF) {
goto err;
+ }
numLitCodes += 257;
- if ((numDistCodes = getCodeWord(5)) == EOF)
+ if ((numDistCodes = getCodeWord(5)) == EOF) {
goto err;
+ }
numDistCodes += 1;
- if ((numCodeLenCodes = getCodeWord(4)) == EOF)
+ if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
goto err;
+ }
numCodeLenCodes += 4;
if (numLitCodes > flateMaxLitCodes ||
numDistCodes > flateMaxDistCodes ||
- numCodeLenCodes > flateMaxCodeLenCodes)
+ numCodeLenCodes > flateMaxCodeLenCodes) {
goto err;
+ }
- // read code length code table
- codeLenCodeTab.codes = codeLenCodes;
- for (i = 0; i < flateMaxCodeLenCodes; ++i)
- codeLenCodes[i].len = 0;
+ // build the code length code table
+ for (i = 0; i < flateMaxCodeLenCodes; ++i) {
+ codeLenCodeLengths[i] = 0;
+ }
for (i = 0; i < numCodeLenCodes; ++i) {
- if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
+ if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
goto err;
+ }
}
- compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
+ compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
- // set up code arrays
- litCodeTab.codes = allCodes;
- distCodeTab.codes = allCodes + numLitCodes;
-
- // read literal and distance code tables
+ // build the literal and distance code tables
len = 0;
repeat = 0;
i = 0;
while (i < numLitCodes + numDistCodes) {
- if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
+ if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
goto err;
+ }
if (code == 16) {
- if ((repeat = getCodeWord(2)) == EOF)
+ if ((repeat = getCodeWord(2)) == EOF) {
goto err;
- for (repeat += 3; repeat > 0; --repeat)
- allCodes[i++].len = len;
+ }
+ for (repeat += 3; repeat > 0; --repeat) {
+ codeLengths[i++] = len;
+ }
} else if (code == 17) {
- if ((repeat = getCodeWord(3)) == EOF)
+ if ((repeat = getCodeWord(3)) == EOF) {
goto err;
+ }
len = 0;
- for (repeat += 3; repeat > 0; --repeat)
- allCodes[i++].len = 0;
+ for (repeat += 3; repeat > 0; --repeat) {
+ codeLengths[i++] = 0;
+ }
} else if (code == 18) {
- if ((repeat = getCodeWord(7)) == EOF)
+ if ((repeat = getCodeWord(7)) == EOF) {
goto err;
+ }
len = 0;
- for (repeat += 11; repeat > 0; --repeat)
- allCodes[i++].len = 0;
+ for (repeat += 11; repeat > 0; --repeat) {
+ codeLengths[i++] = 0;
+ }
} else {
- allCodes[i++].len = len = code;
+ codeLengths[i++] = len = code;
}
}
- compHuffmanCodes(&litCodeTab, numLitCodes);
- compHuffmanCodes(&distCodeTab, numDistCodes);
+ compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
+ compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
+ gfree(codeLenCodeTab.codes);
return gTrue;
err:
error(getPos(), "Bad dynamic code table in flate stream");
+ gfree(codeLenCodeTab.codes);
return gFalse;
}
-// On entry, the <tab->codes> array contains the lengths of each code,
-// stored in code value order. This function computes the code words.
-// The result is sorted in order of (1) code length and (2) code word.
-// The length values are no longer valid. The <tab->start> array is
-// filled with the indexes of the first code of each length.
-void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
- int numLengths[flateMaxHuffman+1];
- int nextCode[flateMaxHuffman+1];
- int nextIndex[flateMaxHuffman+2];
- int code;
- int i, j;
+// Convert an array <lengths> of <n> lengths, in value order, into a
+// Huffman code lookup table.
+void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
+ int tabSize, len, code, code2, skip, val, i, t;
- // count number of codes for each code length
- for (i = 0; i <= flateMaxHuffman; ++i)
- numLengths[i] = 0;
- for (i = 0; i < n; ++i)
- ++numLengths[tab->codes[i].len];
+ // find max code length
+ tab->maxLen = 0;
+ for (val = 0; val < n; ++val) {
+ if (lengths[val] > tab->maxLen) {
+ tab->maxLen = lengths[val];
+ }
+ }
- // compute first index for each length
- tab->start[0] = nextIndex[0] = 0;
- for (i = 1; i <= flateMaxHuffman + 1; ++i)
- tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
+ // allocate the table
+ tabSize = 1 << tab->maxLen;
+ tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
- // compute first code for each length
- code = 0;
- numLengths[0] = 0;
- for (i = 1; i <= flateMaxHuffman; ++i) {
- code = (code + numLengths[i-1]) << 1;
- nextCode[i] = code;
+ // clear the table
+ for (i = 0; i < tabSize; ++i) {
+ tab->codes[i].len = 0;
+ tab->codes[i].val = 0;
}
- // compute the codes -- this permutes the codes array from value
- // order to length/code order
- for (i = 0; i < n; ++i) {
- j = nextIndex[tab->codes[i].len]++;
- if (tab->codes[i].len == 0)
- tab->codes[j].code = 0;
- else
- tab->codes[j].code = nextCode[tab->codes[i].len]++;
- tab->codes[j].val = i;
+ // build the table
+ for (len = 1, code = 0, skip = 2;
+ len <= tab->maxLen;
+ ++len, code <<= 1, skip <<= 1) {
+ for (val = 0; val < n; ++val) {
+ if (lengths[val] == len) {
+
+ // bit-reverse the code
+ code2 = 0;
+ t = code;
+ for (i = 0; i < len; ++i) {
+ code2 = (code2 << 1) | (t & 1);
+ t >>= 1;
+ }
+
+ // fill in the table entries
+ for (i = code2; i < tabSize; i += skip) {
+ tab->codes[i].len = (Gushort)len;
+ tab->codes[i].val = (Gushort)val;
+ }
+
+ ++code;
+ }
+ }
}
}
int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
- int len;
- int code;
+ FlateCode *code;
int c;
- int i, j;
-
- code = 0;
- for (len = 1; len <= flateMaxHuffman; ++len) {
-
- // add a bit to the code
- if (codeSize == 0) {
- if ((c = str->getChar()) == EOF)
- return EOF;
- codeBuf = c & 0xff;
- codeSize = 8;
- }
- code = (code << 1) | (codeBuf & 1);
- codeBuf >>= 1;
- --codeSize;
- // look for code
- i = tab->start[len];
- j = tab->start[len + 1];
- if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
- i += code - tab->codes[i].code;
- return tab->codes[i].val;
+ while (codeSize < tab->maxLen) {
+ if ((c = str->getChar()) == EOF) {
+ break;
}
+ codeBuf |= (c & 0xff) << codeSize;
+ codeSize += 8;
}
-
- // not found
- error(getPos(), "Bad code (%04x) in flate stream", code);
- return EOF;
+ code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
+ if (codeSize == 0 || codeSize < code->len || code->len == 0) {
+ return EOF;
+ }
+ codeBuf >>= code->len;
+ codeSize -= code->len;
+ return (int)code->val;
}
int FlateStream::getCodeWord(int bits) {
#ifndef STREAM_H
#define STREAM_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
strCCITTFax,
strDCT,
strFlate,
+ strJBIG2,
strWeird // internal-use stream types
};
// at least nComps elements. Returns false at end of file.
GBool getPixel(Guchar *pix);
+ // Returns a pointer to the next line of pixels. Returns NULL at
+ // end of file.
+ Guchar *getLine();
+
// Skip an entire line from the image.
void skipLine();
StreamPredictor *pred; // predictor
int early; // early parameter
- FILE *zPipe; // uncompress pipe
- GString *zName; // .Z file name
+ GBool eof; // true if at eof
int inputBuf; // input buffer
int inputBits; // number of bits in input buffer
- int inCodeBits; // size of input code
- char buf[256]; // buffer
- char *bufPtr; // next char to read
- char *bufEnd; // end of buffer
-
- void dumpFile(FILE *f);
+ struct { // decoding table
+ int length;
+ int head;
+ Guchar tail;
+ } table[4097];
+ int nextCode; // next code to be used
+ int nextBits; // number of bits in next code word
+ int prevCode; // previous code used in stream
+ int newChar; // next char to be added to table
+ Guchar seqBuf[4097]; // buffer for current sequence
+ int seqLength; // length of current sequence
+ int seqIndex; // index into current sequence
+ GBool first; // first code after a table clear
+
+ GBool processNextCode();
+ void clearTable();
int getCode();
- GBool fillBuf();
};
//------------------------------------------------------------------------
// DCT component info
struct DCTCompInfo {
int id; // component ID
- GBool inScan; // is this component in the current scan?
int hSample, vSample; // horiz/vert sampling resolutions
int quantTable; // quantization table number
- int dcHuffTable, acHuffTable; // Huffman table numbers
int prevDC; // DC coefficient accumulator
};
+struct DCTScanInfo {
+ GBool comp[4]; // comp[i] is set if component i is
+ // included in this scan
+ int numComps; // number of components in the scan
+ int dcHuffTable[4]; // DC Huffman table numbers
+ int acHuffTable[4]; // AC Huffman table numbers
+ int firstCoeff, lastCoeff; // first and last DCT coefficient
+ int ah, al; // successive approximation parameters
+};
+
// DCT Huffman decoding table
struct DCTHuffTable {
Guchar firstSym[17]; // first symbol for this bit length
private:
+ GBool progressive; // set if in progressive mode
+ GBool interleaved; // set if in interleaved mode
int width, height; // image size
int mcuWidth, mcuHeight; // size of min coding unit, in data units
+ int bufWidth, bufHeight; // frameBuf size
DCTCompInfo compInfo[4]; // info for each component
+ DCTScanInfo scanInfo; // info for the current scan
int numComps; // number of components in image
int colorXform; // need YCbCr-to-RGB transform?
GBool gotAdobeMarker; // set if APP14 Adobe marker was present
DCTHuffTable acHuffTables[4]; // AC Huffman tables
int numDCHuffTables; // number of DC Huffman tables
int numACHuffTables; // number of AC Huffman tables
- Guchar *rowBuf[4][32]; // buffer for one MCU
+ Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
+ int *frameBuf[4]; // buffer for frame (progressive mode)
int comp, x, y, dy; // current position within image/MCU
int restartCtr; // MCUs left until restart
int restartMarker; // next restart marker
+ int eobRun; // number of EOBs left in the current run
int inputBuf; // input buffer for variable length codes
int inputBits; // number of valid bits in input buffer
void restart();
GBool readMCURow();
- GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable,
- Guchar quantTable[64], int *prevDC, Guchar data[64]);
+ void readScan();
+ GBool readDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]);
+ GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]);
+ void decodeImage();
+ void transformDataUnit(Guchar *quantTable,
+ int dataIn[64], Guchar dataOut[64]);
int readHuffSym(DCTHuffTable *table);
int readAmp(int size);
int readBit();
GBool readHeader();
- GBool readFrameInfo();
+ GBool readBaselineSOF();
+ GBool readProgressiveSOF();
GBool readScanInfo();
GBool readQuantTables();
GBool readHuffmanTables();
// Huffman code table entry
struct FlateCode {
- int len; // code length in bits
- int code; // code word
- int val; // value represented by this code
+ Gushort len; // code length, in bits
+ Gushort val; // value represented by this code
};
-// Huffman code table
struct FlateHuffmanTab {
- int start[flateMaxHuffman+2]; // indexes of first code of each length
- FlateCode *codes; // codes, sorted by length and code word
+ FlateCode *codes;
+ int maxLen;
};
// Decoding info for length and distance code words
int remain; // number valid bytes in output buffer
int codeBuf; // input buffer
int codeSize; // number of bits in input buffer
- FlateCode // literal and distance codes
- allCodes[flateMaxLitCodes + flateMaxDistCodes];
+ int // literal and distance code lengths
+ codeLengths[flateMaxLitCodes + flateMaxDistCodes];
FlateHuffmanTab litCodeTab; // literal code table
FlateHuffmanTab distCodeTab; // distance code table
GBool compressedBlock; // set if reading a compressed block
GBool startBlock();
void loadFixedCodes();
GBool readDynamicCodes();
- void compHuffmanCodes(FlateHuffmanTab *tab, int n);
+ void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
int getHuffmanCodeWord(FlateHuffmanTab *tab);
int getCodeWord(int bits);
};
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "ICSupport.h"
#endif
+//------------------------------------------------------------------------
+
+#define textOutSpace 0.2
+#define textOutColSpace 0.2
+
+//------------------------------------------------------------------------
+
+struct TextOutColumnEdge {
+ double x, y0, y1;
+};
+
+//------------------------------------------------------------------------
+// TextBlock
+//------------------------------------------------------------------------
+
+class TextBlock {
+public:
+
+ TextBlock();
+ ~TextBlock();
+
+ double xMin, xMax;
+ double yMin, yMax;
+ TextString *strings; // list of strings in the block
+ TextBlock *next; // next block in line
+ TextBlock *xyNext; // next block on xyBlocks list
+ Unicode *text; // Unicode text of the block, including
+ // spaces between strings
+ double *xRight; // right-hand x coord of each char
+ int len; // total number of Unicode characters
+ int convertedLen; // total number of converted characters
+ int *col; // starting column number for each
+ // Unicode character
+};
+
+TextBlock::TextBlock() {
+ strings = NULL;
+ next = NULL;
+ xyNext = NULL;
+ text = NULL;
+ xRight = NULL;
+ col = NULL;
+}
+
+TextBlock::~TextBlock() {
+ TextString *p1, *p2;
+
+ for (p1 = strings; p1; p1 = p2) {
+ p2 = p1->next;
+ delete p1;
+ }
+ gfree(text);
+ gfree(xRight);
+ gfree(col);
+}
+
+//------------------------------------------------------------------------
+// TextLine
+//------------------------------------------------------------------------
+
+class TextLine {
+public:
+
+ TextLine();
+ ~TextLine();
+
+ TextBlock *blocks;
+ TextLine *next;
+ double yMin, yMax;
+};
+
+TextLine::TextLine() {
+ blocks = NULL;
+ next = NULL;
+}
+
+TextLine::~TextLine() {
+ TextBlock *p1, *p2;
+
+ for (p1 = blocks; p1; p1 = p2) {
+ p2 = p1->next;
+ delete p1;
+ }
+}
+
//------------------------------------------------------------------------
// TextString
//------------------------------------------------------------------------
-TextString::TextString(GfxState *state, double fontSize) {
+TextString::TextString(GfxState *state, double x0, double y0,
+ double fontSize) {
GfxFont *font;
double x, y;
- state->transform(state->getCurX(), state->getCurY(), &x, &y);
+ state->transform(x0, y0, &x, &y);
if ((font = state->getFont())) {
yMin = y - font->getAscent() * fontSize;
yMax = y - font->getDescent() * fontSize;
yMin = y;
yMax = y + 1;
}
- col = 0;
+ marked = gFalse;
text = NULL;
xRight = NULL;
len = size = 0;
- yxNext = NULL;
- xyNext = NULL;
+ next = NULL;
}
+
TextString::~TextString() {
gfree(text);
gfree(xRight);
rawOrder = rawOrderA;
curStr = NULL;
fontSize = 0;
- yxStrings = NULL;
xyStrings = NULL;
- yxCur1 = yxCur2 = NULL;
+ xyCur1 = xyCur2 = NULL;
+ lines = NULL;
nest = 0;
+ nTinyChars = 0;
}
TextPage::~TextPage() {
GfxFont *font;
double *fm;
char *name;
- int code;
+ int code, mCode, letterCode, anyCode;
double w;
// adjust the font size
// 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').
+ mCode = letterCode = anyCode = -1;
for (code = 0; code < 256; ++code) {
- if ((name = ((Gfx8BitFont *)font)->getCharName(code)) &&
- name[0] == 'm' && name[1] == '\0') {
- break;
+ name = ((Gfx8BitFont *)font)->getCharName(code);
+ if (name && name[0] == 'm' && name[1] == '\0') {
+ mCode = code;
}
- }
- if (code < 256) {
- w = ((Gfx8BitFont *)font)->getWidth(code);
- if (w != 0) {
- // 600 is a generic average 'm' width -- yes, this is a hack
- fontSize *= w / 0.6;
+ if (letterCode < 0 && name && name[1] == '\0' &&
+ ((name[0] >= 'A' && name[0] <= 'Z') ||
+ (name[0] >= 'a' && name[0] <= 'z'))) {
+ letterCode = code;
}
+ if (anyCode < 0 && name && ((Gfx8BitFont *)font)->getWidth(code) > 0) {
+ anyCode = code;
+ }
+ }
+ if (mCode >= 0 &&
+ (w = ((Gfx8BitFont *)font)->getWidth(mCode)) > 0) {
+ // 0.6 is a generic average 'm' width -- yes, this is a hack
+ fontSize *= w / 0.6;
+ } else if (letterCode >= 0 &&
+ (w = ((Gfx8BitFont *)font)->getWidth(letterCode)) > 0) {
+ // even more of a hack: 0.5 is a generic letter width
+ fontSize *= w / 0.5;
+ } else if (anyCode >= 0 &&
+ (w = ((Gfx8BitFont *)font)->getWidth(anyCode)) > 0) {
+ // better than nothing: 0.5 is a generic character width
+ fontSize *= w / 0.5;
}
fm = font->getFontMatrix();
if (fm[0] != 0) {
}
}
-void TextPage::beginString(GfxState *state) {
+void TextPage::beginString(GfxState *state, double x0, double y0) {
// This check is needed because Type 3 characters can contain
// text-drawing operations.
if (curStr) {
return;
}
- curStr = new TextString(state, fontSize);
+ curStr = new TextString(state, x0, y0, fontSize);
}
void TextPage::addChar(GfxState *state, double x, double y,
int n, i;
state->transform(x, y, &x1, &y1);
- n = curStr->len;
- if (n > 0 &&
- x1 - curStr->xRight[n-1] > 0.1 * (curStr->yMax - curStr->yMin)) {
- endString();
- beginString(state);
+ if (x1 < 0 || x1 > state->getPageWidth() ||
+ y1 < 0 || y1 > state->getPageHeight()) {
+ return;
}
state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(),
0, &dx2, &dy2);
dx -= dx2;
dy -= dy2;
state->transformDelta(dx, dy, &w1, &h1);
+ if (!globalParams->getTextKeepTinyChars() &&
+ fabs(w1) < 3 && fabs(h1) < 3) {
+ if (++nTinyChars > 20000) {
+ return;
+ }
+ }
+ n = curStr->len;
+ if (n > 0 && x1 - curStr->xRight[n-1] >
+ 0.1 * (curStr->yMax - curStr->yMin)) {
+ // large char spacing is sometimes used to move text around
+ endString();
+ beginString(state, x, y);
+ }
+ if (uLen == 1 && u[0] == (Unicode)0x20 &&
+ w1 > 0.5 * (curStr->yMax - curStr->yMin)) {
+ // large word spacing is sometimes used to move text around
+ return;
+ }
if (uLen != 0) {
w1 /= uLen;
h1 /= uLen;
}
void TextPage::endString() {
- TextString *p1, *p2;
- double h, y1, y2;
-
// This check is needed because Type 3 characters can contain
// text-drawing operations.
if (nest > 0) {
return;
}
+ addString(curStr);
+ curStr = NULL;
+}
+
+void TextPage::addString(TextString *str) {
+ TextString *p1, *p2;
+
// throw away zero-length strings -- they don't have valid xMin/xMax
// values, and they're useless anyway
- if (curStr->len == 0) {
- delete curStr;
- curStr = NULL;
+ if (str->len == 0) {
+ delete str;
return;
}
- // insert string in y-major list
- h = curStr->yMax - curStr->yMin;
- y1 = curStr->yMin + 0.5 * h;
- y2 = curStr->yMin + 0.8 * h;
+ // insert string in xy list
if (rawOrder) {
- p1 = yxCur1;
+ p1 = xyCur1;
p2 = NULL;
- } else if ((!yxCur1 ||
- (y1 >= yxCur1->yMin &&
- (y2 >= yxCur1->yMax || curStr->xMax >= yxCur1->xMin))) &&
- (!yxCur2 ||
- (y1 < yxCur2->yMin ||
- (y2 < yxCur2->yMax && curStr->xMax < yxCur2->xMin)))) {
- p1 = yxCur1;
- p2 = yxCur2;
+ } else if ((!xyCur1 || xyBefore(xyCur1, str)) &&
+ (!xyCur2 || xyBefore(str, xyCur2))) {
+ p1 = xyCur1;
+ p2 = xyCur2;
+ } else if (xyCur1 && xyBefore(xyCur1, str)) {
+ for (p1 = xyCur1, p2 = xyCur2; p2; p1 = p2, p2 = p2->next) {
+ if (xyBefore(str, p2)) {
+ break;
+ }
+ }
+ xyCur2 = p2;
} else {
- for (p1 = NULL, p2 = yxStrings; p2; p1 = p2, p2 = p2->yxNext) {
- if (y1 < p2->yMin || (y2 < p2->yMax && curStr->xMax < p2->xMin)) {
+ for (p1 = NULL, p2 = xyStrings; p2; p1 = p2, p2 = p2->next) {
+ if (xyBefore(str, p2)) {
break;
}
}
- yxCur2 = p2;
+ xyCur2 = p2;
}
- yxCur1 = curStr;
+ xyCur1 = str;
if (p1) {
- p1->yxNext = curStr;
+ p1->next = str;
} else {
- yxStrings = curStr;
+ xyStrings = str;
}
- curStr->yxNext = p2;
- curStr = NULL;
+ str->next = p2;
}
void TextPage::coalesce() {
- TextString *str1, *str2;
- double space, d;
- GBool addSpace;
- int n, i;
+ TextLine *line, *line0;
+ TextBlock *yxBlocks, *xyBlocks, *blk, *blk0, *blk1, *blk2;
+ TextString *str0, *str1, *str2, *str3, *str4;
+ TextString *str1prev, *str2prev, *str3prev;
+ TextOutColumnEdge *edges;
+ UnicodeMap *uMap;
+ GBool isUnicode;
+ char buf[8];
+ int edgesLength, edgesSize;
+ double x, yMin, yMax;
+ double space, fit1, fit2, h;
+ int col1, col2, d;
+ int i, j;
#if 0 //~ for debugging
- for (str1 = yxStrings; str1; str1 = str1->yxNext) {
- printf("x=%3d..%3d y=%3d..%3d size=%2d '",
- (int)str1->xMin, (int)str1->xMax, (int)str1->yMin, (int)str1->yMax,
- (int)(str1->yMax - str1->yMin));
+ for (str1 = xyStrings; str1; str1 = str1->next) {
+ printf("x=%.2f..%.2f y=%.2f..%.2f size=%.2f '",
+ str1->xMin, str1->xMax, str1->yMin, str1->yMax,
+ (str1->yMax - str1->yMin));
for (i = 0; i < str1->len; ++i) {
fputc(str1->text[i] & 0xff, stdout);
}
}
printf("\n------------------------------------------------------------\n\n");
#endif
- str1 = yxStrings;
- while (str1 && (str2 = str1->yxNext)) {
- space = str1->yMax - str1->yMin;
- d = str2->xMin - str1->xMax;
- if (((rawOrder &&
- ((str2->yMin >= str1->yMin && str2->yMin <= str1->yMax) ||
- (str2->yMax >= str1->yMin && str2->yMax <= str1->yMax))) ||
- (!rawOrder && str2->yMin < str1->yMax)) &&
- d > -0.5 * space && d < space) {
- n = str1->len + str2->len;
- if ((addSpace = d > 0.1 * space)) {
- ++n;
- }
- str1->size = (n + 15) & ~15;
- str1->text = (Unicode *)grealloc(str1->text,
- str1->size * sizeof(Unicode));
- str1->xRight = (double *)grealloc(str1->xRight,
- str1->size * sizeof(double));
- if (addSpace) {
- str1->text[str1->len] = 0x20;
- str1->xRight[str1->len] = str2->xMin;
- ++str1->len;
- }
- for (i = 0; i < str2->len; ++i) {
- str1->text[str1->len] = str2->text[i];
- str1->xRight[str1->len] = str2->xRight[i];
- ++str1->len;
- }
- if (str2->xMax > str1->xMax) {
- str1->xMax = str2->xMax;
- }
- if (str2->yMax > str1->yMax) {
- str1->yMax = str2->yMax;
- }
- str1->yxNext = str2->yxNext;
- delete str2;
+
+ // build the list of column edges
+ edges = NULL;
+ edgesLength = edgesSize = 0;
+ if (!rawOrder) {
+ for (str1prev = NULL, str1 = xyStrings;
+ str1;
+ str1prev = str1, str1 = str1->next) {
+ if (str1->marked) {
+ continue;
+ }
+ h = str1->yMax - str1->yMin;
+ if (str1prev && (str1->xMin - str1prev->xMax) / h < textOutColSpace) {
+ continue;
+ }
+ x = str1->xMin;
+ yMin = str1->yMin;
+ yMax = str1->yMax;
+ for (str2prev = str1, str2 = str1->next;
+ str2;
+ str2prev = str2, str2 = str2->next) {
+ h = str2->yMax - str2->yMin;
+ if (!str2->marked &&
+ (str2->xMin - str2prev->xMax) / h > textOutColSpace &&
+ fabs(str2->xMin - x) < 0.5 &&
+ str2->yMin - yMax < 0.3 * h &&
+ yMin - str2->yMax < 0.3 * h) {
+ break;
+ }
+ }
+ if (str2) {
+ if (str2->yMin < yMin) {
+ yMin = str2->yMin;
+ }
+ if (str2->yMax > yMax) {
+ yMax = str2->yMax;
+ }
+ str2->marked = gTrue;
+ for (str3prev = str1, str3 = str1->next;
+ str3;
+ str3prev = str3, str3 = str3->next) {
+ h = str3->yMax - str3->yMin;
+ if (!str3->marked &&
+ (str3->xMin - str3prev->xMax) / h > textOutColSpace &&
+ fabs(str3->xMin - x) < 0.5 &&
+ str3->yMin - yMax < 0.3 * h &&
+ yMin - str3->yMax < 0.3 * h) {
+ break;
+ }
+ }
+ if (str3) {
+ if (str3->yMin < yMin) {
+ yMin = str3->yMin;
+ }
+ if (str3->yMax > yMax) {
+ yMax = str3->yMax;
+ }
+ str3->marked = gTrue;
+ do {
+ for (str2prev = str1, str2 = str1->next;
+ str2;
+ str2prev = str2, str2 = str2->next) {
+ h = str2->yMax - str2->yMin;
+ if (!str2->marked &&
+ (str2->xMin - str2prev->xMax) / h > textOutColSpace &&
+ fabs(str2->xMin - x) < 0.5 &&
+ str2->yMin - yMax < 0.3 * h &&
+ yMin - str2->yMax < 0.3 * h) {
+ if (str2->yMin < yMin) {
+ yMin = str2->yMin;
+ }
+ if (str2->yMax > yMax) {
+ yMax = str2->yMax;
+ }
+ str2->marked = gTrue;
+ break;
+ }
+ }
+ } while (str2);
+ if (edgesLength == edgesSize) {
+ edgesSize = edgesSize ? 2 * edgesSize : 16;
+ edges = (TextOutColumnEdge *)
+ grealloc(edges, edgesSize * sizeof(TextOutColumnEdge));
+ }
+ edges[edgesLength].x = x;
+ edges[edgesLength].y0 = yMin;
+ edges[edgesLength].y1 = yMax;
+ ++edgesLength;
+ } else {
+ str2->marked = gFalse;
+ }
+ }
+ str1->marked = gTrue;
+ }
+ }
+
+#if 0 //~ for debugging
+ printf("column edges:\n");
+ for (i = 0; i < edgesLength; ++i) {
+ printf("%d: x=%.2f y0=%.2f y1=%.2f\n",
+ i, edges[i].x, edges[i].y0, edges[i].y1);
+ }
+ printf("\n------------------------------------------------------------\n\n");
+#endif
+
+ // build the blocks
+ yxBlocks = NULL;
+ blk1 = blk2 = NULL;
+ while (xyStrings) {
+
+ // build the block
+ str0 = xyStrings;
+ xyStrings = xyStrings->next;
+ str0->next = NULL;
+ blk = new TextBlock();
+ blk->strings = str0;
+ blk->xMin = str0->xMin;
+ blk->xMax = str0->xMax;
+ blk->yMin = str0->yMin;
+ blk->yMax = str0->yMax;
+ while (xyStrings) {
+ str1 = NULL;
+ str2 = xyStrings;
+ fit1 = coalesceFit(str0, str2);
+ if (!rawOrder) {
+ // look for best-fitting string
+ space = str0->yMax - str0->yMin;
+ for (str3 = xyStrings, str4 = xyStrings->next;
+ str4 && str4->xMin - str0->xMax <= space;
+ str3 = str4, str4 = str4->next) {
+ fit2 = coalesceFit(str0, str4);
+ if (fit2 < fit1) {
+ str1 = str3;
+ str2 = str4;
+ fit1 = fit2;
+ }
+ }
+ }
+ if (fit1 > 1) {
+ // no fit - we're done with this block
+ break;
+ }
+
+ // if we've hit a column edge we're done with this block
+ if (fit1 > 0.2) {
+ for (i = 0; i < edgesLength; ++i) {
+ if (str0->xMax < edges[i].x + 0.5 && edges[i].x - 0.5 < str2->xMin &&
+ str0->yMin < edges[i].y1 && str0->yMax > edges[i].y0 &&
+ str2->yMin < edges[i].y1 && str2->yMax > edges[i].y0) {
+ break;
+ }
+ }
+ if (i < edgesLength) {
+ break;
+ }
+ }
+
+ if (str1) {
+ str1->next = str2->next;
+ } else {
+ xyStrings = str2->next;
+ }
+ str0->next = str2;
+ str2->next = NULL;
+ if (str2->xMax > blk->xMax) {
+ blk->xMax = str2->xMax;
+ }
+ if (str2->yMin < blk->yMin) {
+ blk->yMin = str2->yMin;
+ }
+ if (str2->yMax > blk->yMax) {
+ blk->yMax = str2->yMax;
+ }
+ str0 = str2;
+ }
+
+ // insert block on list
+ if (!rawOrder) {
+ // insert block on list in yx order
+ for (blk1 = NULL, blk2 = yxBlocks;
+ blk2 && !yxBefore(blk, blk2);
+ blk1 = blk2, blk2 = blk2->next) ;
+ }
+ blk->next = blk2;
+ if (blk1) {
+ blk1->next = blk;
+ } else {
+ yxBlocks = blk;
+ }
+ blk1 = blk;
+ }
+
+ gfree(edges);
+
+ // the strings are now owned by the lines/blocks tree
+ xyStrings = NULL;
+
+ // build the block text
+ uMap = globalParams->getTextEncoding();
+ isUnicode = uMap ? uMap->isUnicode() : gFalse;
+ for (blk = yxBlocks; blk; blk = blk->next) {
+ blk->len = 0;
+ for (str1 = blk->strings; str1; str1 = str1->next) {
+ blk->len += str1->len;
+ if (str1->next && str1->next->xMin - str1->xMax >
+ textOutSpace * (str1->yMax - str1->yMin)) {
+ str1->spaceAfter = gTrue;
+ ++blk->len;
+ } else {
+ str1->spaceAfter = gFalse;
+ }
+ }
+ blk->text = (Unicode *)gmalloc(blk->len * sizeof(Unicode));
+ blk->xRight = (double *)gmalloc(blk->len * sizeof(double));
+ blk->col = (int *)gmalloc(blk->len * sizeof(int));
+ i = 0;
+ for (str1 = blk->strings; str1; str1 = str1->next) {
+ for (j = 0; j < str1->len; ++j) {
+ blk->text[i] = str1->text[j];
+ blk->xRight[i] = str1->xRight[j];
+ ++i;
+ }
+ if (str1->spaceAfter) {
+ blk->text[i] = (Unicode)0x0020;
+ blk->xRight[i] = str1->next->xMin;
+ ++i;
+ }
+ }
+ blk->convertedLen = 0;
+ for (j = 0; j < blk->len; ++j) {
+ blk->col[j] = blk->convertedLen;
+ if (isUnicode) {
+ ++blk->convertedLen;
+ } else if (uMap) {
+ blk->convertedLen += uMap->mapUnicode(blk->text[j], buf, sizeof(buf));
+ }
+ }
+ }
+ if (uMap) {
+ uMap->decRefCnt();
+ }
+
+#if 0 //~ for debugging
+ for (blk = yxBlocks; blk; blk = blk->next) {
+ printf("[block: x=%.2f..%.2f y=%.2f..%.2f len=%d]\n",
+ blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->len);
+ TextString *str;
+ for (str = blk->strings; str; str = str->next) {
+ printf(" x=%.2f..%.2f y=%.2f..%.2f size=%.2f'",
+ str->xMin, str->xMax, str->yMin, str->yMax,
+ (str->yMax - str->yMin));
+ for (i = 0; i < str->len; ++i) {
+ fputc(str->text[i] & 0xff, stdout);
+ }
+ if (str->spaceAfter) {
+ fputc(' ', stdout);
+ }
+ printf("'\n");
+ }
+ }
+ printf("\n------------------------------------------------------------\n\n");
+#endif
+
+ // build the lines
+ lines = NULL;
+ line0 = NULL;
+ while (yxBlocks) {
+ blk0 = yxBlocks;
+ yxBlocks = yxBlocks->next;
+ blk0->next = NULL;
+ line = new TextLine();
+ line->blocks = blk0;
+ line->yMin = blk0->yMin;
+ line->yMax = blk0->yMax;
+ while (yxBlocks) {
+
+ // remove duplicated text (fake boldface, shadowed text)
+ h = blk0->yMax - blk0->yMin;
+ if (yxBlocks->len == blk0->len &&
+ !memcmp(yxBlocks->text, blk0->text,
+ yxBlocks->len * sizeof(Unicode)) &&
+ fabs(yxBlocks->yMin - blk0->yMin) / h < 0.2 &&
+ fabs(yxBlocks->yMax - blk0->yMax) / h < 0.2 &&
+ fabs(yxBlocks->xMin - blk0->xMin) / h < 0.2 &&
+ fabs(yxBlocks->xMax - blk0->xMax) / h < 0.2) {
+ blk1 = yxBlocks;
+ yxBlocks = yxBlocks->next;
+ delete blk1;
+ continue;
+ }
+
+ if (rawOrder && yxBlocks->yMax < blk0->yMin) {
+ break;
+ }
+ if (yxBlocks->yMin > 0.2*blk0->yMin + 0.8*blk0->yMax ||
+ yxBlocks->xMin < blk0->xMax) {
+ break;
+ }
+ blk1 = yxBlocks;
+ yxBlocks = yxBlocks->next;
+ blk0->next = blk1;
+ blk1->next = NULL;
+ if (blk1->yMin < line->yMin) {
+ line->yMin = blk1->yMin;
+ }
+ if (blk1->yMax > line->yMax) {
+ line->yMax = blk1->yMax;
+ }
+ blk0 = blk1;
+ }
+ if (line0) {
+ line0->next = line;
} else {
- str1 = str2;
+ lines = line;
+ }
+ line->next = NULL;
+ line0 = line;
+ }
+
+
+ // sort the blocks into xy order
+ xyBlocks = NULL;
+ for (line = lines; line; line = line->next) {
+ for (blk = line->blocks; blk; blk = blk->next) {
+ for (blk1 = NULL, blk2 = xyBlocks;
+ blk2 && !xyBefore(blk, blk2);
+ blk1 = blk2, blk2 = blk2->xyNext) ;
+ blk->xyNext = blk2;
+ if (blk1) {
+ blk1->xyNext = blk;
+ } else {
+ xyBlocks = blk;
+ }
+ }
+ }
+
+#if 0 //~ for debugging
+ for (blk = xyBlocks; blk; blk = blk->xyNext) {
+ printf("[block: x=%.2f..%.2f y=%.2f..%.2f len=%d]\n",
+ blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->len);
+ TextString *str;
+ for (str = blk->strings; str; str = str->next) {
+ printf(" x=%.2f..%.2f y=%.2f..%.2f size=%.2f '",
+ str->xMin, str->xMax, str->yMin, str->yMax,
+ (str->yMax - str->yMin));
+ for (i = 0; i < str->len; ++i) {
+ fputc(str->text[i] & 0xff, stdout);
+ }
+ printf("'\n");
+ }
+ }
+ printf("\n------------------------------------------------------------\n\n");
+#endif
+
+ // do column assignment
+ for (blk1 = xyBlocks; blk1; blk1 = blk1->xyNext) {
+ col1 = 0;
+ for (blk2 = xyBlocks; blk2 != blk1; blk2 = blk2->xyNext) {
+ if (blk1->xMin >= blk2->xMax) {
+ d = (int)((blk1->xMin - blk2->xMax) /
+ (0.4 * (blk1->yMax - blk1->yMin)));
+ if (d > 4) {
+ d = 4;
+ }
+ col2 = blk2->col[0] + blk2->convertedLen + d;
+ if (col2 > col1) {
+ col1 = col2;
+ }
+ } else if (blk1->xMin > blk2->xMin) {
+ for (i = 0; i < blk2->len && blk1->xMin >= blk2->xRight[i]; ++i) ;
+ col2 = blk2->col[i];
+ if (col2 > col1) {
+ col1 = col2;
+ }
+ }
+ }
+ for (j = 0; j < blk1->len; ++j) {
+ blk1->col[j] += col1;
}
}
+
+#if 0 //~ for debugging
+ for (line = lines; line; line = line->next) {
+ printf("[line]\n");
+ for (blk = line->blocks; blk; blk = blk->next) {
+ printf("[block: col=%d, len=%d]\n", blk->col[0], blk->len);
+ TextString *str;
+ for (str = blk->strings; str; str = str->next) {
+ printf(" x=%.2f..%.2f y=%.2f..%.2f size=%.2f '",
+ str->xMin, str->xMax, str->yMin, str->yMax,
+ (str->yMax - str->yMin));
+ for (i = 0; i < str->len; ++i) {
+ fputc(str->text[i] & 0xff, stdout);
+ }
+ if (str->spaceAfter) {
+ printf(" [space]\n");
+ }
+ printf("'\n");
+ }
+ }
+ }
+ printf("\n------------------------------------------------------------\n\n");
+#endif
}
+
GBool TextPage::findText(Unicode *s, int len,
GBool top, GBool bottom,
double *xMin, double *yMin,
double *xMax, double *yMax) {
- TextString *str;
+ TextLine *line;
+ TextBlock *blk;
Unicode *p;
Unicode u1, u2;
int m, i, j;
- double x;
+ double x0, x1, x;
- // scan all strings on page
- for (str = yxStrings; str; str = str->yxNext) {
-
- // check: above top limit?
- if (!top && (str->yMax < *yMin ||
- (str->yMin < *yMin && str->xMax <= *xMin))) {
- continue;
- }
-
- // check: below bottom limit?
- if (!bottom && (str->yMin > *yMax ||
- (str->yMax > *yMax && str->xMin >= *xMax))) {
- return gFalse;
- }
-
- // search each position in this string
- m = str->len;
- for (i = 0, p = str->text; i <= m - len; ++i, ++p) {
+ // scan all blocks on page
+ for (line = lines; line; line = line->next) {
+ for (blk = line->blocks; blk; blk = blk->next) {
// check: above top limit?
- if (!top && str->yMin < *yMin) {
- x = (((i == 0) ? str->xMin : str->xRight[i-1]) + str->xRight[i]) / 2;
- if (x < *xMin) {
- continue;
- }
+ if (!top && (blk->yMax < *yMin ||
+ (blk->yMin < *yMin && blk->xMax <= *xMin))) {
+ continue;
}
// check: below bottom limit?
- if (!bottom && str->yMax > *yMax) {
- x = (((i == 0) ? str->xMin : str->xRight[i-1]) + str->xRight[i]) / 2;
- if (x > *xMax) {
- return gFalse;
- }
+ if (!bottom && (blk->yMin > *yMax ||
+ (blk->yMax > *yMax && blk->xMin >= *xMax))) {
+ return gFalse;
}
- // compare the strings
- for (j = 0; j < len; ++j) {
-#if 1 //~ this lowercases Latin A-Z only -- this will eventually be
- //~ extended to handle other character sets
- if (p[j] >= 0x41 && p[j] <= 0x5a) {
- u1 = p[j] + 0x20;
- } else {
- u1 = p[j];
+ // search each position in this block
+ m = blk->len;
+ for (i = 0, p = blk->text; i <= m - len; ++i, ++p) {
+
+ x0 = (i == 0) ? blk->xMin : blk->xRight[i-1];
+ x1 = blk->xRight[i];
+ x = 0.5 * (x0 + x1);
+
+ // check: above top limit?
+ if (!top && blk->yMin < *yMin) {
+ if (x < *xMin) {
+ continue;
+ }
}
- if (s[j] >= 0x41 && s[j] <= 0x5a) {
- u2 = s[j] + 0x20;
- } else {
- u2 = s[j];
+
+ // check: below bottom limit?
+ if (!bottom && blk->yMax > *yMax) {
+ if (x > *xMax) {
+ return gFalse;
+ }
}
+
+ // compare the strings
+ for (j = 0; j < len; ++j) {
+#if 1 //~ this lowercases Latin A-Z only -- this will eventually be
+ //~ extended to handle other character sets
+ if (p[j] >= 0x41 && p[j] <= 0x5a) {
+ u1 = p[j] + 0x20;
+ } else {
+ u1 = p[j];
+ }
+ if (s[j] >= 0x41 && s[j] <= 0x5a) {
+ u2 = s[j] + 0x20;
+ } else {
+ u2 = s[j];
+ }
#endif
- if (u1 != u2) {
- break;
+ if (u1 != u2) {
+ break;
+ }
}
- }
- // found it
- if (j == len) {
- *xMin = (i == 0) ? str->xMin : str->xRight[i-1];
- *xMax = str->xRight[i + len - 1];
- *yMin = str->yMin;
- *yMax = str->yMax;
- return gTrue;
+ // found it
+ if (j == len) {
+ *xMin = x0;
+ *xMax = blk->xRight[i + len - 1];
+ *yMin = blk->yMin;
+ *yMax = blk->yMax;
+ return gTrue;
+ }
}
}
}
+
return gFalse;
}
double xMax, double yMax) {
GString *s;
UnicodeMap *uMap;
+ GBool isUnicode;
char space[8], eol[16], buf[8];
- int spaceLen, eolLen, n;
- TextString *str1;
- double x0, x1, x2, y;
- double xPrev, yPrev;
- int i1, i2, i;
+ int spaceLen, eolLen, len;
+ TextLine *line;
+ TextBlock *blk;
+ double x0, x1, y;
+ int firstCol, col, i;
GBool multiLine;
s = new GString();
+
+ // get the output encoding
if (!(uMap = globalParams->getTextEncoding())) {
return s;
}
+ isUnicode = uMap->isUnicode();
spaceLen = uMap->mapUnicode(0x20, space, sizeof(space));
eolLen = 0; // make gcc happy
switch (globalParams->getTextEOL()) {
eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
break;
}
- xPrev = yPrev = 0;
+
+ // find the leftmost column
multiLine = gFalse;
- for (str1 = yxStrings; str1; str1 = str1->yxNext) {
- y = 0.5 * (str1->yMin + str1->yMax);
- if (y > yMax) {
+ firstCol = -1;
+ for (line = lines; line; line = line->next) {
+ if (line->yMin > yMax) {
break;
}
- if (y > yMin && str1->xMin < xMax && str1->xMax > xMin) {
- x0 = x1 = x2 = str1->xMin;
- for (i1 = 0; i1 < str1->len; ++i1) {
- x0 = (i1==0) ? str1->xMin : str1->xRight[i1-1];
- x1 = str1->xRight[i1];
- if (0.5 * (x0 + x1) >= xMin) {
- break;
- }
+ if (line->yMax < yMin) {
+ continue;
+ }
+
+ for (blk = line->blocks; blk && blk->xMax < xMin; blk = blk->next) ;
+ if (!blk || blk->xMin > xMax) {
+ continue;
+ }
+
+ y = 0.5 * (blk->yMin + blk->yMax);
+ if (y < yMin || y > yMax) {
+ continue;
+ }
+
+ if (firstCol >= 0) {
+ multiLine = gTrue;
+ }
+
+ i = 0;
+ while (1) {
+ x0 = (i==0) ? blk->xMin : blk->xRight[i-1];
+ x1 = blk->xRight[i];
+ if (0.5 * (x0 + x1) > xMin) {
+ break;
}
- for (i2 = str1->len - 1; i2 > i1; --i2) {
- x1 = (i2==0) ? str1->xMin : str1->xRight[i2-1];
- x2 = str1->xRight[i2];
- if (0.5 * (x1 + x2) <= xMax) {
- break;
- }
+ ++i;
+ }
+ col = blk->col[i];
+
+ if (firstCol < 0 || col < firstCol) {
+ firstCol = col;
+ }
+ }
+
+ // extract the text
+ for (line = lines; line; line = line->next) {
+ if (line->yMin > yMax) {
+ break;
+ }
+ if (line->yMax < yMin) {
+ continue;
+ }
+
+ for (blk = line->blocks; blk && blk->xMax < xMin; blk = blk->next) ;
+ if (!blk || blk->xMin > xMax) {
+ continue;
+ }
+
+ y = 0.5 * (blk->yMin + blk->yMax);
+ if (y < yMin || y > yMax) {
+ continue;
+ }
+
+ i = 0;
+ while (1) {
+ x0 = (i==0) ? blk->xMin : blk->xRight[i-1];
+ x1 = blk->xRight[i];
+ if (0.5 * (x0 + x1) > xMin) {
+ break;
}
- if (s->getLength() > 0) {
- if (x0 < xPrev || str1->yMin > yPrev) {
- s->append(eol, eolLen);
- multiLine = gTrue;
- } else {
- for (i = 0; i < 4; ++i) {
- s->append(space, spaceLen);
- }
+ ++i;
+ }
+
+ col = firstCol;
+
+ do {
+
+ // line this block up with the correct column
+ for (; col < blk->col[i]; ++col) {
+ s->append(space, spaceLen);
+ }
+
+ // print the block
+ for (; i < blk->len; ++i) {
+
+ x0 = (i==0) ? blk->xMin : blk->xRight[i-1];
+ x1 = blk->xRight[i];
+ if (0.5 * (x0 + x1) > xMax) {
+ break;
}
+
+ len = uMap->mapUnicode(blk->text[i], buf, sizeof(buf));
+ s->append(buf, len);
+ col += isUnicode ? 1 : len;
}
- for (i = i1; i <= i2; ++i) {
- n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf));
- s->append(buf, n);
+ if (i < blk->len) {
+ break;
}
- xPrev = x2;
- yPrev = str1->yMax;
+
+ // next block
+ blk = blk->next;
+ i = 0;
+
+ } while (blk && blk->xMin < xMax);
+
+ if (multiLine) {
+ s->append(eol, eolLen);
}
}
- if (multiLine) {
- s->append(eol, eolLen);
- }
+
uMap->decRefCnt();
+
return s;
}
void TextPage::dump(void *outputStream, TextOutputFunc outputFunc) {
UnicodeMap *uMap;
char space[8], eol[16], eop[8], buf[8];
- int spaceLen, eolLen, eopLen, n;
- TextString *str1, *str2, *str3;
- double yMin, yMax;
- int col1, col2, d, i;
+ int spaceLen, eolLen, eopLen, len;
+ TextLine *line;
+ TextBlock *blk;
+ int col, d, i;
// get the output encoding
if (!(uMap = globalParams->getTextEncoding())) {
}
eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop));
- // build x-major list
- xyStrings = NULL;
- for (str1 = yxStrings; str1; str1 = str1->yxNext) {
- for (str2 = NULL, str3 = xyStrings;
- str3;
- str2 = str3, str3 = str3->xyNext) {
- if (str1->xMin < str3->xMin ||
- (str1->xMin == str3->xMin && str1->yMin < str3->yMin)) {
- break;
- }
- }
- if (str2) {
- str2->xyNext = str1;
- } else {
- xyStrings = str1;
- }
- str1->xyNext = str3;
- }
-
- // do column assignment
- for (str1 = xyStrings; str1; str1 = str1->xyNext) {
- col1 = 0;
- for (str2 = xyStrings; str2 != str1; str2 = str2->xyNext) {
- if (str1->xMin >= str2->xMax) {
- col2 = str2->col + str2->len + 4;
- if (col2 > col1) {
- col1 = col2;
- }
- } else if (str1->xMin > str2->xMin) {
- col2 = str2->col +
- (int)(((str1->xMin - str2->xMin) / (str2->xMax - str2->xMin)) *
- str2->len);
- if (col2 > col1) {
- col1 = col2;
+ // output
+ for (line = lines; line; line = line->next) {
+ col = 0;
+ for (blk = line->blocks; blk; blk = blk->next) {
+
+ // line this block up with the correct column
+ if (rawOrder && col == 0) {
+ col = blk->col[0];
+ } else {
+ for (; col < blk->col[0]; ++col) {
+ (*outputFunc)(outputStream, space, spaceLen);
}
}
- }
- str1->col = col1;
- }
-
-#if 0 //~ for debugging
- fprintf((FILE *)outputStream, "~~~~~~~~~~\n");
- for (str1 = yxStrings; str1; str1 = str1->yxNext) {
- fprintf((FILE *)outputStream, "(%4d,%4d) - (%4d,%4d) [%3d] '",
- (int)str1->xMin, (int)str1->yMin,
- (int)str1->xMax, (int)str1->yMax, str1->col);
- for (i = 0; i < str1->len; ++i) {
- fputc(str1->text[i] & 0xff, stdout);
- }
- printf("'\n");
- }
- fprintf((FILE *)outputStream, "~~~~~~~~~~\n");
-#endif
-
- // output
- col1 = 0;
- yMax = yxStrings ? yxStrings->yMax : 0;
- for (str1 = yxStrings; str1; str1 = str1->yxNext) {
- // line this string up with the correct column
- if (rawOrder && col1 == 0) {
- col1 = str1->col;
- } else {
- for (; col1 < str1->col; ++col1) {
- (*outputFunc)(outputStream, space, spaceLen);
+ // print the block
+ for (i = 0; i < blk->len; ++i) {
+ len = uMap->mapUnicode(blk->text[i], buf, sizeof(buf));
+ (*outputFunc)(outputStream, buf, len);
}
+ col += blk->convertedLen;
}
- // print the string
- for (i = 0; i < str1->len; ++i) {
- if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) {
- (*outputFunc)(outputStream, buf, n);
+ // print a return
+ (*outputFunc)(outputStream, eol, eolLen);
+
+ // print extra vertical space if necessary
+ if (line->next) {
+ d = (int)((line->next->yMin - line->yMax) /
+ (line->blocks->strings->yMax - lines->blocks->strings->yMin)
+ + 0.5);
+ // various things (weird font matrices) can result in bogus
+ // values here, so do a sanity check
+ if (rawOrder && d > 2) {
+ d = 2;
+ } else if (!rawOrder && d > 5) {
+ d = 5;
}
- }
-
- // increment column
- col1 += str1->len;
-
- // update yMax for this line
- if (str1->yMax > yMax) {
- yMax = str1->yMax;
- }
-
- // if we've hit the end of the line...
- if (!(str1->yxNext &&
- !(rawOrder && str1->yxNext->yMax < str1->yMin) &&
- str1->yxNext->yMin < 0.2*str1->yMin + 0.8*str1->yMax &&
- str1->yxNext->xMin >= str1->xMax)) {
-
- // print a return
- (*outputFunc)(outputStream, eol, eolLen);
-
- // print extra vertical space if necessary
- if (str1->yxNext) {
-
- // find yMin for next line
- yMin = str1->yxNext->yMin;
- for (str2 = str1->yxNext; str2; str2 = str2->yxNext) {
- if (str2->yMin < yMin) {
- yMin = str2->yMin;
- }
- if (!(str2->yxNext && str2->yxNext->yMin < str2->yMax &&
- str2->yxNext->xMin >= str2->xMax))
- break;
- }
-
- // print the space
- d = (int)((yMin - yMax) / (str1->yMax - str1->yMin) + 0.5);
- // various things (weird font matrices) can result in bogus
- // values here, so do a sanity check
- if (rawOrder && d > 2) {
- d = 2;
- } else if (!rawOrder && d > 5) {
- d = 5;
- }
- for (; d > 0; --d) {
- (*outputFunc)(outputStream, eol, eolLen);
- }
+ for (; d > 0; --d) {
+ (*outputFunc)(outputStream, eol, eolLen);
}
-
- // set up for next line
- col1 = 0;
- yMax = str1->yxNext ? str1->yxNext->yMax : 0;
}
}
uMap->decRefCnt();
}
+// Returns true if <str1> should be inserted before <str2> in xy
+// order.
+GBool TextPage::xyBefore(TextString *str1, TextString *str2) {
+ return str1->xMin < str2->xMin ||
+ (str1->xMin == str2->xMin && str1->yMin < str2->yMin);
+}
+
+// Returns true if <blk1> should be inserted before <blk2> in xy
+// order.
+GBool TextPage::xyBefore(TextBlock *blk1, TextBlock *blk2) {
+ return blk1->xMin < blk2->xMin ||
+ (blk1->xMin == blk2->xMin && blk1->yMin < blk2->yMin);
+}
+
+// Returns true if <blk1> should be inserted before <blk2> in yx
+// order, allowing a little slack for vertically overlapping text.
+GBool TextPage::yxBefore(TextBlock *blk1, TextBlock *blk2) {
+ double h1, h2, overlap;
+
+ h1 = blk1->yMax - blk1->yMin;
+ h2 = blk2->yMax - blk2->yMin;
+ overlap = ((blk1->yMax < blk2->yMax ? blk1->yMax : blk2->yMax) -
+ (blk1->yMin > blk2->yMin ? blk1->yMin : blk2->yMin)) /
+ (h1 < h2 ? h1 : h2);
+ if (overlap > 0.6) {
+ return blk1->xMin < blk2->xMin;
+ }
+ return blk1->yMin < blk2->yMin;
+}
+
+double TextPage::coalesceFit(TextString *str1, TextString *str2) {
+ double h1, h2, w1, w2, r, overlap, spacing;
+
+ h1 = str1->yMax - str1->yMin;
+ h2 = str2->yMax - str2->yMin;
+ w1 = str1->xMax - str1->xMin;
+ w2 = str2->xMax - str2->xMin;
+ r = h1 / h2;
+ if (r < (1.0 / 3.0) || r > 3) {
+ return 10;
+ }
+ overlap = ((str1->yMax < str2->yMax ? str1->yMax : str2->yMax) -
+ (str1->yMin > str2->yMin ? str1->yMin : str2->yMin)) /
+ (h1 < h2 ? h1 : h2);
+ if (overlap < 0.5) {
+ return 10;
+ }
+ spacing = (str2->xMin - str1->xMax) / (h1 > h2 ? h1 : h2);
+ if (spacing < -0.5) {
+ return 10;
+ }
+ // separate text that overlaps - duplicated text (so that fake
+ // boldface and shadowed text can be cleanly removed)
+ if ((str2->xMin - str1->xMax) / (w1 < w2 ? w1 : w2) < -0.7) {
+ return 10;
+ }
+ return spacing;
+}
+
void TextPage::clear() {
- TextString *p1, *p2;
+ TextLine *p1, *p2;
+ TextString *s1, *s2;
if (curStr) {
delete curStr;
curStr = NULL;
}
- for (p1 = yxStrings; p1; p1 = p2) {
- p2 = p1->yxNext;
- delete p1;
+ if (lines) {
+ for (p1 = lines; p1; p1 = p2) {
+ p2 = p1->next;
+ delete p1;
+ }
+ } else if (xyStrings) {
+ for (s1 = xyStrings; s1; s1 = s2) {
+ s2 = s1->next;
+ delete s1;
+ }
}
- yxStrings = NULL;
xyStrings = NULL;
- yxCur1 = yxCur2 = NULL;
+ xyCur1 = xyCur2 = NULL;
+ lines = NULL;
+ nest = 0;
+ nTinyChars = 0;
}
//------------------------------------------------------------------------
}
void TextOutputDev::beginString(GfxState *state, GString *s) {
- text->beginString(state);
+ text->beginString(state, state->getCurX(), state->getCurY());
}
void TextOutputDev::endString(GfxState *state) {
double *xMax, double *yMax) {
return text->findText(s, len, top, bottom, xMin, yMin, xMax, yMax);
}
+
+GString *TextOutputDev::getText(double xMin, double yMin,
+ double xMax, double yMax) {
+ return text->getText(xMin, yMin, xMax, yMax);
+}
+
#ifndef TEXTOUTPUTDEV_H
#define TEXTOUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
class GfxState;
class GString;
+class TextBlock;
+class TextLine;
+
+#undef TEXTOUT_DO_SYMBOLS
//------------------------------------------------------------------------
typedef void (*TextOutputFunc)(void *stream, char *text, int len);
+
//------------------------------------------------------------------------
// TextString
//------------------------------------------------------------------------
public:
// Constructor.
- TextString(GfxState *state, double fontSize);
+ TextString(GfxState *state, double x0, double y0,
+ double fontSize);
+
// Destructor.
~TextString();
double xMin, xMax; // bounding box x coordinates
double yMin, yMax; // bounding box y coordinates
- int col; // starting column
+ union {
+ GBool marked; // temporary flag used by coalesce()
+ GBool spaceAfter; // insert a space after this string?
+ };
Unicode *text; // the text
double *xRight; // right-hand x coord of each char
int len; // length of text and xRight
int size; // size of text and xRight arrays
- TextString *yxNext; // next string in y-major order
- TextString *xyNext; // next string in x-major order
+ TextString *next;
friend class TextPage;
+ friend class TextBlock;
};
//------------------------------------------------------------------------
// Update the current font.
void updateFont(GfxState *state);
+
// Begin a new string.
- void beginString(GfxState *state);
+ void beginString(GfxState *state, double x0, double y0);
// Add a character to the current string.
void addChar(GfxState *state, double x, double y,
// End the current string, sorting it into the list of strings.
void endString();
+ // Add a string, sorting it into the list of strings.
+ void addString(TextString *str);
+
+
// Coalesce strings that look like parts of the same line.
void coalesce();
private:
+ GBool xyBefore(TextString *str1, TextString *str2);
+ GBool xyBefore(TextBlock *blk1, TextBlock *blk2);
+ GBool yxBefore(TextBlock *blk1, TextBlock *blk2);
+ double coalesceFit(TextString *str1, TextString *str2);
+
GBool rawOrder; // keep strings in content stream order
TextString *curStr; // currently active string
double fontSize; // current font size
- TextString *yxStrings; // strings in y-major order
- TextString *xyStrings; // strings in x-major order
- TextString *yxCur1, *yxCur2; // cursors for yxStrings list
+ TextString *xyStrings; // strings in x-major order (before
+ // they're sorted into lines)
+ TextString *xyCur1, *xyCur2; // cursors for xyStrings list
+ TextLine *lines; // list of lines
int nest; // current nesting level (for Type 3 fonts)
+
+ int nTinyChars; // number of "tiny" chars seen so far
+
};
//------------------------------------------------------------------------
double originX, double originY,
CharCode c, Unicode *u, int uLen);
+ //----- path painting
+
//----- special access
// Find a string. If <top> is true, starts looking at top of page;
double *xMin, double *yMin,
double *xMax, double *yMax);
+ // Get the text which is inside the specified rectangle.
+ GString *getText(double xMin, double yMin,
+ double xMax, double yMax);
+
private:
TextOutputFunc outputFunc; // output function
TextPage *text; // text for the current page
GBool rawOrder; // keep text in content stream order
GBool ok; // set up ok?
+
};
#endif
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
{"Symbol", 0.576}
};
+//------------------------------------------------------------------------
+
+static void outputToFile(void *stream, char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
//------------------------------------------------------------------------
// XOutputFont
//------------------------------------------------------------------------
#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
delFonts();
}
-void XOutputFontCache::startDoc(int screenNum, Colormap colormap,
- GBool trueColor,
+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) {
#if HAVE_T1LIB_H
if (t1libControl != fontRastNone) {
- t1Engine = new T1FontEngine(display, DefaultVisual(display, screenNum),
- depth, colormap,
+ t1Engine = new T1FontEngine(display, visual, depth, colormap,
t1libControl == fontRastAALow ||
t1libControl == fontRastAAHigh,
t1libControl == fontRastAAHigh);
#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
if (freetypeControl != fontRastNone) {
- ftEngine = new FTFontEngine(display, DefaultVisual(display, screenNum),
- depth, colormap,
+ ftEngine = new FTFontEngine(display, visual, depth, colormap,
freetypeControl == fontRastAALow ||
freetypeControl == fontRastAAHigh);
if (ftEngine->isOk()) {
#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
if (freetypeControl != fontRastNone) {
- ttEngine = new TTFontEngine(display, DefaultVisual(display, screenNum),
- depth, colormap,
+ ttEngine = new TTFontEngine(display, visual, depth, colormap,
freetypeControl == fontRastAALow ||
freetypeControl == fontRastAAHigh);
if (ttEngine->isOk()) {
case displayFontT1:
#if HAVE_T1LIB_H
if (t1libControl != fontRastNone) {
- font = tryGetT1FontFromFile(xref, dfp->t1.fileName, gfxFont,
+ font = tryGetT1FontFromFile(xref, dfp->t1.fileName, gFalse, gfxFont,
m11Orig, m12Orig, m21Orig, m22Orig,
m11, m12, m21, m22, subst);
}
#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
if (!font) {
if (freetypeControl != fontRastNone) {
- font = tryGetFTFontFromFile(xref, dfp->t1.fileName, gfxFont,
+ font = tryGetFTFontFromFile(xref, dfp->t1.fileName, gFalse, gfxFont,
m11Orig, m12Orig, m21Orig, m22Orig,
m11, m12, m21, m22, subst);
}
case displayFontTT:
#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
if (freetypeControl != fontRastNone) {
- font = tryGetFTFontFromFile(xref, dfp->tt.fileName, gfxFont,
+ font = tryGetFTFontFromFile(xref, dfp->tt.fileName, gFalse, gfxFont,
m11Orig, m12Orig, m21Orig, m22Orig,
m11, m12, m21, m22, subst);
}
#endif
#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
if (freetypeControl != fontRastNone) {
- font = tryGetTTFontFromFile(xref, dfp->tt.fileName, gfxFont,
+ font = tryGetTTFontFromFile(xref, dfp->tt.fileName, gFalse, gfxFont,
m11Orig, m12Orig, m21Orig, m22Orig,
m11, m12, m21, m22, subst);
}
return NULL;
}
ff = new Type1CFontFile(fontBuf, fontLen);
- ff->convertToType1(f);
+ ff->convertToType1(outputToFile, f);
delete ff;
gfree(fontBuf);
} else { // fontType1
fclose(f);
// create the Font
- font = tryGetT1FontFromFile(xref, fileName, gfxFont,
+ font = tryGetT1FontFromFile(xref, fileName, gTrue, gfxFont,
m11, m12, m21, m22,
m11, m12, m21, m22, gFalse);
- // remove the temporary file
+ // 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, gfxFont,
+ font = tryGetT1FontFromFile(xref, fileName, gFalse, gfxFont,
m11, m12, m21, m22,
m11, m12, m21, m22, gFalse);
XOutputFont *XOutputFontCache::tryGetT1FontFromFile(XRef *xref,
GString *fileName,
+ GBool deleteFile,
GfxFont *gfxFont,
double m11Orig,
double m12Orig,
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));
+ subst, fontFile,
+ deleteFile ? fileName->copy()
+ : (GString *)NULL));
// create the Font
font = new XOutputT1Font(gfxFont->getID(), fontFile,
fclose(f);
// create the Font
- font = tryGetFTFontFromFile(xref, fileName, gfxFont,
+ font = tryGetFTFontFromFile(xref, fileName, gTrue, gfxFont,
m11, m12, m21, m22,
m11, m12, m21, m22, gFalse);
- // remove the temporary file
+ // 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, gfxFont,
+ font = tryGetFTFontFromFile(xref, fileName, gFalse, gfxFont,
m11, m12, m21, m22,
m11, m12, m21, m22, gFalse);
XOutputFont *XOutputFontCache::tryGetFTFontFromFile(XRef *xref,
GString *fileName,
+ GBool deleteFile,
GfxFont *gfxFont,
double m11Orig,
double m12Orig,
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));
+ subst, fontFile,
+ deleteFile ? fileName->copy()
+ : (GString *)NULL));
// create the Font
font = new XOutputFTFont(gfxFont->getID(), fontFile,
fclose(f);
// create the Font
- font = tryGetTTFontFromFile(xref, fileName, gfxFont,
+ font = tryGetTTFontFromFile(xref, fileName, gTrue, gfxFont,
m11, m12, m21, m22,
m11, m12, m21, m22, gFalse);
- // remove the temporary file
+ // 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, gfxFont,
+ font = tryGetTTFontFromFile(xref, fileName, gFalse, gfxFont,
m11, m12, m21, m22,
m11, m12, m21, m22, gFalse);
XOutputFont *XOutputFontCache::tryGetTTFontFromFile(XRef *xref,
GString *fileName,
+ GBool deleteFile,
GfxFont *gfxFont,
double m11Orig,
double m12Orig,
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));
+ subst, fontFile,
+ deleteFile ? fileName->copy()
+ : (GString *)NULL));
// create the Font
font = new XOutputTTFont(gfxFont->getID(), fontFile,
GC origStrokeGC;
GC origFillGC;
Region origClipRegion;
+ double origCTM4, origCTM5;
double wx, wy; // untransformed glyph metrics
T3GlyphStack *next;
};
// XOutputDev
//------------------------------------------------------------------------
-XOutputDev::XOutputDev(Display *displayA, Pixmap pixmapA, Guint depthA,
- Colormap colormapA, GBool reverseVideoA,
- unsigned long paperColor, GBool installCmap,
- int rgbCubeSize) {
+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;
- XGCValues gcValues;
XColor xcolor;
XColor *xcolors;
- int r, g, b, n, m, i;
+ int r, g, b, n, m;
GBool ok;
+ // no document yet
xref = NULL;
- // get display/pixmap info
+ // display / screen / visual / colormap
display = displayA;
- screenNum = DefaultScreen(display);
- pixmap = pixmapA;
- depth = depthA;
+ screenNum = screenNumA;
+ visual = visualA;
colormap = colormapA;
+ // no pixmap yet
+ pixmapW = pixmapH = 0;
+
// check for TrueColor visual
- trueColor = gFalse;
- if (depth == 0) {
- depth = DefaultDepth(display, screenNum);
- visualList = XGetVisualInfo(display, 0, &visualTempl, &nVisuals);
- for (i = 0; i < nVisuals; ++i) {
- if (visualList[i].visual == DefaultVisual(display, screenNum)) {
- if (visualList[i].c_class == TrueColor) {
- trueColor = gTrue;
- for (mask = visualList[i].red_mask, rShift = 0;
- mask && !(mask & 1);
- mask >>= 1, ++rShift) ;
- rMul = (int)mask;
- for (mask = visualList[i].green_mask, gShift = 0;
- mask && !(mask & 1);
- mask >>= 1, ++gShift) ;
- gMul = (int)mask;
- for (mask = visualList[i].blue_mask, bShift = 0;
- mask && !(mask & 1);
- mask >>= 1, ++bShift) ;
- bMul = (int)mask;
- }
- break;
- }
+ 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);
}
}
}
- // reverse video mode
+ // misc parameters
reverseVideo = reverseVideoA;
-
- // 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);
-
- // no clip region yet
- clipRegion = NULL;
+ paperColor = paperColorA;
// set up the font cache and fonts
gfxFont = NULL;
for (i = 0; i < nT3Fonts; ++i) {
delete t3FontCache[i];
}
- XFreeGC(display, strokeGC);
- XFreeGC(display, fillGC);
- XFreeGC(display, paperGC);
- if (clipRegion) {
- XDestroyRegion(clipRegion);
- }
delete text;
}
int i;
xref = xrefA;
- fontCache->startDoc(screenNum, colormap, trueColor, rMul, gMul, bMul,
+ fontCache->startDoc(screenNum, visual, colormap, trueColor, rMul, gMul, bMul,
rShift, gShift, bShift, colors, numColors);
for (i = 0; i < nT3Fonts; ++i) {
delete t3FontCache[i];
}
void XOutputDev::startPage(int pageNum, GfxState *state) {
- XOutputState *s;
XGCValues gcValues;
XRectangle rect;
- // clear state stack
- while (save) {
- s = save;
- save = save->next;
- XFreeGC(display, s->strokeGC);
- XFreeGC(display, s->fillGC);
- XDestroyRegion(s->clipRegion);
- delete s;
- }
- save = NULL;
-
// default line flatness
flatness = 0;
- // reset GCs
+ // allocate GCs
gcValues.foreground = BlackPixel(display, screenNum);
gcValues.background = WhitePixel(display, screenNum);
gcValues.line_width = 0;
gcValues.line_style = LineSolid;
- XChangeGC(display, strokeGC,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
- XChangeGC(display, fillGC,
- GCForeground | GCBackground | GCLineWidth | GCLineStyle,
- &gcValues);
-
- // clear clipping region
- if (clipRegion)
- XDestroyRegion(clipRegion);
+ 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;
}
void XOutputDev::endPage() {
+ XOutputState *s;
+
text->coalesce();
+
+ // 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) {
void XOutputDev::updateFont(GfxState *state) {
double m11, m12, m21, m22;
+ text->updateFont(state);
+
if (!(gfxFont = state->getFont())) {
font = NULL;
return;
font->updateGC(fillGC);
font->updateGC(strokeGC);
}
-
- text->updateFont(state);
}
void XOutputDev::stroke(GfxState *state) {
}
void XOutputDev::beginString(GfxState *state, GString *s) {
- text->beginString(state);
+ text->beginString(state, state->getCurX(), state->getCurY());
}
void XOutputDev::endString(GfxState *state) {
(int)floor(yMin - yt),
(int)ceil(xMax) - (int)floor(xMin) + 3,
(int)ceil(yMax) - (int)floor(yMin) + 3,
- display,
- DefaultVisual(display, screenNum),
- depth, pixmap);
+ display, visual, depth, pixmap);
}
}
t3Font = t3FontCache[0];
Gulong pixel;
double alpha;
T3GlyphStack *t3gs;
+ double *ctm;
if (t3GlyphStack->cacheable) {
image = t3GlyphStack->cache->image;
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->u, t3GlyphStack->uLen);
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);
}
pixBuf = (Guchar *)gmalloc((yp + 1) * width * sizeof(Guchar));
// allocate XImage and read from page pixmap
- image = XCreateImage(display, DefaultVisual(display, screenNum),
- depth, ZPixmap, 0, NULL, bw, bh, 8, 0);
+ 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);
if (n > 0) {
p = pixBuf;
for (i = 0; i < n; ++i) {
- for (j = 0; j < width; ++j) {
- imgStr->getPixel(p);
- if (invert) {
- *p ^= 1;
+ memcpy(p, imgStr->getLine(), width);
+ if (invert) {
+ for (j = 0; j < width; ++j) {
+ p[j] ^= 1;
}
- ++p;
}
+ p += width;
}
}
lastYStep = yStep;
double r0, g0, b0, alpha, mul;
Gulong pix;
GfxRGB *p;
- Guchar *q;
+ Guchar *q, *p2;
GBool oneBitMode;
GfxRGB oneBitRGB[2];
int x, y, x1, y1, x2, y2;
}
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;
}
// allocate XImage
- image = XCreateImage(display, DefaultVisual(display, screenNum),
- depth, ZPixmap, 0, NULL, bw, bh, 8, 0);
+ 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
p = pixBuf;
q = alphaBuf;
for (i = 0; i < n; ++i) {
- for (j = 0; j < width; ++j) {
- imgStr->getPixel(pixBuf2);
- if (oneBitMode) {
- *p++ = oneBitRGB[pixBuf2[0]];
- } else {
- colorMap->getRGB(pixBuf2, p);
- ++p;
- }
- if (q) {
- *q = 1;
- for (k = 0; k < nComps; ++k) {
- if (pixBuf2[k] < maskColors[2*k] ||
- pixBuf2[k] > maskColors[2*k]) {
- *q = 0;
- break;
- }
- }
- ++q;
- }
- }
+ p2 = imgStr->getLine();
+ for (j = 0; j < width; ++j) {
+ if (oneBitMode) {
+ *p = oneBitRGB[*p2];
+ } else {
+ 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]) {
+ *q = 0;
+ break;
+ }
+ }
+ ++q;
+ }
+ p2 += nComps;
+ }
}
}
lastYStep = yStep;
#ifndef XOUTPUTDEV_H
#define XOUTPUTDEV_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#if HAVE_T1LIB_H
class XOutputT1FontFile {
public:
- XOutputT1FontFile(int numA, int genA, GBool substA, T1FontFile *fontFileA)
- { num = numA; gen = genA; subst = substA; fontFile = fontFileA; }
+ 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)
- { num = numA; gen = genA; subst = substA; fontFile = fontFileA; }
+ 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)
- { num = numA; gen = genA; subst = substA; fontFile = fontFileA; }
+ 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
~XOutputFontCache();
// Initialize (or re-initialize) the font cache for a new document.
- void startDoc(int screenNum, Colormap colormap,
- GBool trueColor,
+ 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);
XOutputFont *tryGetT1Font(XRef *xref, GfxFont *gfxFont,
double m11, double m12, double m21, double m22);
XOutputFont *tryGetT1FontFromFile(XRef *xref, GString *fileName,
- GfxFont *gfxFont,
+ GBool deleteFile, GfxFont *gfxFont,
double m11Orig, double m12Orig,
double m21Orig, double m22Orig,
double m11, double m12,
XOutputFont *tryGetFTFont(XRef *xref, GfxFont *gfxFont,
double m11, double m12, double m21, double m22);
XOutputFont *tryGetFTFontFromFile(XRef *xref, GString *fileName,
- GfxFont *gfxFont,
+ GBool deleteFile, GfxFont *gfxFont,
double m11Orig, double m12Orig,
double m21Orig, double m22Orig,
double m11, double m12,
XOutputFont *tryGetTTFont(XRef *xref, GfxFont *gfxFont,
double m11, double m12, double m21, double m22);
XOutputFont *tryGetTTFontFromFile(XRef *xref, GString *fileName,
- GfxFont *gfxFont,
+ GBool deleteFile, GfxFont *gfxFont,
double m11Orig, double m12Orig,
double m21Orig, double m22Orig,
double m11, double m12,
public:
// Constructor.
- XOutputDev(Display *displayA, Pixmap pixmapA, Guint depthA,
- Colormap colormapA, GBool reverseVideoA,
- unsigned long paperColor, GBool installCmap,
- int rgbCubeSize);
+ XOutputDev(Display *displayA, int screenNumA,
+ Visual *visualA, Colormap colormapA,
+ GBool reverseVideoA, unsigned long paperColorA,
+ GBool installCmap, int rgbCubeSize,
+ int forceDepth = 0);
// Destructor.
virtual ~XOutputDev();
GBool isReverseVideo() { return reverseVideo; }
-protected:
-
// Update pixmap ID after a page change.
- void setPixmap(Pixmap pixmap1, int pixmapW1, int pixmapH1)
- { pixmap = pixmap1; pixmapW = pixmapW1; pixmapH = pixmapH1; }
+ 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:
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
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
void drawType3Glyph(T3FontCache *t3Font,
T3FontCacheTag *tag, Guchar *data,
double x, double y, GfxRGB *color);
- Gulong findColor(GfxRGB *rgb);
Gulong findColor(GfxRGB *x, GfxRGB *err);
};
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
ret = gFalse;
permFlags = defPermFlags;
+ ownerPasswordOk = gFalse;
trailerDict.dictLookup("Encrypt", &encrypt);
if ((encrypted1 = encrypt.isDict())) {
ret = gTrue;
#ifndef XREF_H
#define XREF_H
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
// Returns false if unknown or file is not damaged.
GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
+ // Direct access.
+ int getSize() { return size; }
+ XRefEntry *getEntry(int i) { return &entries[i]; }
+ Object *getTrailerDict() { return &trailerDict; }
+
private:
BaseStream *str; // input stream
GString *ownerPW, *userPW;
ImageOutputDev *imgOut;
GBool ok;
+ int exitCode;
+
+ exitCode = 99;
// parse args
ok = parseArgs(argDesc, &argc, argv);
if (!printVersion) {
printUsage("pdfimages", "<PDF-file> <image-root>", argDesc);
}
- exit(1);
+ goto err0;
}
fileName = new GString(argv[1]);
imgRoot = argv[2];
delete ownerPW;
}
if (!doc->isOk()) {
- goto err;
+ exitCode = 1;
+ goto err1;
}
// check for copy permission
if (!doc->okToCopy()) {
error(-1, "Copying of images from this document is not allowed.");
- goto err;
+ exitCode = 3;
+ goto err1;
}
// get page range
// write image files
imgOut = new ImageOutputDev(imgRoot, dumpJPEG);
- if (imgOut->isOk())
+ if (imgOut->isOk()) {
doc->displayPages(imgOut, firstPage, lastPage, 72, 0, gFalse);
+ }
delete imgOut;
+ exitCode = 0;
+
// clean up
- err:
+ err1:
delete doc;
delete globalParams;
+ err0:
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
- return 0;
+ return exitCode;
}
FILE *f;
GString *metadata;
GBool ok;
+ int exitCode;
+
+ exitCode = 99;
// parse args
ok = parseArgs(argDesc, &argc, argv);
if (!printVersion) {
printUsage("pdfinfo", "<PDF-file>", argDesc);
}
- exit(1);
+ goto err0;
}
fileName = new GString(argv[1]);
delete ownerPW;
}
if (!doc->isOk()) {
+ exitCode = 1;
goto err2;
}
f = fopen(fileName->getCString(), "rb");
#endif
if (f) {
-#if HAVE_FSEEK64
+#if HAVE_FSEEKO
+ fseeko(f, 0, SEEK_END);
+ printf("File size: %u bytes\n", (Guint)ftello(f));
+#elif HAVE_FSEEK64
fseek64(f, 0, SEEK_END);
printf("File size: %u bytes\n", (Guint)ftell64(f));
#else
delete metadata;
}
+ exitCode = 0;
+
// clean up
err2:
uMap->decRefCnt();
delete doc;
err1:
delete globalParams;
+ err0:
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
- return 0;
+ return exitCode;
}
static void printInfoString(Dict *infoDict, char *key, char *text,
tmStruct.tm_wday = -1;
tmStruct.tm_yday = -1;
tmStruct.tm_isdst = -1;
- mktime(&tmStruct); // compute the tm_wday and tm_yday fields
- if (strftime(buf, sizeof(buf), "%c", &tmStruct)) {
+ // compute the tm_wday and tm_yday fields
+ if (mktime(&tmStruct) != (time_t)-1 &&
+ strftime(buf, sizeof(buf), "%c", &tmStruct)) {
fputs(buf, stdout);
} else {
fputs(s, stdout);
GString *ownerPW, *userPW;
PBMOutputDev *pbmOut;
GBool ok;
+ int exitCode;
+
+ exitCode = 99;
// parse args
ok = parseArgs(argDesc, &argc, argv);
if (!printVersion) {
printUsage("pdftopbm", "<PDF-file> <PBM-root>", argDesc);
}
- exit(1);
+ goto err0;
}
fileName = new GString(argv[1]);
pbmRoot = argv[2];
delete ownerPW;
}
if (!doc->isOk()) {
- goto err;
+ exitCode = 1;
+ goto err1;
}
// get page range
doc->displayPages(pbmOut, firstPage, lastPage, resolution, 0, gFalse);
PBMOutputDev::killPBMOutputDev(pbmOut);
+ exitCode = 0;
+
// clean up
- err:
+ err1:
delete doc;
delete globalParams;
+ err0:
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
- return 0;
+ return exitCode;
}
PSOutputDev *psOut;
GBool ok;
char *p;
+ int exitCode;
+
+ exitCode = 99;
// parse args
ok = parseArgs(argDesc, &argc, argv);
if (paperSize[0]) {
if (!globalParams->setPSPaperSize(paperSize)) {
fprintf(stderr, "Invalid paper size\n");
- exit(1);
+ goto err0;
}
} else {
if (paperWidth) {
delete ownerPW;
}
if (!doc->isOk()) {
+ exitCode = 1;
goto err1;
}
// check for print permission
if (!doc->okToPrint()) {
error(-1, "Printing this document is not allowed.");
+ exitCode = 3;
goto err1;
}
doc->getCatalog(), firstPage, lastPage, mode);
if (psOut->isOk()) {
doc->displayPages(psOut, firstPage, lastPage, 72, 0, gFalse);
+ } else {
+ delete psOut;
+ exitCode = 2;
+ goto err2;
}
delete psOut;
+ exitCode = 0;
+
// clean up
err2:
delete psFileName;
err1:
delete doc;
delete globalParams;
+ err0:
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
- return 0;
+ return exitCode;
}
Object info;
GBool ok;
char *p;
+ int exitCode;
+
+ exitCode = 99;
// parse args
ok = parseArgs(argDesc, &argc, argv);
if (!printVersion) {
printUsage("pdftotext", "<PDF-file> [<text-file>]", argDesc);
}
- exit(1);
+ goto err0;
}
fileName = new GString(argv[1]);
delete ownerPW;
}
if (!doc->isOk()) {
+ exitCode = 1;
goto err2;
}
// check for copy permission
if (!doc->okToCopy()) {
error(-1, "Copying of text from this document is not allowed.");
+ exitCode = 3;
goto err2;
}
} else {
if (!(f = fopen(textFileName->getCString(), "wb"))) {
error(-1, "Couldn't open text file '%s'", textFileName->getCString());
+ exitCode = 2;
goto err3;
}
}
textOut = new TextOutputDev(textFileName->getCString(), rawOrder, htmlMeta);
if (textOut->isOk()) {
doc->displayPages(textOut, firstPage, lastPage, 72, 0, gFalse);
+ } else {
+ delete textOut;
+ exitCode = 2;
+ goto err3;
}
delete textOut;
} else {
if (!(f = fopen(textFileName->getCString(), "ab"))) {
error(-1, "Couldn't open text file '%s'", textFileName->getCString());
+ exitCode = 2;
goto err3;
}
}
}
}
+ exitCode = 0;
+
// clean up
err3:
delete textFileName;
uMap->decRefCnt();
err1:
delete globalParams;
+ err0:
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
- return 0;
+ return exitCode;
}
static void printInfoString(FILE *f, Dict *infoDict, char *key,
+++ /dev/null
-#define postscript_width 15
-#define postscript_height 15
-static unsigned char postscript_bits[] = {
- 0xf0, 0x7f, 0x10, 0x40, 0x10, 0x40, 0xc8, 0x23, 0x08, 0x20, 0x68, 0x23,
- 0x04, 0x10, 0x34, 0x10, 0x04, 0x10, 0xff, 0x7f, 0x55, 0x55, 0xab, 0x6a,
- 0x55, 0x55, 0xab, 0x6a, 0xfe, 0x3f};
$!
$ COMMON_OBJS = "Annot.obj,Array.obj,BuiltinFont.obj," + -
"BuiltinFontTables.obj,Catalog.obj,CharCodeToUnicode.obj," + -
- "CMap.obj,Decrypt.obj,Dict.obj,Error.obj," + -
+ "CMap.obj,Decrypt.obj,Dict.obj,Error.obj," + -
"FontEncodingTables.obj,FontFile.obj," + -
"Function.obj,Gfx.obj,GfxFont.obj,GfxState.obj,"+ -
- "GlobalParams.obj,Lexer.obj," + -
- "Link.obj,NameToCharCode.obj,Object.obj,OutputDev.obj," + -
- "Page.obj,Parser.obj,PDFdoc.obj,PSTokenizer.obj," + -
- "Stream.obj,UnicodeMap.obj,XRef.obj"
+ "GlobalParams.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,XRef.obj"
$ COMMON_LIBS = "[]common.olb/lib,[-.goo]libgoo.olb/lib"
$!
-$ XPDF_OBJS = "xpdf.obj,FTFont.obj,LTKOutputDev.obj,PSOutputDev.obj," + -
+$ XPDF_OBJS = "xpdf.obj,FTFont.obj,PSOutputDev.obj," + -
"SFont.obj,T1Font.obj,TextOutputDev.obj,TTFont.obj," + -
- "XOutputDev.obj"
-$ XPDF_LIBS = "[-.ltk]libltk.olb/lib"
+ "XOutputDev.obj,XPDFApp.o,XPDFCore.o,XPDFTree.o," + -
+ "XPDFViewer.o,XPixmapOutputDev.o"
+$ XPDF_LIBS = ""
$!
$ PDFTOPS_OBJS = "pdftops.obj,PSOutputDev.obj"
$ PDFTOPS_LIBS = ""
$!
$ PDFFONTS_OBJS = "pdffonts.obj"
$ PDFFONTS_LIBS = ""
-$! Build xpdf-ltk.h
-$ close sys$input
-$ define/user sys$input xpdf.ltk
-$ define/user sys$output xpdf-ltk.h
-$ run [-.ltk]ltkbuild
$!
$COMPILE_CXX_LOOP:
$ file = f$element(i, ",",COMMON_OBJS)
+++ /dev/null
-#========================================================================
-#
-# xpdf-flip.ltk
-#
-# Copyright 1997-2002 Glyph & Cog, LLC
-#
-#========================================================================
-
-#------------------------------------------------------------------------
-# main window
-#------------------------------------------------------------------------
-
-Window(func:makeWindow title:"xpdf" icon:xpdfIcon) {
- Box(x:2 y:1 xfill:1 yfill:1) {
-
- # canvas, scrollbars, page number
- Box(x:2 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1 sunken) {
- ScrollingCanvas(name:"canvas" w:100 h:100)
- }
- Box1(yfill:1) {
- Scrollbar(name:"vScrollbar" vert min:0 max:100 move:&scrollVertCbk)
- }
- Box(x:4 y:1) {
- Box1() {
- Label(text:"Page"
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- Box1(sunken left:4 right:4) {
- TextIn(name:"pageNum" mw:6 done:&pageNumCbk
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- Box1() {
- Label(name:"numPages" length:9
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- Box(x:1 y:2 xfill:1) {
- Box1(xfill:1) {
- Scrollbar(name:"hScrollbar" horiz min:0 max:100
- move:&scrollHorizCbk)
- }
- Box1(xfill:1 yfill:1) { Empty() }
- }
- }
- Box1() { Empty() }
- }
-
- # buttons
- Box(x:1 y:12 yfill:1) {
- Box1() {
- IconButton(bitmap:leftArrow_bits w:leftArrow_width
- h:leftArrow_height press:&prevPageCbk)
- }
- Box1() {
- IconButton(bitmap:rightArrow_bits w:rightArrow_width
- h:rightArrow_height press:&nextPageCbk)
- }
- Box1() {
- IconButton(bitmap:dblLeftArrow_bits w:dblLeftArrow_width
- h:dblLeftArrow_height press:&prevTenPageCbk)
- }
- Box1() {
- IconButton(bitmap:dblRightArrow_bits w:dblRightArrow_width
- h:dblRightArrow_height press:&nextTenPageCbk)
- }
- Box1(yfill:1) { Empty() }
- Box1() {
- IconButton(bitmap:zoomIn_bits w:zoomIn_width
- h:zoomIn_height press:&zoomInCbk)
- }
- Box1() {
- IconButton(bitmap:zoomOut_bits w:zoomOut_width
- h:zoomOut_height press:&zoomOutCbk)
- }
- Box1(yfill:1) { Empty() }
- Box1() {
- IconButton(bitmap:postscript_bits w:postscript_width
- h:postscript_height press:&postScriptCbk)
- }
- Box1() {
- IconButton(bitmap:about_bits w:about_width h:about_height
- press:&aboutCbk)
- }
- Box1(yfill:1) { Empty() }
- Box1() { Button(label:"Quit" press:&quitCbk) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# menu for main window
-#------------------------------------------------------------------------
-
-Menu(func:makeMenu title:"xpdf" n:9) {
- MenuItem(text:"Open..." shortcut:"O" num:menuOpen
- select:&menuCbk)
- MenuItem(text:"Save PDF..." num:menuSavePDF
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Find" shortcut:"F" num:menuFind
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Rotate counterclockwise" num:menuRotateCCW
- select:&menuCbk)
- MenuItem(text:"Rotate clockwise" num:menuRotateCW
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Quit" shortcut:"Q" num:menuQuit
- select:&menuCbk)
-}
-
-#------------------------------------------------------------------------
-# "PostScript output" dialog
-#------------------------------------------------------------------------
-
-Window(func:makePostScriptDialog dialog:gTrue defWidget:"ok"
- title:"xpdf: PostScript output") {
- Box(x:1 y:3) {
- Box(x:4 y:1) {
- Box1() { Label(text:"Pages:") }
- Box1(sunken) {
- TextIn(name:"firstPage" mw:6 tab:"lastPage"
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- Box1() { Label(text:"to") }
- Box1(sunken) {
- TextIn(name:"lastPage" mw:6 tab:"fileName"
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- }
- Box(x:2 y:1) {
- Box1() { Label(text:"File:") }
- Box1(sunken xfill:1) {
- TextIn(name:"fileName" mw:32
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- }
- Box(x:3 y:1 top:8) {
- Box1(left:8) { Button(name:"ok" label:"Ok" press:&psButtonCbk num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&psButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "open" dialog
-#------------------------------------------------------------------------
-
-Window(func:makeOpenDialog dialog:gTrue defWidget:"open"
- title:"xpdf: Open...") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1) {
- FileReq(name:"fileReq" select:openSelectCbk
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"open" label:"Open" press:&openButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&openButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "save" dialog
-#------------------------------------------------------------------------
-
-Window(func:makeSaveDialog dialog:gTrue defWidget:"save"
- title:"xpdf: Save as...") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1) {
- FileReq(name:"fileReq" select:saveSelectCbk
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"save" label:"Save" press:&saveButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&saveButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "find" window
-#------------------------------------------------------------------------
-
-Window(func:makeFindWindow defWidget:"find" title:"xpdf: Find") {
- Box(x:1 y:3 xfill:1 yfill:1) {
- Box(x:2 y:1 xfill:1) {
- Box1() { Label(text:"Text:") }
- Box1(xfill:1 sunken) {
- TextIn(name:"text" mw:32
- font:"-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*")
- }
- }
- Box1(xfill:1 yfill:1) { Empty() }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"find" label:"Find" press:&findButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Close" press:&findButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "about" window
-#------------------------------------------------------------------------
-
-Window(func:makeAboutWindow defWidget:"close" title:"About xpdf") {
- Box(x:1 y:2) {
- Box(x:1 y:10 left:2 right:2 top:2 bottom:2 sunken) {
- Box1(bottom:0) {
- Label(text:"xpdf"
- font:"-*-times-bold-i-*-*-24-*-*-*-*-*-*-*")
- }
- Box1(bottom:12) {
- Label(text:["Version " xpdfVersion])
- }
- Box1(bottom:0) {
- Label(text:xpdfCopyright)
- }
- Box1(bottom:12) {
- Label(text:"derekn@foolabs.com")
- }
- Box1(bottom:0) {
- Label(text:["Supports PDF version " pdfVersion "."])
- }
- Box1(bottom:0) {
- Label(text:"The PDF data structures, operators, and specification")
- }
- Box1(bottom:12) {
- Label(text:"are copyright 1995 Adobe Systems Inc.")
- }
- Box1(bottom:0) {
- Label(text:"Mouse button 1: select text / follow link")
- }
- Box1(bottom:12) {
- Label(text:"Mouse button 3: menu")
- }
- Box1(bottom:12) {
- Label(text:"http://www.foolabs.com/xpdf/")
- }
- }
- Box(x:2 y:1) {
- Box1(xfill:1) { Empty() }
- Box1() { Button(name:"close" label:"Close" press:&closeAboutCbk) }
- }
- }
-}
+++ /dev/null
-// This file was generated by ltkbuild 1.01
-
-LTKWindow *makeWindow(LTKApp *a) {
- return new LTKWindow(a, gFalse, "xpdf", xpdfIcon, NULL,
- new LTKBox(NULL, 1, 2, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 2, 2, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderSunken, 1, 1,
- new LTKScrollingCanvas("canvas", 0, 100, 100, 32, 32)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 1,
- new LTKScrollbar("vScrollbar", 0, gTrue, 0, 100, &scrollVertCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKScrollbar("hScrollbar", 0, gFalse, 0, 100, &scrollHorizCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKEmpty()
- )
- ),
- new LTKBox(NULL, 15, 1, 0, 0, 0, 0, ltkBorderNone, 1, 0,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, backArrow_bits, backArrow_width, backArrow_height, ltkButtonClick, &backCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, dblLeftArrow_bits, dblLeftArrow_width, dblLeftArrow_height, ltkButtonClick, &prevTenPageCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, leftArrow_bits, leftArrow_width, leftArrow_height, ltkButtonClick, &prevPageCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, rightArrow_bits, rightArrow_width, rightArrow_height, ltkButtonClick, &nextPageCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, dblRightArrow_bits, dblRightArrow_width, dblRightArrow_height, ltkButtonClick, &nextTenPageCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, forwardArrow_bits, forwardArrow_width, forwardArrow_height, ltkButtonClick, &forwardCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKLabel(NULL, 0, ltkLabelStatic, 8, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", "Page")
- ),
- new LTKBox(NULL, 1, 1, 4, 4, 2, 2, ltkBorderSunken, 0, 0,
- new LTKTextIn("pageNum", 0, 6, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", &pageNumCbk, NULL)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKLabel("numPages", 0, ltkLabelMaxLength, 9, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", NULL)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKMenuButton("zoom", 0, zoomMenu)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, find_bits, find_width, find_height, ltkButtonClick, &findCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, postscript_bits, postscript_width, postscript_height, ltkButtonClick, &postScriptCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, about_bits, about_width, about_height, ltkButtonClick, &aboutCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKLabel("link", 0, ltkLabelFixedWidth, 8, "-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*", NULL)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, "Quit", ltkButtonClick, &quitCbk)
- )
- )
- )
- );
-}
-
-LTKWindow *makeFullScreenWindow(LTKApp *a) {
- return new LTKWindow(a, gFalse, "xpdf", xpdfIcon, NULL,
- new LTKBox(NULL, 1, 1, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKScrollingCanvas("canvas", 0, 100, 100, 32, 32)
- )
- );
-}
-
-LTKMenu *makeMenu() {
- return new LTKMenu("xpdf", 8,
- new LTKMenuItem("Open...", "O", menuOpen, &menuCbk, NULL),
- new LTKMenuItem("Reload", "R", menuReload, &menuCbk, NULL),
- new LTKMenuItem("Save as...", NULL, menuSavePDF, &menuCbk, NULL),
- new LTKMenuItem(NULL, NULL, 0, NULL, NULL),
- new LTKMenuItem("Rotate counterclockwise", NULL, menuRotateCCW, &menuCbk, NULL),
- new LTKMenuItem("Rotate clockwise", NULL, menuRotateCW, &menuCbk, NULL),
- new LTKMenuItem(NULL, NULL, 0, NULL, NULL),
- new LTKMenuItem("Quit", "Q", menuQuit, &menuCbk, NULL)
-
- );
-}
-
-LTKMenu *makeZoomMenu() {
- return new LTKMenu("zoom", 14,
- new LTKMenuItem("-5", NULL, -5, &zoomMenuCbk, NULL),
- new LTKMenuItem("-4", NULL, -4, &zoomMenuCbk, NULL),
- new LTKMenuItem("-3", NULL, -3, &zoomMenuCbk, NULL),
- new LTKMenuItem("-2", NULL, -2, &zoomMenuCbk, NULL),
- new LTKMenuItem("-1", NULL, -1, &zoomMenuCbk, NULL),
- new LTKMenuItem("0", NULL, 0, &zoomMenuCbk, NULL),
- new LTKMenuItem("+1", NULL, 1, &zoomMenuCbk, NULL),
- new LTKMenuItem("+2", NULL, 2, &zoomMenuCbk, NULL),
- new LTKMenuItem("+3", NULL, 3, &zoomMenuCbk, NULL),
- new LTKMenuItem("+4", NULL, 4, &zoomMenuCbk, NULL),
- new LTKMenuItem("+5", NULL, 5, &zoomMenuCbk, NULL),
- new LTKMenuItem(NULL, NULL, 0, NULL, NULL),
- new LTKMenuItem("fit page", "z", 100, &zoomMenuCbk, NULL),
- new LTKMenuItem("fit width", "w", 101, &zoomMenuCbk, NULL)
-
- );
-}
-
-LTKWindow *makePostScriptDialog(LTKApp *a) {
- return new LTKWindow(a, gTrue, "xpdf: PostScript output", NULL, "ok",
- new LTKBox(NULL, 1, 3, 0, 0, 0, 0, ltkBorderNone, 0, 0,
- new LTKBox(NULL, 4, 1, 0, 0, 0, 0, ltkBorderNone, 0, 0,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKLabel(NULL, 0, ltkLabelStatic, 8, NULL, "Pages:")
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderSunken, 0, 0,
- new LTKTextIn("firstPage", 0, 6, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", NULL, "lastPage")
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKLabel(NULL, 0, ltkLabelStatic, 8, NULL, "to")
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderSunken, 0, 0,
- new LTKTextIn("lastPage", 0, 6, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", NULL, "fileName")
- )
- ),
- new LTKBox(NULL, 2, 1, 0, 0, 0, 0, ltkBorderNone, 0, 0,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKLabel(NULL, 0, ltkLabelStatic, 8, NULL, "File:")
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderSunken, 1, 0,
- new LTKTextIn("fileName", 0, 32, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", NULL, NULL)
- )
- ),
- new LTKBox(NULL, 3, 1, 0, 0, 8, 0, ltkBorderNone, 0, 0,
- new LTKBox(NULL, 1, 1, 8, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton("ok", 1, "Ok", ltkButtonClick, &psButtonCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKEmpty()
- ),
- new LTKBox(NULL, 1, 1, 2, 8, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, "Cancel", ltkButtonClick, &psButtonCbk)
- )
- )
- )
- );
-}
-
-LTKWindow *makeOpenDialog(LTKApp *a) {
- return new LTKWindow(a, gTrue, "xpdf: Open...", NULL, "open",
- new LTKBox(NULL, 1, 2, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 1,
- new LTKFileReq("fileReq", 0, openSelectCbk, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- ),
- new LTKBox(NULL, 3, 1, 0, 0, 8, 0, ltkBorderNone, 1, 0,
- new LTKBox(NULL, 1, 1, 8, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton("open", 1, "Open", ltkButtonClick, &openButtonCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKEmpty()
- ),
- new LTKBox(NULL, 1, 1, 2, 8, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, "Cancel", ltkButtonClick, &openButtonCbk)
- )
- )
- )
- );
-}
-
-LTKWindow *makeSaveDialog(LTKApp *a) {
- return new LTKWindow(a, gTrue, "xpdf: Save as...", NULL, "save",
- new LTKBox(NULL, 1, 2, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 1,
- new LTKFileReq("fileReq", 0, saveSelectCbk, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- ),
- new LTKBox(NULL, 3, 1, 0, 0, 8, 0, ltkBorderNone, 1, 0,
- new LTKBox(NULL, 1, 1, 8, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton("save", 1, "Save", ltkButtonClick, &saveButtonCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKEmpty()
- ),
- new LTKBox(NULL, 1, 1, 2, 8, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, "Cancel", ltkButtonClick, &saveButtonCbk)
- )
- )
- )
- );
-}
-
-LTKWindow *makeFindWindow(LTKApp *a) {
- return new LTKWindow(a, gFalse, "xpdf: Find", NULL, "find",
- new LTKBox(NULL, 1, 3, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 2, 1, 0, 0, 0, 0, ltkBorderNone, 1, 0,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKLabel(NULL, 0, ltkLabelStatic, 8, NULL, "Text:")
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderSunken, 1, 0,
- new LTKTextIn("text", 0, 32, "-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*", NULL, NULL)
- )
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 1,
- new LTKEmpty()
- ),
- new LTKBox(NULL, 3, 1, 0, 0, 8, 0, ltkBorderNone, 1, 0,
- new LTKBox(NULL, 1, 1, 8, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton("find", 1, "Find", ltkButtonClick, &findButtonCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKEmpty()
- ),
- new LTKBox(NULL, 1, 1, 2, 8, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton(NULL, 0, "Close", ltkButtonClick, &findButtonCbk)
- )
- )
- )
- );
-}
-
-LTKWindow *makeAboutWindow(LTKApp *a) {
- return new LTKWindow(a, gFalse, "About xpdf", NULL, "close",
- new LTKBox(NULL, 1, 2, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 2, 2, 0, 0, 0, 0, ltkBorderNone, 1, 1,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderSunken, 1, 1,
- new LTKList("list", 0, 400, 30, gFalse, "-*-courier-medium-r-normal-*-12-*-*-*-*-*-*-*")
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 1,
- new LTKScrollbar("vScrollbar", 0, gTrue, 0, 100, &aboutScrollVertCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKScrollbar("hScrollbar", 0, gFalse, 0, 100, &aboutScrollHorizCbk)
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKEmpty()
- )
- ),
- new LTKBox(NULL, 2, 1, 0, 0, 0, 0, ltkBorderNone, 0, 0,
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 1, 0,
- new LTKEmpty()
- ),
- new LTKBox(NULL, 1, 1, 2, 2, 2, 2, ltkBorderNone, 0, 0,
- new LTKButton("close", 0, "Close", ltkButtonClick, &closeAboutCbk)
- )
- )
- )
- );
-}
-
+++ /dev/null
-#========================================================================
-#
-# xpdf-top.ltk
-#
-# Copyright 1996-2002 Glyph & Cog, LLC
-#
-#========================================================================
-
-#------------------------------------------------------------------------
-# main window
-#------------------------------------------------------------------------
-
-Window(func:makeWindow title:"xpdf" icon:xpdfIcon) {
- Box(x:1 y:2 xfill:1 yfill:1) {
-
- # buttons, page number, etc.
- Box(x:14 y:1 xfill:1 top:2) {
- Box1() {
- IconButton(bitmap:dblLeftArrow_bits w:dblLeftArrow_width
- h:dblLeftArrow_height press:&prevTenPageCbk)
- }
- Box1() {
- IconButton(bitmap:leftArrow_bits w:leftArrow_width
- h:leftArrow_height press:&prevPageCbk)
- }
- Box1() {
- IconButton(bitmap:rightArrow_bits w:rightArrow_width
- h:rightArrow_height press:&nextPageCbk)
- }
- Box1() {
- IconButton(bitmap:dblRightArrow_bits w:dblRightArrow_width
- h:dblRightArrow_height press:&nextTenPageCbk)
- }
- Box1() {
- Label(text:"Page"
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1(sunken left:4 right:4) {
- TextIn(name:"pageNum" mw:6 done:&pageNumCbk
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1() {
- Label(name:"numPages" maxLength length:9
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1() {
- IconButton(bitmap:zoomIn_bits w:zoomIn_width
- h:zoomIn_height press:&zoomInCbk)
- }
- Box1() {
- IconButton(bitmap:zoomOut_bits w:zoomOut_width
- h:zoomOut_height press:&zoomOutCbk)
- }
- Box1() {
- IconButton(bitmap:find_bits w:find_width
- h:find_height press:&findCbk)
- }
- Box1() {
- IconButton(bitmap:postscript_bits w:postscript_width
- h:postscript_height press:&postScriptCbk)
- }
- Box1() {
- IconButton(bitmap:about_bits w:about_width h:about_height
- press:&aboutCbk)
- }
- Box1(xfill:1) {
- Label(name:"link" fixedWidth
- font:"-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*")
- }
- Box1() { Button(label:"Quit" press:&quitCbk) }
- }
-
- # canvas and scrollbars
- Box(x:2 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1 sunken) {
- ScrollingCanvas(name:"canvas" w:100 h:100)
- }
- Box1(yfill:1) {
- Scrollbar(name:"vScrollbar" vert min:0 max:100 move:&scrollVertCbk)
- }
- Box1(xfill:1) {
- Scrollbar(name:"hScrollbar" horiz min:0 max:100 move:&scrollHorizCbk)
- }
- Box1() { Empty() }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# menu for main window
-#------------------------------------------------------------------------
-
-Menu(func:makeMenu title:"xpdf" n:7) {
- MenuItem(text:"Open..." shortcut:"O" num:menuOpen
- select:&menuCbk)
- MenuItem(text:"Save as..." num:menuSavePDF
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Rotate counterclockwise" num:menuRotateCCW
- select:&menuCbk)
- MenuItem(text:"Rotate clockwise" num:menuRotateCW
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Quit" shortcut:"Q" num:menuQuit
- select:&menuCbk)
-}
-
-#------------------------------------------------------------------------
-# "PostScript output" dialog
-#------------------------------------------------------------------------
-
-Window(func:makePostScriptDialog dialog:gTrue defWidget:"ok"
- title:"xpdf: PostScript output") {
- Box(x:1 y:3) {
- Box(x:4 y:1) {
- Box1() { Label(text:"Pages:") }
- Box1(sunken) {
- TextIn(name:"firstPage" mw:6 tab:"lastPage"
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1() { Label(text:"to") }
- Box1(sunken) {
- TextIn(name:"lastPage" mw:6 tab:"fileName"
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- }
- Box(x:2 y:1) {
- Box1() { Label(text:"File:") }
- Box1(sunken xfill:1) {
- TextIn(name:"fileName" mw:32
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- }
- Box(x:3 y:1 top:8) {
- Box1(left:8) { Button(name:"ok" label:"Ok" press:&psButtonCbk num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&psButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "open" dialog
-#------------------------------------------------------------------------
-
-Window(func:makeOpenDialog dialog:gTrue defWidget:"open"
- title:"xpdf: Open...") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1) {
- FileReq(name:"fileReq" select:openSelectCbk
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"open" label:"Open" press:&openButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&openButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "save" dialog
-#------------------------------------------------------------------------
-
-Window(func:makeSaveDialog dialog:gTrue defWidget:"save"
- title:"xpdf: Save as...") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1) {
- FileReq(name:"fileReq" select:saveSelectCbk
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"save" label:"Save" press:&saveButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&saveButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "find" window
-#------------------------------------------------------------------------
-
-Window(func:makeFindWindow defWidget:"find" title:"xpdf: Find") {
- Box(x:1 y:3 xfill:1 yfill:1) {
- Box(x:2 y:1 xfill:1) {
- Box1() { Label(text:"Text:") }
- Box1(xfill:1 sunken) {
- TextIn(name:"text" mw:32
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- }
- Box1(xfill:1 yfill:1) { Empty() }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"find" label:"Find" press:&findButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Close" press:&findButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "about" window
-#------------------------------------------------------------------------
-
-Window(func:makeAboutWindow defWidget:"close" title:"About xpdf") {
- Box(x:1 y:2) {
- Box(x:1 y:11 left:2 right:2 top:2 bottom:2 sunken) {
- Box1(bottom:0) {
- Label(text:"xpdf"
- font:"-*-times-bold-i-normal-*-24-*-*-*-*-*-*-*")
- }
- Box1(bottom:12) {
- Label(text:["Version " xpdfVersion])
- }
- Box1(bottom:0) {
- Label(text:xpdfCopyright)
- }
- Box1(bottom:12) {
- Label(text:"derekn@foolabs.com")
- }
- Box1(bottom:2) {
- Label(text:["Supports PDF version " pdfVersion "."])
- }
- Box1(bottom:0) {
- Label(text:"The PDF data structures, operators, and specification")
- }
- Box1(bottom:12) {
- Label(text:"are copyright 1995 Adobe Systems Inc.")
- }
- Box1(bottom:0) {
- Label(text:"Mouse button 1: select text / follow link")
- }
- Box1(bottom:0) {
- Label(text:"Mouse button 2: pan window")
- }
- Box1(bottom:12) {
- Label(text:"Mouse button 3: menu")
- }
- Box1(bottom:12) {
- Label(text:"http://www.foolabs.com/xpdf/")
- }
- }
- Box(x:2 y:1) {
- Box1(xfill:1) { Empty() }
- Box1() { Button(name:"close" label:"Close" press:&closeAboutCbk) }
- }
- }
-}
//========================================================================
#include <aconf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <time.h>
-#include <X11/X.h>
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
#include "gtypes.h"
#include "GString.h"
#include "parseargs.h"
#include "gfile.h"
#include "gmem.h"
#include "GlobalParams.h"
-#include "LTKAll.h"
#include "Object.h"
-#include "Stream.h"
-#include "Array.h"
-#include "Dict.h"
-#include "XRef.h"
-#include "Catalog.h"
-#include "Page.h"
-#include "Link.h"
-#include "PDFDoc.h"
-#include "XOutputDev.h"
-#include "LTKOutputDev.h"
-#include "PSOutputDev.h"
-#include "TextOutputDev.h"
-#include "Error.h"
+#include "XPDFApp.h"
#include "config.h"
-#ifdef XlibSpecificationRelease
-#if XlibSpecificationRelease < 5
-typedef char *XPointer;
-#endif
-#else
-typedef char *XPointer;
-#endif
-
-// hack around old X includes which are missing these symbols
-#ifndef XK_Page_Up
-#define XK_Page_Up 0xFF55
-#endif
-#ifndef XK_Page_Down
-#define XK_Page_Down 0xFF56
-#endif
-#ifndef XK_KP_Home
-#define XK_KP_Home 0xFF95
-#endif
-#ifndef XK_KP_Left
-#define XK_KP_Left 0xFF96
-#endif
-#ifndef XK_KP_Up
-#define XK_KP_Up 0xFF97
-#endif
-#ifndef XK_KP_Right
-#define XK_KP_Right 0xFF98
-#endif
-#ifndef XK_KP_Down
-#define XK_KP_Down 0xFF99
-#endif
-#ifndef XK_KP_Prior
-#define XK_KP_Prior 0xFF9A
-#endif
-#ifndef XK_KP_Page_Up
-#define XK_KP_Page_Up 0xFF9A
-#endif
-#ifndef XK_KP_Next
-#define XK_KP_Next 0xFF9B
-#endif
-#ifndef XK_KP_Page_Down
-#define XK_KP_Page_Down 0xFF9B
-#endif
-#ifndef XK_KP_End
-#define XK_KP_End 0xFF9C
-#endif
-#ifndef XK_KP_Begin
-#define XK_KP_Begin 0xFF9D
-#endif
-#ifndef XK_KP_Insert
-#define XK_KP_Insert 0xFF9E
-#endif
-#ifndef XK_KP_Delete
-#define XK_KP_Delete 0xFF9F
-#endif
-
-//------------------------------------------------------------------------
-// misc constants / enums
-//------------------------------------------------------------------------
-
-#define remoteCmdLength 512
-
-enum XpdfMenuItem {
- menuOpen,
- menuReload,
- menuSavePDF,
- menuRotateCCW,
- menuRotateCW,
- menuQuit
-};
-
-//------------------------------------------------------------------------
-// prototypes
-//------------------------------------------------------------------------
-
-// loadFile / displayPage
-static GBool loadFile(GString *fileName);
-static void displayPage(int page1, int zoomA, int rotateA, GBool addToHist);
-static void displayDest(LinkDest *dest, int zoomA, int rotateA,
- GBool addToHist);
-
-// key press and menu callbacks
-static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers,
- char *s, int n);
-static void menuCbk(LTKMenuItem *item);
-
-// mouse callbacks
-static void buttonPressCbk(LTKWidget *canvas1, int n,
- int mx, int my, int button, GBool dblClick);
-static void buttonReleaseCbk(LTKWidget *canvas1, int n,
- int mx, int my, int button, GBool click);
-static void doLink(int mx, int my);
-static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my);
-static void mouseDragCbk(LTKWidget *widget, int widgetNum,
- int mx, int my, int button);
-
-// button callbacks
-static void nextPageCbk(LTKWidget *button, int n, GBool on);
-static void nextTenPageCbk(LTKWidget *button, int n, GBool on);
-static void gotoNextPage(int inc, GBool top);
-static void prevPageCbk(LTKWidget *button, int n, GBool on);
-static void prevTenPageCbk(LTKWidget *button, int n, GBool on);
-static void gotoPrevPage(int dec, GBool top, GBool bottom);
-static void backCbk(LTKWidget *button, int n, GBool on);
-static void forwardCbk(LTKWidget *button, int n, GBool on);
-static void pageNumCbk(LTKWidget *textIn, int n, GString *text);
-static void zoomMenuCbk(LTKMenuItem *item);
-static void postScriptCbk(LTKWidget *button, int n, GBool on);
-static void aboutCbk(LTKWidget *button, int n, GBool on);
-static void quitCbk(LTKWidget *button, int n, GBool on);
-
-// scrollbar callbacks
-static void scrollVertCbk(LTKWidget *scrollbar, int n, int val);
-static void scrollHorizCbk(LTKWidget *scrollbar, int n, int val);
-
-// misc callbacks
-static void layoutCbk(LTKWindow *win1);
-static void updateScrollbars();
-static void propChangeCbk(LTKWindow *win1, Atom atom);
-
-// selection
-static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax);
-
-// "Open" dialog
-static void mapOpenDialog();
-static void openButtonCbk(LTKWidget *button, int n, GBool on);
-static void openSelectCbk(LTKWidget *widget, int n, GString *name);
-
-// "Reload"
-static void reloadCbk();
-
-// "Save PDF" dialog
-static void mapSaveDialog();
-static void saveButtonCbk(LTKWidget *button, int n, GBool on);
-static void saveSelectCbk(LTKWidget *widget, int n, GString *name);
-
-// "PostScript" dialog
-static void mapPSDialog();
-static void psButtonCbk(LTKWidget *button, int n, GBool on);
-
-// "About" window
-static void mapAboutWin();
-static void closeAboutCbk(LTKWidget *button, int n, GBool on);
-static void aboutLayoutCbk(LTKWindow *winA);
-static void aboutScrollVertCbk(LTKWidget *scrollbar, int n, int val);
-static void aboutScrollHorizCbk(LTKWidget *scrollbar, int n, int val);
-
-// "Find" window
-static void findCbk(LTKWidget *button, int n, GBool on);
-static void mapFindWin();
-static void findButtonCbk(LTKWidget *button, int n, GBool on);
-static void doFind(char *s);
-
-// app kill callback
-static void killCbk(LTKWindow *win1);
-
-//------------------------------------------------------------------------
-// "About" window text
-//------------------------------------------------------------------------
-
-static char *aboutWinText[] = {
- "X X d fff",
- " X X d f f",
- " X X d f",
- " X pppp dddd ffff",
- " X X p p d d f",
- " X X p p d d f",
- "X X pppp dddd f Version " xpdfVersion,
- " p",
- " p",
- " p",
- "",
- xpdfCopyright,
- "",
- "http://www.foolabs.com/xpdf/",
- "derekn@foolabs.com",
- "",
- "Licensed under the GNU General Public License (GPL).",
- "See the 'COPYING' file for details.",
- "",
- "Supports PDF version " supportedPDFVersionStr ".",
- "",
- "The PDF data structures, operators, and specification",
- "are copyright 1985-2001 Adobe Systems Inc.",
- "",
- "Mouse bindings:",
- " button 1: select text / follow link",
- " button 2: pan window",
- " button 3: menu",
- "",
- "Key bindings:",
- " o = open file",
- " r = reload",
- " f = find text",
- " n = <PgDn> = next page",
- " p = <PgUp> = previous page",
- " <space> = scroll down",
- " <backspace> = <delete> = scroll up",
- " v = forward (history path)",
- " b = backward (history path)",
- " 0 / + / - = zoom zero / in / out",
- " z / w = zoom page / page width",
- " ctrl-L = redraw",
- " q = quit",
- " <home> / <end> = top / bottom of page",
- " <arrows> = scroll",
- "",
- "For more information, please read the xpdf(1) man page.",
- NULL
-};
-
//------------------------------------------------------------------------
// command line options
//------------------------------------------------------------------------
-static char initialZoomStr[32] = "";
static char t1libControlStr[16] = "";
static char freetypeControlStr[16] = "";
static char psFileArg[256];
static char cfgFileName[256] = "";
static GBool printVersion = gFalse;
static GBool printHelp = gFalse;
-static GBool viKeys = gFalse;
static ArgDesc argDesc[] = {
{"-g", argStringDummy, NULL, 0,
"reverse video"},
{"-papercolor", argStringDummy, NULL, 0,
"color of paper background"},
- {"-z", argString, initialZoomStr, sizeof(initialZoomStr),
+ {"-z", argStringDummy, NULL, 0,
"initial zoom level (-5..5, page, width)"},
#if HAVE_T1LIB_H
{"-t1lib", argString, t1libControlStr, sizeof(t1libControlStr),
{NULL}
};
-static XrmOptionDescRec opts[] = {
- {"-display", ".display", XrmoptionSepArg, NULL},
- {"-foreground", ".foreground", XrmoptionSepArg, NULL},
- {"-fg", ".foreground", XrmoptionSepArg, NULL},
- {"-background", ".background", XrmoptionSepArg, NULL},
- {"-bg", ".background", XrmoptionSepArg, NULL},
- {"-geometry", ".geometry", XrmoptionSepArg, NULL},
- {"-g", ".geometry", XrmoptionSepArg, NULL},
- {"-font", ".font", XrmoptionSepArg, NULL},
- {"-fn", ".font", XrmoptionSepArg, NULL},
- {"-title", ".title", XrmoptionSepArg, NULL},
- {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"},
- {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL},
- {"-rv", ".reverseVideo", XrmoptionNoArg, (XPointer)"true"},
- {"-papercolor", ".paperColor", XrmoptionSepArg, NULL},
- {NULL}
-};
-
-//------------------------------------------------------------------------
-// global variables
-//------------------------------------------------------------------------
-
-// zoom factor is 1.2 (similar to DVI magsteps)
-#define minZoom -5
-#define maxZoom 5
-#define zoomPage 100
-#define zoomWidth 101
-#define defZoom 1
-static int zoomDPI[maxZoom - minZoom + 1] = {
- 29, 35, 42, 50, 60,
- 72,
- 86, 104, 124, 149, 179
-};
-
-static PDFDoc *doc;
-
-static LTKOutputDev *out;
-
-static int page;
-static int zoom;
-static int rotate;
-static GBool quit;
-
-static time_t modTime; // last modification time of PDF file
-
-static LinkAction *linkAction; // mouse pointer is over this link
-static int // coordinates of current selection:
- selectXMin, selectYMin, // (xMin==xMax || yMin==yMax) means there
- selectXMax, selectYMax; // is no selection
-static GBool lastDragLeft; // last dragged selection edge was left/right
-static GBool lastDragTop; // last dragged selection edge was top/bottom
-static int panMX, panMY; // last mouse position for pan
-
-struct History {
- GString *fileName;
- int page;
-};
-#define historySize 50
-static History // page history queue
- history[historySize];
-static int historyCur; // currently displayed page
-static int historyBLen; // number of valid entries backward from
- // current entry
-static int historyFLen; // number of valid entries forward from
- // current entry
-
-static GString *psFileName;
-static int psFirstPage, psLastPage;
-
-static GString *fileReqDir; // current directory for file requesters
-
-static GString *urlCommand; // command to execute for URI links
-
-static GString *windowTitle; // window title string
-
-static LTKApp *app;
-static Display *display;
-static LTKWindow *win;
-static LTKMenu *zoomMenu;
-static LTKScrollingCanvas *canvas;
-static LTKScrollbar *hScrollbar, *vScrollbar;
-static LTKTextIn *pageNumText;
-static LTKLabel *numPagesLabel;
-static LTKLabel *linkLabel;
-static LTKMenuButton *zoomMenuBtn;
-static LTKWindow *aboutWin;
-static LTKList *aboutList;
-static LTKScrollbar *aboutHScrollbar, *aboutVScrollbar;
-static LTKWindow *psDialog;
-static LTKWindow *openDialog;
-static LTKWindow *saveDialog;
-static LTKWindow *findWin;
-static LTKTextIn *findTextIn;
-static Atom remoteAtom;
-static GC selectGC;
-
-//------------------------------------------------------------------------
-// GUI includes
-//------------------------------------------------------------------------
-
-#include "xpdfIcon.xpm"
-#include "leftArrow.xbm"
-#include "dblLeftArrow.xbm"
-#include "rightArrow.xbm"
-#include "dblRightArrow.xbm"
-#include "backArrow.xbm"
-#include "forwardArrow.xbm"
-#include "find.xbm"
-#include "postscript.xbm"
-#include "about.xbm"
-#include "xpdf-ltk.h"
-
-//------------------------------------------------------------------------
-// main program
//------------------------------------------------------------------------
int main(int argc, char *argv[]) {
- Window xwin;
- XGCValues gcValues;
- char cmd[remoteCmdLength];
- LTKMenu *menu;
- GString *name;
- GString *title;
- GString *initialZoom;
- GBool reverseVideo;
- unsigned long paperColor;
- GBool installCmap;
- int rgbCubeSize;
+ XPDFApp *app;
+ GString *fileName;
int pg;
GString *destName;
- LinkDest *dest;
- int x, y;
- Guint width, height;
- double width1, height1;
+ GString *userPasswordStr, *ownerPasswordStr;
GBool ok;
- char s[20];
- int i;
- int ret;
+ int exitCode;
- // initialize
- app = NULL;
- win = NULL;
- out = NULL;
- remoteAtom = None;
- doc = NULL;
- psFileName = NULL;
- fileReqDir = getCurrentDir();
- ret = 0;
+ exitCode = 0;
+ userPasswordStr = ownerPasswordStr = NULL;
// parse args
ok = parseArgs(argDesc, &argc, argv);
fprintf(stderr, "Bad '-eol' value on command line\n");
}
}
- if (initialZoomStr[0]) {
- globalParams->setInitialZoom(initialZoomStr);
- }
if (t1libControlStr[0]) {
if (!globalParams->setT1libControl(t1libControlStr)) {
fprintf(stderr, "Bad '-t1lib' value on command line\n");
fprintf(stderr, "Bad '-freetype' value on command line\n");
}
}
+ if (printCommands) {
+ globalParams->setPrintCommands(printCommands);
+ }
if (quiet) {
globalParams->setErrQuiet(quiet);
}
- // create LTKApp (and parse X-related args)
- app = new LTKApp("xpdf", "Xpdf", opts, &argc, argv);
- app->setKillCbk(&killCbk);
- display = app->getDisplay();
+ // create the XPDFApp object
+ app = new XPDFApp(&argc, argv);
+
+ // the initialZoom parameter can be set in either the config file or
+ // as an X resource (or command line arg)
+ if (app->getInitialZoom()) {
+ globalParams->setInitialZoom(app->getInitialZoom()->getCString());
+ }
// check command line
- if (doRemoteRaise)
+ if (doRemoteRaise) {
ok = ok && remoteName[5] && !doRemoteQuit && argc >= 1 && argc <= 3;
- else if (doRemoteQuit)
+ } else if (doRemoteQuit) {
ok = ok && remoteName[5] && argc == 1;
- else
+ } else {
ok = ok && argc >= 1 && argc <= 3;
+ }
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);
}
- ret = 1;
- goto done2;
+ exitCode = 99;
+ goto done1;
}
if (argc >= 2) {
- name = new GString(argv[1]);
+ fileName = new GString(argv[1]);
} else {
- name = NULL;
+ fileName = NULL;
}
pg = 1;
destName = NULL;
}
}
- // look for already-running remote server
+ // handle remote server stuff
if (remoteName[5]) {
- remoteAtom = XInternAtom(display, remoteName, False);
- xwin = XGetSelectionOwner(display, remoteAtom);
- if (xwin != None) {
- if (name) {
+ app->setRemoteName(remoteName);
+ if (app->remoteServerRunning()) {
+ if (fileName) {
if (destName) {
- sprintf(cmd, "%c +%.256s %.200s", doRemoteRaise ? 'D' : 'd',
- destName->getCString(), name->getCString());
- delete destName;
+ app->remoteOpenAtDest(fileName, destName, doRemoteRaise);
} else {
- sprintf(cmd, "%c %d %.200s", doRemoteRaise ? 'D' : 'd',
- pg, name->getCString());
+ app->remoteOpen(fileName, pg, doRemoteRaise);
}
- XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
- PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1);
- delete name;
} else if (doRemoteRaise) {
- XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
- PropModeReplace, (Guchar *)"r", 2);
+ app->remoteRaise();
} else if (doRemoteQuit) {
- XChangeProperty(display, xwin, remoteAtom, remoteAtom, 8,
- PropModeReplace, (Guchar *)"q", 2);
+ app->remoteQuit();
}
goto done2;
}
if (doRemoteQuit) {
- if (destName) {
- delete destName;
- }
goto done2;
}
}
- // no history yet
- historyCur = historySize - 1;
- historyBLen = historyFLen = 0;
- for (i = 0; i < historySize; ++i)
- history[i].fileName = NULL;
-
- // open PDF file
- if (name) {
- if (!loadFile(name)) {
- ret = 1;
- goto done1;
- }
- delete fileReqDir;
- fileReqDir = makePathAbsolute(grabPath(name->getCString()));
- }
-
- // check for legal page number
- if (doc && (pg < 1 || pg > doc->getNumPages())) {
- pg = 1;
- }
-
- // create window
- menu = makeMenu();
- if (fullScreen) {
- zoomMenu = NULL;
- win = makeFullScreenWindow(app);
- win->setDecorated(gFalse);
- } else {
- zoomMenu = makeZoomMenu();
- win = makeWindow(app);
- }
- win->setMenu(menu);
- canvas = (LTKScrollingCanvas *)win->findWidget("canvas");
- hScrollbar = (LTKScrollbar *)win->findWidget("hScrollbar");
- vScrollbar = (LTKScrollbar *)win->findWidget("vScrollbar");
- pageNumText = (LTKTextIn *)win->findWidget("pageNum");
- numPagesLabel = (LTKLabel *)win->findWidget("numPages");
- linkLabel = (LTKLabel *)win->findWidget("link");
- zoomMenuBtn = (LTKMenuButton *)win->findWidget("zoom");
- win->setKeyCbk(&keyPressCbk);
- win->setLayoutCbk(&layoutCbk);
- canvas->setButtonPressCbk(&buttonPressCbk);
- canvas->setButtonReleaseCbk(&buttonReleaseCbk);
- canvas->setMouseMoveCbk(&mouseMoveCbk);
- canvas->setMouseDragCbk(&mouseDragCbk);
- if (!fullScreen) {
- hScrollbar->setRepeatPeriod(0);
- vScrollbar->setRepeatPeriod(0);
- }
-
- // get parameters
- urlCommand = globalParams->getURLCommand();
-
- // get X resources
- windowTitle = app->getStringResource("title", NULL);
- installCmap = app->getBoolResource("installCmap", gFalse);
- if (installCmap) {
- win->setInstallCmap(gTrue);
- }
- rgbCubeSize = app->getIntResource("rgbCubeSize", defaultRGBCube);
- reverseVideo = app->getBoolResource("reverseVideo", gFalse);
- paperColor = app->getColorResource(
- "paperColor",
- reverseVideo ? (char *)"black" : (char *)"white",
- reverseVideo ? BlackPixel(display, app->getScreenNum())
- : WhitePixel(display, app->getScreenNum()),
- NULL);
- if (fullScreen) {
- zoom = zoomPage;
- } else {
- initialZoom = globalParams->getInitialZoom();
- if (!initialZoom->cmp("page")) {
- zoom = zoomPage;
- i = maxZoom - minZoom + 2;
- } else if (!initialZoom->cmp("width")) {
- zoom = zoomWidth;
- i = maxZoom - minZoom + 3;
- } else {
- zoom = atoi(initialZoom->getCString());
- if (zoom < minZoom) {
- zoom = minZoom;
- } else if (zoom > maxZoom) {
- zoom = maxZoom;
- }
- i = zoom - minZoom;
- }
- zoomMenuBtn->setInitialMenuItem(zoomMenu->getItem(i));
- }
- viKeys = app->getBoolResource("viKeys", gFalse);
-
- // get geometry
- if (fullScreen) {
- x = y = 0;
- width = app->getDisplayWidth();
- height = app->getDisplayHeight();
- } else {
- x = y = -1;
- width = height = 0;
- app->getGeometryResource("geometry", &x, &y, &width, &height);
- if (width == 0 || height == 0) {
- if (!doc || doc->getNumPages() == 0) {
- width1 = 612;
- height1 = 792;
- } else if (doc->getPageRotate(pg) == 90 ||
- doc->getPageRotate(pg) == 270) {
- width1 = doc->getPageHeight(pg);
- height1 = doc->getPageWidth(pg);
- } else {
- width1 = doc->getPageWidth(pg);
- height1 = doc->getPageHeight(pg);
- }
- if (zoom == zoomPage || zoom == zoomWidth) {
- width = (int)((width1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
- height = (int)((height1 * zoomDPI[defZoom - minZoom]) / 72 + 0.5);
- } else {
- width = (int)((width1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
- height = (int)((height1 * zoomDPI[zoom - minZoom]) / 72 + 0.5);
- }
- width += 28;
- height += 56;
- if (width > (Guint)app->getDisplayWidth() - 100) {
- width = app->getDisplayWidth() - 100;
- }
- if (height > (Guint)app->getDisplayHeight() - 100) {
- height = app->getDisplayHeight() - 100;
- }
- }
- }
-
- // finish setting up window
- if (!fullScreen) {
- sprintf(s, "of %d", doc ? doc->getNumPages() : 0);
- numPagesLabel->setText(s);
- }
- if (windowTitle) {
- title = windowTitle->copy();
- } else if (name) {
- title = new GString("xpdf: ");
- title->append(name);
- } else {
- title = new GString("xpdf");
- }
- win->setTitle(title);
- win->layout(x, y, width, height);
- win->map();
- aboutWin = NULL;
- psDialog = NULL;
- openDialog = NULL;
- saveDialog = NULL;
- findWin = NULL;
- gcValues.foreground = BlackPixel(display, win->getScreenNum()) ^
- WhitePixel(display, win->getScreenNum());
- gcValues.function = GXxor;
- selectGC = XCreateGC(display, win->getXWindow(),
- GCForeground | GCFunction, &gcValues);
-
- // set up remote server
- if (remoteAtom != None) {
- win->setPropChangeCbk(&propChangeCbk);
- xwin = win->getXWindow();
- XSetSelectionOwner(display, remoteAtom, xwin, CurrentTime);
- }
+ // set options
+ app->setFullScreen(fullScreen);
- // create output device
- out = new LTKOutputDev(win, reverseVideo, paperColor,
- installCmap, rgbCubeSize, !fullScreen);
- out->startDoc(doc ? doc->getXRef() : (XRef *)NULL);
+ // check for password string(s)
+ ownerPasswordStr = ownerPassword[0] ? new GString(ownerPassword)
+ : (GString *)NULL;
+ userPasswordStr = userPassword[0] ? new GString(userPassword)
+ : (GString *)NULL;
- // display first page
+ // open the file and run the main loop
if (destName) {
- if (doc) {
- if ((dest = doc->findDest(destName))) {
- displayDest(dest, zoom, 0, gTrue);
- delete dest;
- } else {
- error(-1, "Unknown named destination '%s'", destName->getCString());
- displayPage(1, zoom, 0, gTrue);
- }
+ if (!app->openAtDest(fileName, destName,
+ ownerPasswordStr, userPasswordStr)) {
+ exitCode = 1;
+ goto done2;
}
- delete destName;
} else {
- displayPage(pg, zoom, 0, gTrue);
+ if (!app->open(fileName, pg, ownerPasswordStr, userPasswordStr)) {
+ exitCode = 1;
+ goto done2;
+ }
}
+ app->run();
- // event loop
- quit = gFalse;
- do {
- app->doEvent(gTrue);
- } while (!quit);
-
- done1:
- // release remote control atom
- if (remoteAtom != None)
- XSetSelectionOwner(display, remoteAtom, None, CurrentTime);
+ exitCode = 0;
+ // clean up
done2:
- // free stuff
- if (out) {
- delete out;
- }
- if (win) {
- delete win;
+ if (userPasswordStr) {
+ delete userPasswordStr;
}
- if (aboutWin) {
- delete aboutWin;
+ if (ownerPasswordStr) {
+ delete ownerPasswordStr;
}
- if (findWin) {
- delete findWin;
- }
- if (app) {
- delete app;
- }
- if (doc) {
- delete doc;
- }
- if (psFileName) {
- delete psFileName;
- }
- if (fileReqDir) {
- delete fileReqDir;
- }
- if (windowTitle) {
- delete windowTitle;
+ if (destName) {
+ delete destName;
}
- for (i = 0; i < historySize; ++i) {
- if (history[i].fileName) {
- delete history[i].fileName;
- }
+ if (fileName) {
+ delete fileName;
}
+ done1:
+ delete app;
delete globalParams;
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
- return ret;
-}
-
-//------------------------------------------------------------------------
-// loadFile / displayPage / displayDest
-//------------------------------------------------------------------------
-
-static GBool loadFile(GString *fileName) {
- GString *title;
- PDFDoc *newDoc;
- GString *ownerPW, *userPW;
- char s[20];
- char *p;
-
- // busy cursor
- if (win)
- win->setBusyCursor(gTrue);
-
- // open PDF file
- if (ownerPassword[0]) {
- ownerPW = new GString(ownerPassword);
- } else {
- ownerPW = NULL;
- }
- if (userPassword[0]) {
- userPW = new GString(userPassword);
- } else {
- userPW = NULL;
- }
- newDoc = new PDFDoc(fileName, ownerPW, userPW, printCommands);
- if (userPW) {
- delete userPW;
- }
- if (ownerPW) {
- delete ownerPW;
- }
- if (!newDoc->isOk()) {
- delete newDoc;
- if (win)
- win->setBusyCursor(gFalse);
- return gFalse;
- }
-
- // replace old document
- if (doc)
- delete doc;
- doc = newDoc;
- if (out) {
- out->startDoc(doc->getXRef());
- }
-
- // nothing displayed yet
- page = -99;
-
- // save the modification time
- modTime = getModTime(fileName->getCString());
-
- // init PostScript output params
- if (psFileName)
- delete psFileName;
- if (globalParams->getPSFile()) {
- psFileName = globalParams->getPSFile()->copy();
- } else {
- p = fileName->getCString() + fileName->getLength() - 4;
- if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
- psFileName = new GString(fileName->getCString(),
- fileName->getLength() - 4);
- else
- psFileName = fileName->copy();
- psFileName->append(".ps");
- }
- psFirstPage = 1;
- psLastPage = doc->getNumPages();
-
- // set up title, number-of-pages display; back to normal cursor
- if (win) {
- if (!windowTitle) {
- title = new GString("xpdf: ");
- title->append(fileName);
- win->setTitle(title);
- }
- if (!fullScreen) {
- sprintf(s, "of %d", doc->getNumPages());
- numPagesLabel->setText(s);
- }
- win->setBusyCursor(gFalse);
- }
-
- // done
- return gTrue;
-}
-
-static void displayPage(int pageA, int zoomA, int rotateA, GBool addToHist) {
- time_t modTime1;
- double hDPI, vDPI, dpi;
- int rot;
- char s[20];
- History *h;
-
- // check for document
- if (!doc || doc->getNumPages() == 0)
- return;
-
- // check for changes to the file
- modTime1 = getModTime(doc->getFileName()->getCString());
- if (modTime1 != modTime) {
- if (loadFile(doc->getFileName()->copy())) {
- if (pageA > doc->getNumPages()) {
- pageA = doc->getNumPages();
- }
- }
- modTime = modTime1;
- }
-
- // busy cursor
- if (win)
- win->setBusyCursor(gTrue);
-
- // new page/zoom/rotate values
- page = pageA;
- zoom = zoomA;
- rotate = rotateA;
-
- // initialize mouse-related stuff
- linkAction = NULL;
- win->setDefaultCursor();
- if (!fullScreen) {
- linkLabel->setText(NULL);
- }
- selectXMin = selectXMax = 0;
- selectYMin = selectYMax = 0;
- lastDragLeft = lastDragTop = gTrue;
-
- // draw the page
- rot = rotate + doc->getPageRotate(page);
- if (rot >= 360)
- rot -= 360;
- else if (rotate < 0)
- rot += 360;
- if (fullScreen) {
- if (rot == 90 || rot == 270) {
- hDPI = (win->getWidth() / doc->getPageHeight(page)) * 72;
- vDPI = (win->getHeight() / doc->getPageWidth(page)) * 72;
- } else {
- hDPI = (win->getWidth() / doc->getPageWidth(page)) * 72;
- vDPI = (win->getHeight() / doc->getPageHeight(page)) * 72;
- }
- dpi = (hDPI < vDPI) ? hDPI : vDPI;
- } else if (zoom == zoomPage) {
- if (rot == 90 || rot == 270) {
- hDPI = (canvas->getWidth() / doc->getPageHeight(page)) * 72;
- vDPI = (canvas->getHeight() / doc->getPageWidth(page)) * 72;
- } else {
- hDPI = (canvas->getWidth() / doc->getPageWidth(page)) * 72;
- vDPI = (canvas->getHeight() / doc->getPageHeight(page)) * 72;
- }
- dpi = (hDPI < vDPI) ? hDPI : vDPI;
- } else if (zoom == zoomWidth) {
- if (rot == 90 || rot == 270) {
- dpi = (canvas->getWidth() / doc->getPageHeight(page)) * 72;
- } else {
- dpi = (canvas->getWidth() / doc->getPageWidth(page)) * 72;
- }
- } else {
- dpi = zoomDPI[zoom - minZoom];
- }
- doc->displayPage(out, page, dpi, rotate, gTrue);
- updateScrollbars();
-
- // update page number display
- if (!fullScreen) {
- sprintf(s, "%d", page);
- pageNumText->setText(s);
- }
-
- // add to history
- if (addToHist) {
- if (++historyCur == historySize)
- historyCur = 0;
- h = &history[historyCur];
- if (h->fileName)
- delete h->fileName;
- h->fileName = doc->getFileName()->copy();
- h->page = page;
- if (historyBLen < historySize)
- ++historyBLen;
- historyFLen = 0;
- }
-
- // back to regular cursor
- win->setBusyCursor(gFalse);
-}
-
-static void displayDest(LinkDest *dest, int zoomA, int rotateA,
- GBool addToHist) {
- Ref pageRef;
- int pg;
- int dx, dy;
-
- if (dest->isPageRef()) {
- pageRef = dest->getPageRef();
- pg = doc->findPage(pageRef.num, pageRef.gen);
- } else {
- pg = dest->getPageNum();
- }
- if (pg <= 0 || pg > doc->getNumPages()) {
- pg = 1;
- }
- if (pg != page) {
- displayPage(pg, zoomA, rotateA, addToHist);
- }
-
- if (fullScreen) {
- return;
- }
- switch (dest->getKind()) {
- case destXYZ:
- out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
- if (dest->getChangeLeft() || dest->getChangeTop()) {
- if (dest->getChangeLeft()) {
- hScrollbar->setPos(dx, canvas->getWidth());
- }
- if (dest->getChangeTop()) {
- vScrollbar->setPos(dy, canvas->getHeight());
- }
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- //~ what is the zoom parameter?
- break;
- case destFit:
- case destFitB:
- //~ do fit
- hScrollbar->setPos(0, canvas->getWidth());
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case destFitH:
- case destFitBH:
- //~ do fit
- out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
- hScrollbar->setPos(0, canvas->getWidth());
- vScrollbar->setPos(dy, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case destFitV:
- case destFitBV:
- //~ do fit
- out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
- hScrollbar->setPos(dx, canvas->getWidth());
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case destFitR:
- //~ do fit
- out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
- hScrollbar->setPos(dx, canvas->getWidth());
- vScrollbar->setPos(dy, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- }
-}
-
-//------------------------------------------------------------------------
-// key press and menu callbacks
-//------------------------------------------------------------------------
-
-static void keyPressCbk(LTKWindow *win1, KeySym key, Guint modifiers,
- char *s, int n) {
- if (n > 0) {
- switch (s[0]) {
- case 'O':
- case 'o':
- mapOpenDialog();
- break;
- case 'R':
- case 'r':
- reloadCbk();
- break;
- case 'F':
- case 'f':
- mapFindWin();
- break;
- case 'N':
- case 'n':
- gotoNextPage(1, !(modifiers & Mod5Mask));
- break;
- case 'P':
- case 'p':
- gotoPrevPage(1, !(modifiers & Mod5Mask), gFalse);
- break;
- case ' ':
- if (fullScreen ||
- vScrollbar->getPos() >=
- canvas->getRealHeight() - canvas->getHeight()) {
- gotoNextPage(1, gTrue);
- } else {
- vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case '\b': // bs
- case '\177': // del
- if (fullScreen) {
- gotoPrevPage(1, gTrue, gFalse);
- } else if (vScrollbar->getPos() == 0) {
- gotoPrevPage(1, gFalse, gTrue);
- } else {
- vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case 'v':
- forwardCbk(NULL, 0, gTrue);
- break;
- case 'b':
- backCbk(NULL, 0, gTrue);
- break;
- case 'g':
- if (fullScreen) {
- break;
- }
- pageNumText->selectAll();
- pageNumText->activate(gTrue);
- break;
- case 'h': // vi-style left
- if (fullScreen) {
- break;
- }
- if (viKeys) {
- hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case 'l': // vi-style right
- if (fullScreen) {
- break;
- }
- if (viKeys) {
- hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case 'k': // vi-style up
- if (fullScreen) {
- break;
- }
- if (viKeys) {
- vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case 'j': // vi-style down
- if (fullScreen) {
- break;
- }
- if (viKeys) {
- vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case '0':
- if (fullScreen) {
- break;
- }
- if (zoom != defZoom) {
- zoomMenuBtn->setMenuItem(zoomMenu->getItem(defZoom - minZoom));
- }
- break;
- case '+':
- if (fullScreen) {
- break;
- }
- if (zoom >= minZoom && zoom < maxZoom) {
- zoomMenuBtn->setMenuItem(zoomMenu->getItem(zoom + 1 - minZoom));
- }
- break;
- case '-':
- if (fullScreen) {
- break;
- }
- if (zoom > minZoom && zoom <= maxZoom) {
- zoomMenuBtn->setMenuItem(zoomMenu->getItem(zoom - 1 - minZoom));
- }
- break;
- case 'z':
- if (fullScreen) {
- break;
- }
- zoomMenuBtn->setMenuItem(zoomMenu->getItem(maxZoom - minZoom + 2));
- break;
- case 'w':
- if (fullScreen) {
- break;
- }
- zoomMenuBtn->setMenuItem(zoomMenu->getItem(maxZoom - minZoom + 3));
- break;
- case '\014': // ^L
- win->redraw();
- displayPage(page, zoom, rotate, gFalse);
- break;
- case 'Q':
- case 'q':
- quitCbk(NULL, 0, gTrue);
- break;
- }
- } else {
- switch (key) {
- case XK_Home:
- case XK_KP_Home:
- if (fullScreen) {
- break;
- }
- hScrollbar->setPos(0, canvas->getWidth());
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case XK_End:
- case XK_KP_End:
- if (fullScreen) {
- break;
- }
- hScrollbar->setPos(canvas->getRealWidth() - canvas->getWidth(),
- canvas->getWidth());
- vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case XK_Page_Up:
- case XK_KP_Page_Up:
- if (fullScreen) {
- gotoPrevPage(1, gTrue, gFalse);
- } else if (vScrollbar->getPos() == 0) {
- gotoPrevPage(1, gFalse, gTrue);
- } else {
- vScrollbar->setPos(vScrollbar->getPos() - canvas->getHeight(),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case XK_Page_Down:
- case XK_KP_Page_Down:
- if (fullScreen ||
- vScrollbar->getPos() >=
- canvas->getRealHeight() - canvas->getHeight()) {
- gotoNextPage(1, gTrue);
- } else {
- vScrollbar->setPos(vScrollbar->getPos() + canvas->getHeight(),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case XK_Left:
- case XK_KP_Left:
- if (fullScreen) {
- break;
- }
- hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case XK_Right:
- case XK_KP_Right:
- if (fullScreen) {
- break;
- }
- hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case XK_Up:
- case XK_KP_Up:
- if (fullScreen) {
- break;
- }
- vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case XK_Down:
- case XK_KP_Down:
- if (fullScreen) {
- break;
- }
- vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- }
- }
-}
-
-static void menuCbk(LTKMenuItem *item) {
- int r;
-
- switch (item->getItemNum()) {
- case menuOpen:
- mapOpenDialog();
- break;
- case menuReload:
- reloadCbk();
- break;
- case menuSavePDF:
- if (doc)
- mapSaveDialog();
- break;
- case menuRotateCCW:
- if (doc) {
- r = (rotate == 0) ? 270 : rotate - 90;
- displayPage(page, zoom, r, gFalse);
- }
- break;
- case menuRotateCW:
- if (doc) {
- r = (rotate == 270) ? 0 : rotate + 90;
- displayPage(page, zoom, r, gFalse);
- }
- break;
- case menuQuit:
- quit = gTrue;
- break;
- }
-}
-
-//------------------------------------------------------------------------
-// mouse callbacks
-//------------------------------------------------------------------------
-
-static void buttonPressCbk(LTKWidget *canvas1, int n,
- int mx, int my, int button, GBool dblClick) {
- if (!doc || doc->getNumPages() == 0) {
- return;
- }
- switch (button) {
- case 1:
- setSelection(mx, my, mx, my);
- break;
- case 2:
- if (!fullScreen) {
- panMX = mx - hScrollbar->getPos();
- panMY = my - vScrollbar->getPos();
- }
- break;
- case 4: // mouse wheel up
- if (fullScreen) {
- gotoPrevPage(1, gTrue, gFalse);
- } else if (vScrollbar->getPos() == 0) {
- gotoPrevPage(1, gFalse, gTrue);
- } else {
- vScrollbar->setPos(vScrollbar->getPos() - 16, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case 5: // mouse wheel down
- if (fullScreen ||
- vScrollbar->getPos() >=
- canvas->getRealHeight() - canvas->getHeight()) {
- gotoNextPage(1, gTrue);
- } else {
- vScrollbar->setPos(vScrollbar->getPos() + 16, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- break;
- case 6: // second mouse wheel right
- if (fullScreen) {
- return;
- }
- hScrollbar->setPos(hScrollbar->getPos() + 16, canvas->getWidth());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- case 7: // second mouse wheel left
- if (fullScreen) {
- return;
- }
- hScrollbar->setPos(hScrollbar->getPos() - 16, canvas->getWidth());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- break;
- }
-}
-
-static void buttonReleaseCbk(LTKWidget *canvas1, int n,
- int mx, int my, int button, GBool click) {
- GString *s;
-
- if (!doc || doc->getNumPages() == 0)
- return;
-
- if (button == 1) {
- // selection
- if (selectXMin < selectXMax && selectYMin < selectYMax) {
-#ifndef NO_TEXT_SELECT
- if (doc->okToCopy()) {
- s = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
- win->setSelection(NULL, s);
- } else {
- error(-1, "Copying of text from this document is not allowed.");
- }
-#endif
-
- // link
- } else {
- setSelection(mx, my, mx, my);
- doLink(mx, my);
- }
- }
-}
-
-static void doLink(int mx, int my) {
- LinkActionKind kind;
- LinkAction *action = NULL;
- LinkDest *dest;
- GString *namedDest;
- char *s;
- GString *fileName;
- GString *actionName;
- double x, y;
- LTKButtonDialog *dialog;
- int i;
-
- // look for a link
- out->cvtDevToUser(mx, my, &x, &y);
- if ((action = doc->findLink(x, y))) {
- switch (kind = action->getKind()) {
-
- // GoTo / GoToR action
- case actionGoTo:
- case actionGoToR:
- if (kind == actionGoTo) {
- dest = NULL;
- namedDest = NULL;
- if ((dest = ((LinkGoTo *)action)->getDest()))
- dest = dest->copy();
- else if ((namedDest = ((LinkGoTo *)action)->getNamedDest()))
- namedDest = namedDest->copy();
- } else {
- dest = NULL;
- namedDest = NULL;
- if ((dest = ((LinkGoToR *)action)->getDest()))
- dest = dest->copy();
- else if ((namedDest = ((LinkGoToR *)action)->getNamedDest()))
- namedDest = namedDest->copy();
- s = ((LinkGoToR *)action)->getFileName()->getCString();
- //~ translate path name for VMS (deal with '/')
- if (isAbsolutePath(s))
- fileName = new GString(s);
- else
- fileName = appendToPath(
- grabPath(doc->getFileName()->getCString()), s);
- if (!loadFile(fileName)) {
- if (dest)
- delete dest;
- if (namedDest)
- delete namedDest;
- return;
- }
- }
- if (namedDest) {
- dest = doc->findDest(namedDest);
- delete namedDest;
- }
- if (dest) {
- displayDest(dest, zoom, rotate, gTrue);
- delete dest;
- } else {
- if (kind == actionGoToR) {
- displayPage(1, zoom, 0, gTrue);
- }
- }
- break;
-
- // Launch action
- case actionLaunch:
- fileName = ((LinkLaunch *)action)->getFileName();
- s = fileName->getCString();
- if (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
- !strcmp(s + fileName->getLength() - 4, ".PDF")) {
- //~ translate path name for VMS (deal with '/')
- if (isAbsolutePath(s))
- fileName = fileName->copy();
- else
- fileName = appendToPath(
- grabPath(doc->getFileName()->getCString()), s);
- if (!loadFile(fileName))
- return;
- displayPage(1, zoom, rotate, gTrue);
- } else {
- fileName = fileName->copy();
- if (((LinkLaunch *)action)->getParams()) {
- fileName->append(' ');
- fileName->append(((LinkLaunch *)action)->getParams());
- }
-#ifdef VMS
- fileName->insert(0, "spawn/nowait ");
-#elif defined(__EMX__)
- fileName->insert(0, "start /min /n ");
-#else
- fileName->append(" &");
-#endif
- dialog = new LTKButtonDialog(win, "xpdf: Launch",
- "Execute the command:",
- fileName->getCString(),
- NULL, "Ok", "Cancel");
- if (dialog->go())
- system(fileName->getCString());
- delete dialog;
- delete fileName;
- }
- break;
-
- // URI action
- case actionURI:
- if (urlCommand) {
- for (s = urlCommand->getCString(); *s; ++s) {
- if (s[0] == '%' && s[1] == 's') {
- break;
- }
- }
- if (s) {
- fileName = ((LinkURI *)action)->getURI()->copy();
- // filter out any quote marks (' or ") to avoid a potential
- // security hole
- i = 0;
- while (i < fileName->getLength()) {
- if (fileName->getChar(i) == '"') {
- fileName->del(i);
- fileName->insert(i, "%22");
- i += 3;
- } else if (fileName->getChar(i) == '\'') {
- fileName->del(i);
- fileName->insert(i, "%27");
- i += 3;
- } else {
- ++i;
- }
- }
- fileName->insert(0, urlCommand->getCString(),
- s - urlCommand->getCString());
- fileName->append(s+2);
- } else {
- fileName = urlCommand->copy();
- }
-#ifdef VMS
- fileName->insert(0, "spawn/nowait ");
-#elif defined(__EMX__)
- fileName->insert(0, "start /min /n ");
-#else
- fileName->append(" &");
-#endif
- system(fileName->getCString());
- delete fileName;
- } else {
- printf("URI: %s\n", ((LinkURI *)action)->getURI()->getCString());
- }
- break;
-
- // Named action
- case actionNamed:
- actionName = ((LinkNamed *)action)->getName();
- if (!actionName->cmp("NextPage")) {
- gotoNextPage(1, gTrue);
- } else if (!actionName->cmp("PrevPage")) {
- gotoPrevPage(1, gTrue, gFalse);
- } else if (!actionName->cmp("FirstPage")) {
- if (page != 1) {
- displayPage(1, zoom, rotate, gTrue);
- }
- } else if (!actionName->cmp("LastPage")) {
- if (page != doc->getNumPages()) {
- displayPage(doc->getNumPages(), zoom, rotate, gTrue);
- }
- } else if (!actionName->cmp("GoBack")) {
- backCbk(NULL, 0, gTrue);
- } else if (!actionName->cmp("GoForward")) {
- forwardCbk(NULL, 0, gTrue);
- } else if (!actionName->cmp("Quit")) {
- quitCbk(NULL, 0, gTrue);
- } else {
- error(-1, "Unknown named action: '%s'", actionName->getCString());
- }
- break;
-
- // unknown action type
- case actionUnknown:
- error(-1, "Unknown link action type: '%s'",
- ((LinkUnknown *)action)->getAction()->getCString());
- break;
- }
- }
-}
-
-static void mouseMoveCbk(LTKWidget *widget, int widgetNum, int mx, int my) {
- double x, y;
- LinkAction *action;
- char *s;
-
- if (!doc || doc->getNumPages() == 0)
- return;
- out->cvtDevToUser(mx, my, &x, &y);
- if ((action = doc->findLink(x, y))) {
- if (action != linkAction) {
- if (!linkAction) {
- win->setCursor(XC_hand2);
- }
- linkAction = action;
- if (!fullScreen) {
- s = NULL;
- switch (linkAction->getKind()) {
- case actionGoTo:
- s = "[internal link]";
- break;
- case actionGoToR:
- s = ((LinkGoToR *)linkAction)->getFileName()->getCString();
- break;
- case actionLaunch:
- s = ((LinkLaunch *)linkAction)->getFileName()->getCString();
- break;
- case actionURI:
- s = ((LinkURI *)action)->getURI()->getCString();
- break;
- case actionNamed:
- s = ((LinkNamed *)linkAction)->getName()->getCString();
- break;
- case actionUnknown:
- s = "[unknown link]";
- break;
- }
- linkLabel->setText(s);
- }
- }
- } else {
- if (linkAction) {
- linkAction = NULL;
- win->setDefaultCursor();
- if (!fullScreen) {
- linkLabel->setText(NULL);
- }
- }
- }
-}
-
-static void mouseDragCbk(LTKWidget *widget, int widgetNum,
- int mx, int my, int button) {
- int x, y;
- int xMin, yMin, xMax, yMax;
-
- // button 1: select
- if (button == 1) {
-
- // clip mouse coords
- x = mx;
- if (x < 0)
- x = 0;
- else if (x >= canvas->getRealWidth())
- x = canvas->getRealWidth() - 1;
- y = my;
- if (y < 0)
- y = 0;
- else if (y >= canvas->getRealHeight())
- y = canvas->getRealHeight() - 1;
-
- // move appropriate edges of selection
- if (lastDragLeft) {
- if (x < selectXMax) {
- xMin = x;
- xMax = selectXMax;
- } else {
- xMin = selectXMax;
- xMax = x;
- lastDragLeft = gFalse;
- }
- } else {
- if (x > selectXMin) {
- xMin = selectXMin;
- xMax = x;
- } else {
- xMin = x;
- xMax = selectXMin;
- lastDragLeft = gTrue;
- }
- }
- if (lastDragTop) {
- if (y < selectYMax) {
- yMin = y;
- yMax = selectYMax;
- } else {
- yMin = selectYMax;
- yMax = y;
- lastDragTop = gFalse;
- }
- } else {
- if (y > selectYMin) {
- yMin = selectYMin;
- yMax = y;
- } else {
- yMin = y;
- yMax = selectYMin;
- lastDragTop = gTrue;
- }
- }
-
- // redraw the selection
- setSelection(xMin, yMin, xMax, yMax);
-
- // button 2: pan
- } else if (!fullScreen && button == 2) {
- mx -= hScrollbar->getPos();
- my -= vScrollbar->getPos();
- hScrollbar->setPos(hScrollbar->getPos() - (mx - panMX),
- canvas->getWidth());
- vScrollbar->setPos(vScrollbar->getPos() - (my - panMY),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- panMX = mx;
- panMY = my;
- }
-}
-
-//------------------------------------------------------------------------
-// button callbacks
-//------------------------------------------------------------------------
-
-static void nextPageCbk(LTKWidget *button, int n, GBool on) {
- gotoNextPage(1, gTrue);
-}
-
-static void nextTenPageCbk(LTKWidget *button, int n, GBool on) {
- gotoNextPage(10, gTrue);
-}
-
-static void gotoNextPage(int inc, GBool top) {
- int pg;
-
- if (!doc || doc->getNumPages() == 0) {
- return;
- }
- if (page < doc->getNumPages()) {
- if (top && !fullScreen) {
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->setScrollPos(hScrollbar->getPos(), vScrollbar->getPos());
- }
- if ((pg = page + inc) > doc->getNumPages()) {
- pg = doc->getNumPages();
- }
- displayPage(pg, zoom, rotate, gTrue);
- } else {
- XBell(display, 0);
- }
-}
-
-static void prevPageCbk(LTKWidget *button, int n, GBool on) {
- gotoPrevPage(1, gTrue, gFalse);
-}
-
-static void prevTenPageCbk(LTKWidget *button, int n, GBool on) {
- gotoPrevPage(10, gTrue, gFalse);
-}
-
-static void gotoPrevPage(int dec, GBool top, GBool bottom) {
- int pg;
-
- if (!doc || doc->getNumPages() == 0) {
- return;
- }
- if (page > 1) {
- if (top && !fullScreen) {
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->setScrollPos(hScrollbar->getPos(), vScrollbar->getPos());
- } else if (bottom && !fullScreen) {
- vScrollbar->setPos(canvas->getRealHeight() - canvas->getHeight(),
- canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- if ((pg = page - dec) < 1) {
- pg = 1;
- }
- displayPage(pg, zoom, rotate, gTrue);
- } else {
- XBell(display, 0);
- }
-}
-
-static void backCbk(LTKWidget *button, int n, GBool on) {
- if (historyBLen <= 1) {
- XBell(display, 0);
- return;
- }
- if (--historyCur < 0)
- historyCur = historySize - 1;
- --historyBLen;
- ++historyFLen;
- if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
- if (!loadFile(history[historyCur].fileName->copy())) {
- XBell(display, 0);
- return;
- }
- }
- displayPage(history[historyCur].page, zoom, rotate, gFalse);
-}
-
-static void forwardCbk(LTKWidget *button, int n, GBool on) {
- if (historyFLen == 0) {
- XBell(display, 0);
- return;
- }
- if (++historyCur == historySize)
- historyCur = 0;
- --historyFLen;
- ++historyBLen;
- if (history[historyCur].fileName->cmp(doc->getFileName()) != 0) {
- if (!loadFile(history[historyCur].fileName->copy())) {
- XBell(display, 0);
- return;
- }
- }
- displayPage(history[historyCur].page, zoom, rotate, gFalse);
-}
-
-static void pageNumCbk(LTKWidget *textIn, int n, GString *text) {
- int page1;
- char s[20];
-
- if (!doc || doc->getNumPages() == 0)
- return;
- page1 = atoi(text->getCString());
- if (page1 >= 1 && page1 <= doc->getNumPages()) {
- if (page1 != page)
- displayPage(page1, zoom, rotate, gTrue);
- } else {
- XBell(display, 0);
- sprintf(s, "%d", page);
- pageNumText->setText(s);
- }
-}
-
-static void zoomMenuCbk(LTKMenuItem *item) {
- int z;
-
- if (!doc || doc->getNumPages() == 0) {
- return;
- }
- z = item->getItemNum();
- if (z != zoom) {
- displayPage(page, z, rotate, gFalse);
- }
-}
-
-static void postScriptCbk(LTKWidget *button, int n, GBool on) {
- if (!doc)
- return;
- mapPSDialog();
-}
-
-static void aboutCbk(LTKWidget *button, int n, GBool on) {
- mapAboutWin();
-}
-
-static void quitCbk(LTKWidget *button, int n, GBool on) {
- quit = gTrue;
-}
-
-//------------------------------------------------------------------------
-// scrollbar callbacks
-//------------------------------------------------------------------------
-
-static void scrollVertCbk(LTKWidget *scrollbar, int n, int val) {
- canvas->scroll(hScrollbar->getPos(), val);
- XSync(display, False);
-}
-
-static void scrollHorizCbk(LTKWidget *scrollbar, int n, int val) {
- canvas->scroll(val, vScrollbar->getPos());
- XSync(display, False);
-}
-
-//------------------------------------------------------------------------
-// misc callbacks
-//------------------------------------------------------------------------
-
-static void layoutCbk(LTKWindow *win1) {
- if (page >= 0 && (zoom == zoomPage || zoom == zoomWidth)) {
- displayPage(page, zoom, rotate, gFalse);
- } else {
- updateScrollbars();
- }
-}
-
-static void updateScrollbars() {
- if (fullScreen) {
- return;
- }
- hScrollbar->setLimits(0, canvas->getRealWidth() - 1);
- hScrollbar->setPos(hScrollbar->getPos(), canvas->getWidth());
- hScrollbar->setScrollDelta(16);
- vScrollbar->setLimits(0, canvas->getRealHeight() - 1);
- vScrollbar->setPos(vScrollbar->getPos(), canvas->getHeight());
- vScrollbar->setScrollDelta(16);
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
-}
-
-static void propChangeCbk(LTKWindow *win1, Atom atom) {
- Window xwin;
- char *cmd;
- Atom type;
- int format;
- Gulong size, remain;
- char *p, *q;
- GString *newFileName;
- int newPage;
- GString *destName;
- LinkDest *dest;
-
- // get command
- xwin = win1->getXWindow();
- if (XGetWindowProperty(display, xwin, remoteAtom,
- 0, remoteCmdLength/4, True, remoteAtom,
- &type, &format, &size, &remain,
- (Guchar **)&cmd) != Success) {
- return;
- }
- if (size == 0) {
- return;
- }
-
- // raise window
- if (cmd[0] == 'D' || cmd[0] == 'r'){
- win->raise();
- XFlush(display);
- }
-
- // display file / page
- if (cmd[0] == 'd' || cmd[0] == 'D') {
- p = cmd + 2;
- q = strchr(p, ' ');
- if (!q) {
- return;
- }
- *q++ = '\0';
- newPage = 1;
- destName = NULL;
- if (*p == '+') {
- destName = new GString(p + 1);
- } else {
- newPage = atoi(p);
- }
- if (!q) {
- return;
- }
- newFileName = new GString(q);
- XFree((XPointer)cmd);
- if (!doc || newFileName->cmp(doc->getFileName())) {
- if (!loadFile(newFileName))
- return;
- } else {
- delete newFileName;
- }
- if (destName) {
- if ((dest = doc->findDest(destName))) {
- displayDest(dest, zoom, rotate, gTrue);
- delete dest;
- }
- delete destName;
- } else if (newPage != page &&
- newPage >= 1 && newPage <= doc->getNumPages()) {
- displayPage(newPage, zoom, rotate, gTrue);
- }
-
- // quit
- } else if (cmd[0] == 'q') {
- quit = gTrue;
- }
-}
-
-//------------------------------------------------------------------------
-// selection
-//------------------------------------------------------------------------
-
-static void setSelection(int newXMin, int newYMin, int newXMax, int newYMax) {
- int x, y, w, h;
- GBool needRedraw, needScroll;
- GBool moveLeft, moveRight, moveTop, moveBottom;
-
- // erase old selection on canvas pixmap
- needRedraw = gFalse;
- if (selectXMin < selectXMax && selectYMin < selectYMax) {
- XFillRectangle(canvas->getDisplay(), canvas->getPixmap(),
- selectGC, selectXMin, selectYMin,
- selectXMax - selectXMin, selectYMax - selectYMin);
- needRedraw = gTrue;
- }
-
- // draw new selection on canvas pixmap
- if (newXMin < newXMax && newYMin < newYMax) {
- XFillRectangle(canvas->getDisplay(), canvas->getPixmap(),
- selectGC, newXMin, newYMin,
- newXMax - newXMin, newYMax - newYMin);
- needRedraw = gTrue;
- }
-
- // check which edges moved
- moveLeft = newXMin != selectXMin;
- moveTop = newYMin != selectYMin;
- moveRight = newXMax != selectXMax;
- moveBottom = newYMax != selectYMax;
-
- // redraw currently visible part of canvas
- if (needRedraw) {
- if (moveLeft) {
- canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
- (newYMin < selectYMin) ? newYMin : selectYMin,
- (newXMin > selectXMin) ? newXMin : selectXMin,
- (newYMax > selectYMax) ? newYMax : selectYMax);
- }
- if (moveRight) {
- canvas->redrawRect((newXMax < selectXMax) ? newXMax : selectXMax,
- (newYMin < selectYMin) ? newYMin : selectYMin,
- (newXMax > selectXMax) ? newXMax : selectXMax,
- (newYMax > selectYMax) ? newYMax : selectYMax);
- }
- if (moveTop) {
- canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
- (newYMin < selectYMin) ? newYMin : selectYMin,
- (newXMax > selectXMax) ? newXMax : selectXMax,
- (newYMin > selectYMin) ? newYMin : selectYMin);
- }
- if (moveBottom) {
- canvas->redrawRect((newXMin < selectXMin) ? newXMin : selectXMin,
- (newYMax < selectYMax) ? newYMax : selectYMax,
- (newXMax > selectXMax) ? newXMax : selectXMax,
- (newYMax > selectYMax) ? newYMax : selectYMax);
- }
- }
-
- // switch to new selection coords
- selectXMin = newXMin;
- selectXMax = newXMax;
- selectYMin = newYMin;
- selectYMax = newYMax;
-
- // scroll canvas if necessary
- if (fullScreen) {
- return;
- }
- needScroll = gFalse;
- w = canvas->getWidth();
- h = canvas->getHeight();
- x = hScrollbar->getPos();
- y = vScrollbar->getPos();
- if (moveLeft && selectXMin < x) {
- x = selectXMin;
- needScroll = gTrue;
- } else if (moveRight && selectXMax >= x + w) {
- x = selectXMax - w;
- needScroll = gTrue;
- } else if (moveLeft && selectXMin >= x + w) {
- x = selectXMin - w;
- needScroll = gTrue;
- } else if (moveRight && selectXMax < x) {
- x = selectXMax;
- needScroll = gTrue;
- }
- if (moveTop && selectYMin < y) {
- y = selectYMin;
- needScroll = gTrue;
- } else if (moveBottom && selectYMax >= y + h) {
- y = selectYMax - h;
- needScroll = gTrue;
- } else if (moveTop && selectYMin >= y + h) {
- y = selectYMin - h;
- needScroll = gTrue;
- } else if (moveBottom && selectYMax < y) {
- y = selectYMax;
- needScroll = gTrue;
- }
- if (needScroll) {
- hScrollbar->setPos(x, w);
- vScrollbar->setPos(y, h);
- canvas->scroll(x, y);
- }
-}
-
-//------------------------------------------------------------------------
-// "Open" dialog
-//------------------------------------------------------------------------
-
-static void mapOpenDialog() {
- openDialog = makeOpenDialog(app);
- ((LTKFileReq *)openDialog->findWidget("fileReq"))->setDir(fileReqDir);
- openDialog->layoutDialog(win, -1, -1);
- openDialog->map();
-}
-
-static void openButtonCbk(LTKWidget *button, int n, GBool on) {
- LTKFileReq *fileReq;
- GString *sel;
-
- sel = NULL;
- if (n == 1) {
- fileReq = (LTKFileReq *)openDialog->findWidget("fileReq");
- if (!(sel = fileReq->getSelection())) {
- return;
- }
- openSelectCbk(fileReq, 0, sel);
- }
- if (openDialog) {
- if (sel) {
- delete fileReqDir;
- fileReqDir = ((LTKFileReq *)openDialog->findWidget("fileReq"))->getDir();
- }
- delete openDialog;
- openDialog = NULL;
- }
-}
-
-static void openSelectCbk(LTKWidget *widget, int n, GString *name) {
- GString *name1;
-
- name1 = name->copy();
- if (openDialog) {
- delete fileReqDir;
- fileReqDir = ((LTKFileReq *)openDialog->findWidget("fileReq"))->getDir();
- delete openDialog;
- openDialog = NULL;
- }
- if (loadFile(name1)) {
- if (!fullScreen) {
- vScrollbar->setPos(0, canvas->getHeight());
- canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
- }
- displayPage(1, zoom, rotate, gTrue);
- }
-}
-
-//------------------------------------------------------------------------
-// "Reload"
-//------------------------------------------------------------------------
-
-static void reloadCbk() {
- int pg;
-
- if (!doc) {
- return;
- }
- pg = page;
- if (loadFile(doc->getFileName()->copy())) {
- if (pg > doc->getNumPages()) {
- pg = doc->getNumPages();
- }
- displayPage(pg, zoom, rotate, gFalse);
- }
-}
-
-//------------------------------------------------------------------------
-// "Save PDF" dialog
-//------------------------------------------------------------------------
-
-static void mapSaveDialog() {
- saveDialog = makeSaveDialog(app);
- ((LTKFileReq *)saveDialog->findWidget("fileReq"))->setDir(fileReqDir);
- saveDialog->layoutDialog(win, -1, -1);
- saveDialog->map();
-}
-
-static void saveButtonCbk(LTKWidget *button, int n, GBool on) {
- LTKFileReq *fileReq;
- GString *sel;
-
- if (!doc)
- return;
- sel = NULL;
- if (n == 1) {
- fileReq = (LTKFileReq *)saveDialog->findWidget("fileReq");
- if (!(sel = fileReq->getSelection())) {
- return;
- }
- saveSelectCbk(fileReq, 0, sel);
- }
- if (saveDialog) {
- if (sel) {
- delete fileReqDir;
- fileReqDir = ((LTKFileReq *)saveDialog->findWidget("fileReq"))->getDir();
- }
- delete saveDialog;
- saveDialog = NULL;
- }
-}
-
-static void saveSelectCbk(LTKWidget *widget, int n, GString *name) {
- GString *name1;
-
- name1 = name->copy();
- if (saveDialog) {
- delete fileReqDir;
- fileReqDir = ((LTKFileReq *)saveDialog->findWidget("fileReq"))->getDir();
- delete saveDialog;
- saveDialog = NULL;
- }
- win->setBusyCursor(gTrue);
- doc->saveAs(name1);
- delete name1;
- win->setBusyCursor(gFalse);
-}
-
-//------------------------------------------------------------------------
-// "PostScript" dialog
-//------------------------------------------------------------------------
-
-static void mapPSDialog() {
- LTKTextIn *widget;
- char s[20];
-
- psDialog = makePostScriptDialog(app);
- sprintf(s, "%d", psFirstPage);
- widget = (LTKTextIn *)psDialog->findWidget("firstPage");
- widget->setText(s);
- sprintf(s, "%d", psLastPage);
- widget = (LTKTextIn *)psDialog->findWidget("lastPage");
- widget->setText(s);
- widget = (LTKTextIn *)psDialog->findWidget("fileName");
- widget->setText(psFileName->getCString());
- psDialog->layoutDialog(win, -1, -1);
- psDialog->map();
-}
-
-static void psButtonCbk(LTKWidget *button, int n, GBool on) {
- PSOutputDev *psOut;
- LTKTextIn *widget;
-
- if (!doc)
- return;
-
- // "Ok" button
- if (n == 1) {
- // extract params and close the dialog
- widget = (LTKTextIn *)psDialog->findWidget("firstPage");
- psFirstPage = atoi(widget->getText()->getCString());
- if (psFirstPage < 1)
- psFirstPage = 1;
- widget = (LTKTextIn *)psDialog->findWidget("lastPage");
- psLastPage = atoi(widget->getText()->getCString());
- if (psLastPage < psFirstPage)
- psLastPage = psFirstPage;
- else if (psLastPage > doc->getNumPages())
- psLastPage = doc->getNumPages();
- widget = (LTKTextIn *)psDialog->findWidget("fileName");
- if (psFileName)
- delete psFileName;
- psFileName = widget->getText()->copy();
- if (!(psFileName->getChar(0) == '|' ||
- psFileName->cmp("-") == 0))
- makePathAbsolute(psFileName);
-
- // do the PostScript output
- psDialog->setBusyCursor(gTrue);
- win->setBusyCursor(gTrue);
- if (doc->okToPrint()) {
- psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
- doc->getCatalog(), psFirstPage, psLastPage,
- psModePS);
- if (psOut->isOk()) {
- doc->displayPages(psOut, psFirstPage, psLastPage, 72, 0, gFalse);
- }
- delete psOut;
- } else {
- error(-1, "Printing this document is not allowed.");
- }
-
- delete psDialog;
- win->setBusyCursor(gFalse);
-
- // "Cancel" button
- } else {
- delete psDialog;
- }
-}
-
-//------------------------------------------------------------------------
-// "About" window
-//------------------------------------------------------------------------
-
-static void mapAboutWin() {
- int i;
-
- if (aboutWin) {
- aboutWin->raise();
- } else {
- aboutWin = makeAboutWindow(app);
- aboutWin->setLayoutCbk(&aboutLayoutCbk);
- aboutList = (LTKList *)aboutWin->findWidget("list");
- aboutHScrollbar = (LTKScrollbar *)aboutWin->findWidget("hScrollbar");
- aboutVScrollbar = (LTKScrollbar *)aboutWin->findWidget("vScrollbar");
- for (i = 0; aboutWinText[i]; ++i) {
- aboutList->addLine(aboutWinText[i]);
- }
- aboutWin->layout(-1, -1, -1, -1);
- aboutWin->map();
- }
-}
-
-static void closeAboutCbk(LTKWidget *button, int n, GBool on) {
- delete aboutWin;
- aboutWin = NULL;
-}
-
-static void aboutLayoutCbk(LTKWindow *winA) {
- aboutHScrollbar->setLimits(0, aboutList->getMaxWidth() - 1);
- aboutHScrollbar->setPos(aboutHScrollbar->getPos(), aboutList->getWidth());
- aboutVScrollbar->setLimits(0, aboutList->getNumLines() - 1);
- aboutVScrollbar->setPos(aboutVScrollbar->getPos(),
- aboutList->getDisplayedLines());
-}
-
-static void aboutScrollVertCbk(LTKWidget *scrollbar, int n, int val) {
- aboutList->scrollTo(val, aboutHScrollbar->getPos());
- XSync(display, False);
-}
-
-static void aboutScrollHorizCbk(LTKWidget *scrollbar, int n, int val) {
- aboutList->scrollTo(aboutVScrollbar->getPos(), val);
- XSync(display, False);
-}
-
-//------------------------------------------------------------------------
-// "Find" window
-//------------------------------------------------------------------------
-
-static void findCbk(LTKWidget *button, int n, GBool on) {
- if (!doc || doc->getNumPages() == 0)
- return;
- mapFindWin();
-}
-
-static void mapFindWin() {
- if (findWin) {
- findWin->raise();
- } else {
- findWin = makeFindWindow(app);
- findWin->layout(-1, -1, -1, -1);
- findWin->map();
- findTextIn = (LTKTextIn *)findWin->findWidget("text");
- }
- findTextIn->activate(gTrue);
-}
-
-static void findButtonCbk(LTKWidget *button, int n, GBool on) {
- if (!doc || doc->getNumPages() == 0)
- return;
- if (n == 1) {
- doFind(findTextIn->getText()->getCString());
- } else {
- delete findWin;
- findWin = NULL;
- }
-}
-
-static void doFind(char *s) {
- Unicode *u;
- TextOutputDev *textOut;
- int xMin, yMin, xMax, yMax;
- double xMin1, yMin1, xMax1, yMax1;
- int pg;
- GBool top;
- GString *s1;
- int len, i;
-
- // check for zero-length string
- if (!s[0]) {
- XBell(display, 0);
- return;
- }
-
- // set cursors to watch
- win->setBusyCursor(gTrue);
- findWin->setBusyCursor(gTrue);
-
- // convert to Unicode
-#if 1 //~ should do something more intelligent here
- len = strlen(s);
- u = (Unicode *)gmalloc(len * sizeof(Unicode));
- for (i = 0; i < len; ++i) {
- u[i] = (Unicode)(s[i] & 0xff);
- }
-#endif
-
- // search current page starting at current selection or top of page
- xMin = yMin = xMax = yMax = 0;
- if (selectXMin < selectXMax && selectYMin < selectYMax) {
- xMin = selectXMax;
- yMin = (selectYMin + selectYMax) / 2;
- top = gFalse;
- } else {
- top = gTrue;
- }
- if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) {
- goto found;
- }
-
- // search following pages
- textOut = new TextOutputDev(NULL, gFalse, gFalse);
- if (!textOut->isOk()) {
- delete textOut;
- goto done;
- }
- for (pg = page+1; pg <= doc->getNumPages(); ++pg) {
- doc->displayPage(textOut, pg, 72, 0, gFalse);
- if (textOut->findText(u, len, gTrue, gTrue,
- &xMin1, &yMin1, &xMax1, &yMax1)) {
- goto foundPage;
- }
- }
-
- // search previous pages
- for (pg = 1; pg < page; ++pg) {
- doc->displayPage(textOut, pg, 72, 0, gFalse);
- if (textOut->findText(u, len, gTrue, gTrue,
- &xMin1, &yMin1, &xMax1, &yMax1)) {
- goto foundPage;
- }
- }
- delete textOut;
-
- // search current page ending at current selection
- if (selectXMin < selectXMax && selectYMin < selectYMax) {
- xMax = selectXMin;
- yMax = (selectYMin + selectYMax) / 2;
- if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) {
- goto found;
- }
- }
-
- // not found
- XBell(display, 0);
- goto done;
-
- // found on a different page
- foundPage:
- delete textOut;
- displayPage(pg, zoom, rotate, gTrue);
- if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) {
- // this can happen if coalescing is bad
- goto done;
- }
-
- // found: change the selection
- found:
- setSelection(xMin, yMin, xMax, yMax);
-#ifndef NO_TEXT_SELECT
- if (doc->okToCopy()) {
- s1 = out->getText(selectXMin, selectYMin, selectXMax, selectYMax);
- win->setSelection(NULL, s1);
- }
-#endif
-
- done:
- gfree(u);
-
- // reset cursors to normal
- win->setBusyCursor(gFalse);
- findWin->setBusyCursor(gFalse);
-}
-
-//------------------------------------------------------------------------
-// app kill callback
-//------------------------------------------------------------------------
-
-static void killCbk(LTKWindow *win1) {
- if (win1 == win) {
- quit = gTrue;
- } else if (win1 == aboutWin) {
- delete aboutWin;
- aboutWin = NULL;
- } else if (win1 == psDialog) {
- delete psDialog;
- psDialog = NULL;
- } else if (win1 == openDialog) {
- delete openDialog;
- openDialog = NULL;
- } else if (win1 == saveDialog) {
- delete saveDialog;
- saveDialog = NULL;
- } else if (win1 == findWin) {
- delete findWin;
- findWin = NULL;
- }
+ return exitCode;
}
+++ /dev/null
-#========================================================================
-#
-# xpdf.ltk
-#
-# Copyright 1996-2002 Glyph & Cog, LLC
-#
-#========================================================================
-
-#------------------------------------------------------------------------
-# main window
-#------------------------------------------------------------------------
-
-Window(func:makeWindow title:"xpdf" icon:xpdfIcon) {
- Box(x:1 y:2 xfill:1 yfill:1) {
-
- # canvas and scrollbars
- Box(x:2 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1 sunken) {
- ScrollingCanvas(name:"canvas" w:100 h:100)
- }
- Box1(yfill:1) {
- Scrollbar(name:"vScrollbar" vert min:0 max:100 move:&scrollVertCbk)
- }
- Box1(xfill:1) {
- Scrollbar(name:"hScrollbar" horiz min:0 max:100 move:&scrollHorizCbk)
- }
- Box1() { Empty() }
- }
-
- # buttons, page number, etc.
- Box(x:15 y:1 xfill:1) {
- Box1() {
- IconButton(bitmap:backArrow_bits w:backArrow_width
- h:backArrow_height press:&backCbk)
- }
- Box1() {
- IconButton(bitmap:dblLeftArrow_bits w:dblLeftArrow_width
- h:dblLeftArrow_height press:&prevTenPageCbk)
- }
- Box1() {
- IconButton(bitmap:leftArrow_bits w:leftArrow_width
- h:leftArrow_height press:&prevPageCbk)
- }
- Box1() {
- IconButton(bitmap:rightArrow_bits w:rightArrow_width
- h:rightArrow_height press:&nextPageCbk)
- }
- Box1() {
- IconButton(bitmap:dblRightArrow_bits w:dblRightArrow_width
- h:dblRightArrow_height press:&nextTenPageCbk)
- }
- Box1() {
- IconButton(bitmap:forwardArrow_bits w:forwardArrow_width
- h:forwardArrow_height press:&forwardCbk)
- }
- Box1() {
- Label(text:"Page"
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1(sunken left:4 right:4) {
- TextIn(name:"pageNum" mw:6 done:&pageNumCbk
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1() {
- Label(name:"numPages" maxLength length:9
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1() {
- MenuButton(name:"zoom" menu:zoomMenu)
- }
- Box1() {
- IconButton(bitmap:find_bits w:find_width
- h:find_height press:&findCbk)
- }
- Box1() {
- IconButton(bitmap:postscript_bits w:postscript_width
- h:postscript_height press:&postScriptCbk)
- }
- Box1() {
- IconButton(bitmap:about_bits w:about_width h:about_height
- press:&aboutCbk)
- }
- Box1(xfill:1) {
- Label(name:"link" fixedWidth
- font:"-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*")
- }
- Box1() { Button(label:"Quit" press:&quitCbk) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# full-screen main window
-#------------------------------------------------------------------------
-
-Window(func:makeFullScreenWindow title:"xpdf" icon:xpdfIcon) {
- Box(x:1 y:1 xfill:1 yfill:1) {
- ScrollingCanvas(name:"canvas" w:100 h:100)
- }
-}
-
-#------------------------------------------------------------------------
-# menu for main window
-#------------------------------------------------------------------------
-
-Menu(func:makeMenu title:"xpdf" n:8) {
- MenuItem(text:"Open..." shortcut:"O" num:menuOpen
- select:&menuCbk)
- MenuItem(text:"Reload" shortcut:"R" num:menuReload
- select:&menuCbk)
- MenuItem(text:"Save as..." num:menuSavePDF
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Rotate counterclockwise" num:menuRotateCCW
- select:&menuCbk)
- MenuItem(text:"Rotate clockwise" num:menuRotateCW
- select:&menuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"Quit" shortcut:"Q" num:menuQuit
- select:&menuCbk)
-}
-
-#------------------------------------------------------------------------
-# popup zoom menu
-#------------------------------------------------------------------------
-
-Menu(func:makeZoomMenu title:"zoom" n:14) {
- MenuItem(text:"-5" num:-5 select:&zoomMenuCbk)
- MenuItem(text:"-4" num:-4 select:&zoomMenuCbk)
- MenuItem(text:"-3" num:-3 select:&zoomMenuCbk)
- MenuItem(text:"-2" num:-2 select:&zoomMenuCbk)
- MenuItem(text:"-1" num:-1 select:&zoomMenuCbk)
- MenuItem(text:"0" num: 0 select:&zoomMenuCbk)
- MenuItem(text:"+1" num: 1 select:&zoomMenuCbk)
- MenuItem(text:"+2" num: 2 select:&zoomMenuCbk)
- MenuItem(text:"+3" num: 3 select:&zoomMenuCbk)
- MenuItem(text:"+4" num: 4 select:&zoomMenuCbk)
- MenuItem(text:"+5" num: 5 select:&zoomMenuCbk)
- MenuItem(text:NULL)
- MenuItem(text:"fit page" shortcut:"z" num:100 select:&zoomMenuCbk)
- MenuItem(text:"fit width" shortcut:"w" num:101 select:&zoomMenuCbk)
-}
-
-#------------------------------------------------------------------------
-# "PostScript output" dialog
-#------------------------------------------------------------------------
-
-Window(func:makePostScriptDialog dialog:gTrue defWidget:"ok"
- title:"xpdf: PostScript output") {
- Box(x:1 y:3) {
- Box(x:4 y:1) {
- Box1() { Label(text:"Pages:") }
- Box1(sunken) {
- TextIn(name:"firstPage" mw:6 tab:"lastPage"
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box1() { Label(text:"to") }
- Box1(sunken) {
- TextIn(name:"lastPage" mw:6 tab:"fileName"
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- }
- Box(x:2 y:1) {
- Box1() { Label(text:"File:") }
- Box1(sunken xfill:1) {
- TextIn(name:"fileName" mw:32
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- }
- Box(x:3 y:1 top:8) {
- Box1(left:8) { Button(name:"ok" label:"Ok" press:&psButtonCbk num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&psButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "open" dialog
-#------------------------------------------------------------------------
-
-Window(func:makeOpenDialog dialog:gTrue defWidget:"open"
- title:"xpdf: Open...") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1) {
- FileReq(name:"fileReq" select:openSelectCbk
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"open" label:"Open" press:&openButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&openButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "save" dialog
-#------------------------------------------------------------------------
-
-Window(func:makeSaveDialog dialog:gTrue defWidget:"save"
- title:"xpdf: Save as...") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1) {
- FileReq(name:"fileReq" select:saveSelectCbk
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"save" label:"Save" press:&saveButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Cancel" press:&saveButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "find" window
-#------------------------------------------------------------------------
-
-Window(func:makeFindWindow defWidget:"find" title:"xpdf: Find") {
- Box(x:1 y:3 xfill:1 yfill:1) {
- Box(x:2 y:1 xfill:1) {
- Box1() { Label(text:"Text:") }
- Box1(xfill:1 sunken) {
- TextIn(name:"text" mw:32
- font:"-*-courier-medium-r-normal-*-14-*-*-*-*-*-*-*")
- }
- }
- Box1(xfill:1 yfill:1) { Empty() }
- Box(x:3 y:1 top:8 xfill:1) {
- Box1(left:8) { Button(name:"find" label:"Find" press:&findButtonCbk
- num:1) }
- Box1(xfill:1) { Empty() }
- Box1(right:8) { Button(label:"Close" press:&findButtonCbk num:0) }
- }
- }
-}
-
-#------------------------------------------------------------------------
-# "about" window
-#------------------------------------------------------------------------
-
-Window(func:makeAboutWindow defWidget:"close" title:"About xpdf") {
- Box(x:1 y:2 xfill:1 yfill:1) {
- Box(x:2 y:2 xfill:1 yfill:1) {
- Box1(xfill:1 yfill:1 sunken) {
- List(name:"list" w:400 h:30
- font:"-*-courier-medium-r-normal-*-12-*-*-*-*-*-*-*")
- }
- Box1(yfill:1) {
- Scrollbar(name:"vScrollbar" vert min:0 max:100
- move:&aboutScrollVertCbk)
- }
- Box1(xfill:1) {
- Scrollbar(name:"hScrollbar" horiz min:0 max:100
- move:&aboutScrollHorizCbk)
- }
- Box1() { Empty() }
- }
- Box(x:2 y:1) {
- Box1(xfill:1) { Empty() }
- Box1() { Button(name:"close" label:"Close" press:&closeAboutCbk) }
- }
- }
-}
//------------------------------------------------------------------------
// xpdf version
-
-#define xpdfVersion "1.01.1"
+#define xpdfVersion "2.00"
+#define xpdfVersionNum 2.00
+#define xpdfMajorVersion 2
+#define xpdfMinorVersion 0
+#define xpdfMajorVersionStr "2"
// supported PDF version
#define supportedPDFVersionStr "1.4"
// copyright notice
#define xpdfCopyright "Copyright 1996-2002 Glyph & Cog, LLC"
+// Windows resource file stuff
+#define winxpdfVersion "WinXpdf 2.00"
+#define xpdfCopyrightAmp "Copyright 1996-2002 Glyph && Cog, LLC"
+
//------------------------------------------------------------------------
// paper size
//------------------------------------------------------------------------
#define pclose _pclose
#endif
-#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(__CYGWIN32__) || defined(MACOS)
+#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS)
#define POPEN_READ_MODE "rb"
#else
#define POPEN_READ_MODE "r"
#endif
-//------------------------------------------------------------------------
-// uncompress program
-//------------------------------------------------------------------------
-
-#ifdef HAVE_POPEN
-
-// command to uncompress to stdout
-# ifdef USE_GZIP
-# define uncompressCmd "gzip -d -c -q"
-# else
-# ifdef __EMX__
-# define uncompressCmd "compress -d -c"
-# else
-# define uncompressCmd "uncompress -c"
-# endif // __EMX__
-# endif // USE_GZIP
-
-#else // HAVE_POPEN
-
-// command to uncompress a file
-# ifdef USE_GZIP
-# define uncompressCmd "gzip -d -q"
-# else
-# define uncompressCmd "uncompress"
-# endif // USE_GZIP
-
-#endif // HAVE_POPEN
-
//------------------------------------------------------------------------
// Win32 stuff
//------------------------------------------------------------------------