[poppler] Branch 'xpdf303merge' - poppler/GfxFont.cc poppler/GlobalParams.cc poppler/GlobalParams.h poppler/GlobalParamsWin.cc poppler/Hints.cc poppler/Parser.cc poppler/Parser.h poppler/PreScanOutputDev.cc poppler/PreScanOutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h poppler/XRef.cc poppler/XRef.h utils/pdftops.cc
Albert Astals Cid
aacid at kemper.freedesktop.org
Sun Feb 5 13:57:55 PST 2012
poppler/GfxFont.cc | 4
poppler/GlobalParams.cc | 95 +-
poppler/GlobalParams.h | 18
poppler/GlobalParamsWin.cc | 16
poppler/Hints.cc | 2
poppler/PSOutputDev.cc | 1814 ++++++++++++++++++++++----------------------
poppler/PSOutputDev.h | 51 -
poppler/Parser.cc | 13
poppler/Parser.h | 7
poppler/PreScanOutputDev.cc | 70 +
poppler/PreScanOutputDev.h | 16
poppler/XRef.cc | 91 +-
poppler/XRef.h | 3
utils/pdftops.cc | 2
14 files changed, 1231 insertions(+), 971 deletions(-)
New commits:
commit 6ee907f291427b8751a872b31210bf32e8d2b722
Author: Albert Astals Cid <aacid at kde.org>
Date: Sun Feb 5 22:57:25 2012 +0100
[xpdf303] More merges from Thomas, basically PSOutputDev and some other small stuff
diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc
index c839ad4..4e29c36 100644
--- a/poppler/GfxFont.cc
+++ b/poppler/GfxFont.cc
@@ -729,7 +729,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
if (!isCIDFont()) {
//----- 8-bit PS resident font
- if (ps) {
+ if (name && ps) {
if ((path = globalParams->getPSResidentFont(name))) {
fontLoc = new GfxFontLoc();
fontLoc->locType = gfxFontLocResident;
@@ -756,7 +756,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
substName = new GooString(base14SubstFonts[substIdx]);
if (ps) {
error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
- base14SubstFonts[substIdx], name);
+ base14SubstFonts[substIdx], name ? name : new GooString("null"));
fontLoc = new GfxFontLoc();
fontLoc->locType = gfxFontLocResident;
fontLoc->fontType = fontType1;
diff --git a/poppler/GlobalParams.cc b/poppler/GlobalParams.cc
index ab399db..bfde306 100644
--- a/poppler/GlobalParams.cc
+++ b/poppler/GlobalParams.cc
@@ -582,6 +582,10 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
psOPI = gFalse;
psASCIIHex = gFalse;
psBinary = gFalse;
+ psUncompressPreloadedImages = gFalse;
+ psRasterResolution = 300;
+ psRasterMono = gFalse;
+ psAlwaysRasterize = gFalse;
textEncoding = new GooString("UTF-8");
#if defined(_WIN32)
textEOL = eolDOS;
@@ -596,6 +600,7 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
disableFreeTypeHinting = gFalse;
antialias = gTrue;
vectorAntialias = gTrue;
+ antialiasPrinting = gFalse;
strokeAdjust = gTrue;
screenType = screenUnset;
screenSize = -1;
@@ -610,7 +615,6 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
printCommands = gFalse;
profileCommands = gFalse;
errQuiet = gFalse;
- splashResolution = 0.0;
cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
unicodeToUnicodeCache =
@@ -1559,6 +1563,42 @@ GBool GlobalParams::getPSBinary() {
return binary;
}
+GBool GlobalParams::getPSUncompressPreloadedImages() {
+ GBool ah;
+
+ lockGlobalParams;
+ ah = psUncompressPreloadedImages;
+ unlockGlobalParams;
+ return ah;
+}
+
+double GlobalParams::getPSRasterResolution() {
+ double res;
+
+ lockGlobalParams;
+ res = psRasterResolution;
+ unlockGlobalParams;
+ return res;
+}
+
+GBool GlobalParams::getPSRasterMono() {
+ GBool mono;
+
+ lockGlobalParams;
+ mono = psRasterMono;
+ unlockGlobalParams;
+ return mono;
+}
+
+GBool GlobalParams::getPSAlwaysRasterize() {
+ GBool rast;
+
+ lockGlobalParams;
+ rast = psAlwaysRasterize;
+ unlockGlobalParams;
+ return rast;
+}
+
GooString *GlobalParams::getTextEncodingName() {
GooString *s;
@@ -1631,6 +1671,15 @@ GBool GlobalParams::getVectorAntialias() {
return f;
}
+GBool GlobalParams::getAntialiasPrinting() {
+ GBool f;
+
+ lockGlobalParams;
+ f = antialiasPrinting;
+ unlockGlobalParams;
+ return f;
+}
+
GBool GlobalParams::getStrokeAdjust() {
GBool f;
@@ -1745,14 +1794,6 @@ GBool GlobalParams::getErrQuiet() {
return errQuiet;
}
-double GlobalParams::getSplashResolution() {
- double r;
- lockGlobalParams;
- r = splashResolution;
- unlockGlobalParams;
- return r;
-}
-
CharCodeToUnicode *GlobalParams::getCIDToUnicode(GooString *collection) {
GooString *fileName;
CharCodeToUnicode *ctu;
@@ -1944,6 +1985,30 @@ void GlobalParams::setPSBinary(GBool binary) {
unlockGlobalParams;
}
+void GlobalParams::setPSUncompressPreloadedImages(GBool uncomp) {
+ lockGlobalParams;
+ psUncompressPreloadedImages = uncomp;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSRasterResolution(double res) {
+ lockGlobalParams;
+ psRasterResolution = res;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSRasterMono(GBool mono) {
+ lockGlobalParams;
+ psRasterMono = mono;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSAlwaysRasterize(GBool always) {
+ lockGlobalParams;
+ psAlwaysRasterize = always;
+ unlockGlobalParams;
+}
+
void GlobalParams::setTextEncoding(char *encodingName) {
lockGlobalParams;
delete textEncoding;
@@ -2015,6 +2080,12 @@ GBool GlobalParams::setVectorAntialias(char *s) {
return ok;
}
+void GlobalParams::setAntialiasPrinting(GBool anti) {
+ lockGlobalParams;
+ antialiasPrinting = anti;
+ unlockGlobalParams;
+}
+
void GlobalParams::setStrokeAdjust(GBool adjust)
{
lockGlobalParams;
@@ -2107,12 +2178,6 @@ void GlobalParams::setErrQuiet(GBool errQuietA) {
unlockGlobalParams;
}
-void GlobalParams::setSplashResolution(double SplashResolutionA) {
- lockGlobalParams;
- splashResolution = SplashResolutionA;
- unlockGlobalParams;
-}
-
void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) {
#ifdef ENABLE_PLUGINS
lockGlobalParams;
diff --git a/poppler/GlobalParams.h b/poppler/GlobalParams.h
index 35f4473..a861ffd 100644
--- a/poppler/GlobalParams.h
+++ b/poppler/GlobalParams.h
@@ -165,6 +165,10 @@ public:
GBool getPSOPI();
GBool getPSASCIIHex();
GBool getPSBinary();
+ GBool getPSUncompressPreloadedImages();
+ double getPSRasterResolution();
+ GBool getPSRasterMono();
+ GBool getPSAlwaysRasterize();
GooString *getTextEncodingName();
EndOfLineKind getTextEOL();
GBool getTextPageBreaks();
@@ -173,6 +177,7 @@ public:
GBool getDisableFreeTypeHinting();
GBool getAntialias();
GBool getVectorAntialias();
+ GBool getAntialiasPrinting();
GBool getStrokeAdjust();
ScreenType getScreenType();
int getScreenSize();
@@ -217,6 +222,10 @@ public:
void setPSOPI(GBool opi);
void setPSASCIIHex(GBool hex);
void setPSBinary(GBool binary);
+ void setPSUncompressPreloadedImages(GBool uncomp);
+ void setPSRasterResolution(double res);
+ void setPSRasterMono(GBool mono);
+ void setPSAlwaysRasterize(GBool always);
void setTextEncoding(char *encodingName);
GBool setTextEOL(char *s);
void setTextPageBreaks(GBool pageBreaks);
@@ -225,6 +234,7 @@ public:
GBool setDisableFreeTypeHinting(char *s);
GBool setAntialias(char *s);
GBool setVectorAntialias(char *s);
+ void setAntialiasPrinting(GBool print);
void setStrokeAdjust(GBool strokeAdjust);
void setScreenType(ScreenType st);
void setScreenSize(int size);
@@ -239,7 +249,6 @@ public:
void setPrintCommands(GBool printCommandsA);
void setProfileCommands(GBool profileCommandsA);
void setErrQuiet(GBool errQuietA);
- void setSplashResolution(double splashResolutionA);
//----- security handlers
@@ -313,6 +322,12 @@ private:
GBool psOPI; // generate PostScript OPI comments?
GBool psASCIIHex; // use ASCIIHex instead of ASCII85?
GBool psBinary; // use binary instead of hex
+ GBool psUncompressPreloadedImages; // uncompress all preloaded images
+ double psRasterResolution; // PostScript rasterization resolution (dpi)
+ GBool psRasterMono; // true to do PostScript rasterization
+ // in monochrome (gray); false to do it
+ // in color (RGB/CMYK)
+ GBool psAlwaysRasterize; // force PostScript rasterization
GooString *textEncoding; // encoding (unicodeMap) to use for text
// output
EndOfLineKind textEOL; // type of EOL marker to use for text
@@ -323,6 +338,7 @@ private:
GBool disableFreeTypeHinting; // FreeType disable hinting flag
GBool antialias; // anti-aliasing enable flag
GBool vectorAntialias; // vector anti-aliasing enable flag
+ GBool antialiasPrinting; // allow anti-aliasing when printing
GBool strokeAdjust; // stroke adjustment enable flag
ScreenType screenType; // halftone screen type
int screenSize; // screen matrix size
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index 54ce4f7..100b7a2 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -60,9 +60,9 @@ description for all fonts available in Windows. That's how MuPDF works.
#define DEFAULT_SUBSTITUTE_FONT "Helvetica"
static struct {
- char *name;
- char *t1FileName;
- char *ttFileName;
+ const char *name;
+ const char *t1FileName;
+ const char *ttFileName;
} displayFontTab[] = {
{"Courier", "n022003l.pfb", "cour.ttf"},
{"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
@@ -253,7 +253,8 @@ void SysFontList::scanWindowsFonts(GooString *winFontDir) {
data[dataLen] = '\0';
n = strlen(data);
if (!strcasecmp(data + n - 4, ".ttf") ||
- !strcasecmp(data + n - 4, ".ttc")) {
+ !strcasecmp(data + n - 4, ".ttc") ||
+ !strcasecmp(data + n - 4, ".otf")) {
fontPath = new GooString(data);
if (!(dataLen >= 3 && data[1] == ':' && data[2] == '\\')) {
fontPath->insert(0, '\\');
@@ -301,6 +302,11 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
n -= 11;
}
+ // remove trailing ' (OpenType)'
+ if (n > 11 && !strncmp(name + n - 11, " (OpenType)", 11)) {
+ n -= 11;
+ }
+
// remove trailing ' Italic'
if (n > 7 && !strncmp(name + n - 7, " Italic", 7)) {
n -= 7;
@@ -401,7 +407,7 @@ GooString *GlobalParams::findSystemFontFile(GfxFont *font,
*fontNum = fi->fontNum;
} else {
GooString *substFontName = new GooString(findSubstituteName(fontName->getCString()));
- error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{0:s}'", fontName, substFontName);
+ error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{1:t}'", fontName, substFontName);
if ((fi = sysFonts->find(substFontName, gFalse))) {
path = fi->path->copy();
*type = fi->type;
diff --git a/poppler/Hints.cc b/poppler/Hints.cc
index df066c6..46bce80 100644
--- a/poppler/Hints.cc
+++ b/poppler/Hints.cc
@@ -134,7 +134,7 @@ void Hints::readTables(BaseStream *str, Linearization *linearization, XRef *xref
if (parser->getObj(&obj)->isInt() &&
(num = obj.getInt(), obj.free(), parser->getObj(&obj)->isInt()) &&
(gen = obj.getInt(), obj.free(), parser->getObj(&obj)->isCmd("obj")) &&
- (obj.free(), parser->getObj(&obj,
+ (obj.free(), parser->getObj(&obj, gFalse,
secHdlr ? secHdlr->getFileKey() : (Guchar *)NULL,
secHdlr ? secHdlr->getEncAlgorithm() : cryptRC4,
secHdlr ? secHdlr->getFileKeyLength() : 0,
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index cf385be..7dbac8a 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -86,8 +86,8 @@
//------------------------------------------------------------------------
-// Resolution at which pages with transparency will be rasterized.
-#define defaultSplashDPI 300
+// Max size of a slice when rasterizing pages, in pixels.
+#define rasterizationSliceSize 20000000
//------------------------------------------------------------------------
// PostScript prolog and setup
@@ -113,16 +113,24 @@ static const char *prolog[] = {
" } for",
"~123sn",
"/pdfSetup {",
- " 3 1 roll 2 array astore",
" /setpagedevice where {",
- " pop 3 dict begin",
+ " pop 2 dict begin",
+ " /Policies 1 dict dup begin /PageSize 6 def end def",
+ " { /Duplex true def } if",
+ " currentdict end setpagedevice",
+ " } {",
+ " pop",
+ " } ifelse",
+ "} def",
+ "/pdfSetupPaper {",
+ " 2 array astore",
+ " /setpagedevice where {",
+ " pop 2 dict begin",
" /PageSize exch def",
" /ImagingBBox null def",
- " /Policies 1 dict dup begin /PageSize 3 def end def",
- " { /Duplex true def } if",
" currentdict end setpagedevice",
" } {",
- " pop pop",
+ " pop",
" } ifelse",
"} def",
"~1sn",
@@ -410,82 +418,82 @@ static const char *prolog[] = {
"/Td { pdfTextMat transform moveto } def",
"/Tm { /pdfTextMat exch def } def",
"% text string operators",
+ "/xyshow where {",
+ " pop",
+ " /xyshow2 {",
+ " dup length array",
+ " 0 2 2 index length 1 sub {",
+ " 2 index 1 index 2 copy get 3 1 roll 1 add get",
+ " pdfTextMat dtransform",
+ " 4 2 roll 2 copy 6 5 roll put 1 add 3 1 roll dup 4 2 roll put",
+ " } for",
+ " exch pop",
+ " xyshow",
+ " } def",
+ "}{",
+ " /xyshow2 {",
+ " currentfont /FontType get 0 eq {",
+ " 0 2 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 2 getinterval show moveto",
+ " 2 copy get 2 index 3 2 roll 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } {",
+ " 0 1 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 1 getinterval show moveto",
+ " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
+ " } ifelse",
+ " pop pop",
+ " } def",
+ "} ifelse",
"/cshow where {",
" pop",
- " /cshow2 {",
- " dup {",
- " pop pop",
- " 1 string dup 0 3 index put 3 index exec",
+ " /xycp {", // xycharpath
+ " 0 3 2 roll",
+ " {",
+ " pop pop currentpoint 3 2 roll",
+ " 1 string dup 0 4 3 roll put false charpath moveto",
+ " 2 copy get 2 index 2 index 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " 2 add",
" } exch cshow",
" pop pop",
" } def",
"}{",
- " /cshow2 {",
+ " /xycp {", // xycharpath
" currentfont /FontType get 0 eq {",
- " 0 2 2 index length 1 sub {",
- " 2 copy get exch 1 add 2 index exch get",
- " 2 copy exch 256 mul add",
- " 2 string dup 0 6 5 roll put dup 1 5 4 roll put",
- " 3 index exec",
+ " 0 2 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 2 getinterval false charpath moveto",
+ " 2 copy get 2 index 3 2 roll 1 add get",
+ " pdfTextMat dtransform rmoveto",
" } for",
" } {",
- " dup {",
- " 1 string dup 0 3 index put 3 index exec",
- " } forall",
+ " 0 1 3 index length 1 sub {",
+ " currentpoint 4 index 3 index 1 getinterval false charpath moveto",
+ " 2 copy 2 mul get 2 index 3 2 roll 2 mul 1 add get",
+ " pdfTextMat dtransform rmoveto",
+ " } for",
" } ifelse",
" pop pop",
" } def",
"} ifelse",
- "/awcp {", // awidthcharpath
- " exch {",
- " false charpath",
- " 5 index 5 index rmoveto",
- " 6 index eq { 7 index 7 index rmoveto } if",
- " } exch cshow2",
- " 6 {pop} repeat",
- "} def",
"/Tj {",
" fCol", // because stringwidth has to draw Type 3 chars
- " 1 index stringwidth pdfTextMat idtransform pop",
- " sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
- " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
- " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
- " pdfTextMat dtransform",
- " 6 5 roll Tj1",
- "} def",
- "/Tj16 {",
- " fCol", // because stringwidth has to draw Type 3 chars
- " 2 index stringwidth pdfTextMat idtransform pop",
- " sub exch div",
- " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
- " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
- " pdfTextMat dtransform",
- " 6 5 roll Tj1",
- "} def",
- "/Tj16V {",
- " fCol", // because stringwidth has to draw Type 3 chars
- " 2 index stringwidth pdfTextMat idtransform exch pop",
- " sub exch div",
- " 0 pdfWordSpacing pdfTextMat dtransform 32",
- " 4 3 roll pdfCharSpacing add 0 exch",
- " pdfTextMat dtransform",
- " 6 5 roll Tj1",
- "} def",
- "/Tj1 {",
" 0 pdfTextRise pdfTextMat dtransform rmoveto",
- " currentpoint 8 2 roll",
- " pdfTextRender 1 and 0 eq pdfPatternCS not and {",
- " 6 copy awidthshow",
+ " currentpoint 4 2 roll",
+ " pdfTextRender 1 and 0 eq {",
+ " 2 copy xyshow2",
" } if",
" pdfTextRender 3 and dup 1 eq exch 2 eq or {",
- " 7 index 7 index moveto",
- " 6 copy",
+ " 3 index 3 index moveto",
+ " 2 copy",
" currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
- " false awcp currentpoint stroke moveto",
+ " xycp currentpoint stroke moveto",
" } if",
- " pdfTextRender 4 and 0 ne pdfPatternCS or {",
- " 8 6 roll moveto",
- " false awcp",
+ " pdfTextRender 4 and 0 ne {",
+ " 4 2 roll moveto xycp",
" /pdfTextClipPath [ pdfTextClipPath aload pop",
" {/moveto cvx}",
" {/lineto cvx}",
@@ -494,13 +502,13 @@ static const char *prolog[] = {
" pathforall ] def",
" currentpoint newpath moveto",
" } {",
- " 8 {pop} repeat",
+ " pop pop pop pop",
" } ifelse",
" 0 pdfTextRise neg pdfTextMat dtransform rmoveto",
"} def",
- "/TJm { pdfFontSize 0.001 mul mul neg 0",
+ "/TJm { 0.001 mul pdfFontSize mul pdfHorizScaling mul neg 0",
" pdfTextMat dtransform rmoveto } def",
- "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch",
+ "/TJmV { 0.001 mul pdfFontSize mul neg 0 exch",
" pdfTextMat dtransform rmoveto } def",
"/Tclip { pdfTextClipPath cvx exec clip newpath",
" /pdfTextClipPath [] def } def",
@@ -548,19 +556,52 @@ static const char *prolog[] = {
" fCol /pdfImBuf1 4 index 7 add 8 idiv string def",
" { currentfile pdfImBuf1 readstring pop } imagemask",
"} def",
+ "/pdfImStr {",
+ " 2 copy exch length lt {",
+ " 2 copy get exch 1 add exch",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
"/pdfImM1a {",
- " { 2 copy get exch 1 add exch } imagemask",
+ " { pdfImStr } imagemask",
" pop pop",
"} def",
"~23sn",
- "% Level 2 image operators",
+ "% Level 2/3 image operators",
"/pdfImBuf 100 string def",
- "/pdfIm {",
- " image",
+ "/pdfImStr {",
+ " 2 copy exch length lt {",
+ " 2 copy get exch 1 add exch",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
+ "/skipEOD {",
" { currentfile pdfImBuf readline",
" not { pop exit } if",
" (%-EOD-) eq { exit } if } loop",
"} def",
+ "/pdfIm { image skipEOD } def",
+ "~3sn",
+ "/pdfMask {",
+ " /ReusableStreamDecode filter",
+ " skipEOD",
+ " /maskStream exch def",
+ "} def",
+ "/pdfMaskEnd { maskStream closefile } def",
+ "/pdfMaskInit {",
+ " /maskArray exch def",
+ " /maskIdx 0 def",
+ "} def",
+ "/pdfMaskSrc {",
+ " maskIdx maskArray length lt {",
+ " maskArray maskIdx get",
+ " /maskIdx maskIdx 1 add def",
+ " } {",
+ " ()",
+ " } ifelse",
+ "} def",
"~23s",
"/pdfImSep {",
" findcmykcustomcolor exch",
@@ -576,17 +617,10 @@ static const char *prolog[] = {
" 255 exch sub put",
" } for }",
" 6 5 roll customcolorimage",
- " { currentfile pdfImBuf readline",
- " not { pop exit } if",
- " (%-EOD-) eq { exit } if } loop",
+ " skipEOD",
"} def",
"~23sn",
- "/pdfImM {",
- " fCol imagemask",
- " { currentfile pdfImBuf readline",
- " not { pop exit } if",
- " (%-EOD-) eq { exit } if } loop",
- "} def",
+ "/pdfImM { fCol imagemask skipEOD } def",
"~123sn",
"/pr { 2 index 2 index 3 2 roll putinterval 4 add } def",
"/pdfImClip {",
@@ -892,6 +926,13 @@ struct PSOutImgClipRect {
};
//------------------------------------------------------------------------
+
+struct PSOutPaperSize {
+ PSOutPaperSize(int wA, int hA) { w = wA; h = hA; }
+ int w, h;
+};
+
+//------------------------------------------------------------------------
// DeviceNRecoder
//------------------------------------------------------------------------
@@ -944,6 +985,9 @@ DeviceNRecoder::~DeviceNRecoder() {
if (imgStr) {
delete imgStr;
}
+ if (str->isEncoder()) {
+ delete str;
+ }
}
void DeviceNRecoder::reset() {
@@ -994,8 +1038,9 @@ PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *doc,
int firstPage, int lastPage, PSOutMode modeA,
int paperWidthA, int paperHeightA, GBool duplexA,
int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- GBool forceRasterizeA,
- GBool manualCtrlA) {
+ GBool manualCtrlA,
+ PSOutCustomCodeCbk customCodeCbkA,
+ void *customCodeCbkDataA) {
FILE *f;
PSFileType fileTypeA;
@@ -1003,23 +1048,23 @@ PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *doc,
underlayCbkData = NULL;
overlayCbk = NULL;
overlayCbkData = NULL;
+ customCodeCbk = customCodeCbkA;
+ customCodeCbkData = customCodeCbkDataA;
fontIDs = NULL;
fontNames = new GooHash(gTrue);
- fontFileIDs = NULL;
- fontFileNames = NULL;
+ t1FontNames = NULL;
font8Info = NULL;
font16Enc = NULL;
imgIDs = NULL;
formIDs = NULL;
xobjStack = NULL;
+ paperSizes = NULL;
embFontList = NULL;
customColors = NULL;
haveTextClip = gFalse;
t3String = NULL;
- forceRasterize = forceRasterizeA;
-
// open file or pipe
if (!strcmp(fileName, "-")) {
fileTypeA = psStdout;
@@ -1061,29 +1106,30 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
int firstPage, int lastPage, PSOutMode modeA,
int paperWidthA, int paperHeightA, GBool duplexA,
int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
- GBool forceRasterizeA,
- GBool manualCtrlA) {
+ GBool manualCtrlA,
+ PSOutCustomCodeCbk customCodeCbkA,
+ void *customCodeCbkDataA) {
underlayCbk = NULL;
underlayCbkData = NULL;
overlayCbk = NULL;
overlayCbkData = NULL;
+ customCodeCbk = customCodeCbkA;
+ customCodeCbkData = customCodeCbkDataA;
fontIDs = NULL;
fontNames = new GooHash(gTrue);
- fontFileIDs = NULL;
- fontFileNames = NULL;
+ t1FontNames = NULL;
font8Info = NULL;
font16Enc = NULL;
imgIDs = NULL;
formIDs = NULL;
xobjStack = NULL;
+ paperSizes = NULL;
embFontList = NULL;
customColors = NULL;
haveTextClip = gFalse;
t3String = NULL;
- forceRasterize = forceRasterizeA;
-
init(outputFuncA, outputStreamA, psGeneric, psTitle,
doc, firstPage, lastPage, modeA,
imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA,
@@ -1098,6 +1144,9 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
GBool duplexA) {
Catalog *catalog;
PDFRectangle *box;
+ PSOutPaperSize *size;
+ GooList *names;
+ int pg, w, h, i;
// initialize
displayText = gTrue;
@@ -1118,14 +1167,38 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
imgURY = imgURYA;
if (paperWidth < 0 || paperHeight < 0) {
Page *page;
- if ((page = doc->getPage(firstPage))) {
- paperWidth = (int)ceil(page->getMediaWidth());
- paperHeight = (int)ceil(page->getMediaHeight());
- } else {
- error(errSyntaxError, -1, "Invalid page {0:d}", firstPage);
- paperWidth = 1;
- paperHeight = 1;
+ paperMatch = gTrue;
+ paperSizes = new GooList();
+ paperWidth = paperHeight = 1; // in case the document has zero pages
+ for (pg = (firstPage >= 1) ? firstPage : 1;
+ pg <= lastPage && pg <= catalog->getNumPages();
+ ++pg) {
+ page = catalog->getPage(pg);
+ if (page == NULL) {
+ paperMatch = gFalse;
+ break;
+ }
+ w = (int)ceil(page->getMediaWidth());
+ h = (int)ceil(page->getMediaHeight());
+ for (i = 0; i < paperSizes->getLength(); ++i) {
+ size = (PSOutPaperSize *)paperSizes->get(i);
+ if (size->w == w && size->h == h) {
+ break;
+ }
+ }
+ if (i == paperSizes->getLength()) {
+ paperSizes->append(new PSOutPaperSize(w, h));
+ }
+ if (w > paperWidth) {
+ paperWidth = w;
+ }
+ if (h > paperHeight) {
+ paperHeight = h;
+ }
}
+ // NB: img{LLX,LLY,URX,URY} will be set by startPage()
+ } else {
+ paperMatch = gFalse;
}
preload = globalParams->getPSPreload();
if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
@@ -1161,14 +1234,18 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
fontIDSize = 64;
fontIDLen = 0;
fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
- fontFileIDSize = 64;
- fontFileIDLen = 0;
- fontFileIDs = (Ref *)gmallocn(fontFileIDSize, sizeof(Ref));
- fontFileNameSize = 64;
- fontFileNameLen = 0;
- fontFileNames = (GooString **)gmallocn(fontFileNameSize, sizeof(GooString *));
- psFileNames = (GooString **)gmallocn(fontFileNameSize, sizeof(GooString *));
- nextTrueTypeNum = 0;
+ fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
+ for (i = 0; i < 14; ++i) {
+ fontNames->add(new GooString(psBase14SubstFonts[i].psName), 1);
+ }
+ names = globalParams->getPSResidentFonts();
+ for (i = 0; i < names->getLength(); ++i) {
+ fontNames->add((GooString *)names->get(i), 1);
+ }
+ delete names;
+ t1FontNameSize = 64;
+ t1FontNameLen = 0;
+ t1FontNames = (PST1FontName *)gmallocn(t1FontNameSize, sizeof(PST1FontName));
font8InfoLen = 0;
font8InfoSize = 0;
font16EncLen = 0;
@@ -1246,6 +1323,9 @@ PSOutputDev::~PSOutputDev() {
}
#endif
}
+ if (paperSizes) {
+ deleteGooList(paperSizes, PSOutPaperSize);
+ }
if (embFontList) {
delete embFontList;
}
@@ -1253,14 +1333,11 @@ PSOutputDev::~PSOutputDev() {
gfree(fontIDs);
}
delete fontNames;
- if (fontFileIDs) {
- gfree(fontFileIDs);
- }
- if (fontFileNames) {
- for (i = 0; i < fontFileNameLen; ++i) {
- delete fontFileNames[i];
+ if (t1FontNames) {
+ for (i = 0; i < t1FontNameLen; ++i) {
+ delete t1FontNames[i].psName;
}
- gfree(fontFileNames);
+ gfree(t1FontNames);
}
if (font8Info) {
for (i = 0; i < font8InfoLen; ++i) {
@@ -1268,16 +1345,11 @@ PSOutputDev::~PSOutputDev() {
}
gfree(font8Info);
}
- if (psFileNames) {
- for (i = 0; i < fontFileNameLen; ++i) {
- if (psFileNames[i])
- delete psFileNames[i];
- }
- gfree(psFileNames);
- }
if (font16Enc) {
for (i = 0; i < font16EncLen; ++i) {
- delete font16Enc[i].enc;
+ if (font16Enc[i].enc) {
+ delete font16Enc[i].enc;
+ }
}
gfree(font16Enc);
}
@@ -1296,8 +1368,10 @@ PSOutputDev::~PSOutputDev() {
void PSOutputDev::writeHeader(int firstPage, int lastPage,
PDFRectangle *mediaBox, PDFRectangle *cropBox,
int pageRotate, char *psTitle) {
- double x1, y1, x2, y2;
Object info, obj1;
+ PSOutPaperSize *size;
+ double x1, y1, x2, y2;
+ int i;
switch (mode) {
case psModePSOrigPageSizes:
@@ -1339,14 +1413,24 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
prevWidth = 0;
prevHeight = 0;
case psModePS:
- writePSFmt("%%DocumentMedia: plain {0:d} {1:d} 0 () ()\n",
- paperWidth, paperHeight);
+ if (paperMatch) {
+ for (i = 0; i < paperSizes->getLength(); ++i) {
+ size = (PSOutPaperSize *)paperSizes->get(i);
+ writePSFmt("%%{0:s} {1:d}x{2:d} {1:d} {2:d} 0 () ()\n",
+ i==0 ? "DocumentMedia:" : "+", size->w, size->h);
+ }
+ } else {
+ writePSFmt("%%DocumentMedia: plain {0:d} {1:d} 0 () ()\n",
+ paperWidth, paperHeight);
+ }
writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight);
writePSFmt("%%Pages: {0:d}\n", lastPage - firstPage + 1);
writePS("%%EndComments\n");
- writePS("%%BeginDefaults\n");
- writePS("%%PageMedia: plain\n");
- writePS("%%EndDefaults\n");
+ if (!paperMatch) {
+ writePS("%%BeginDefaults\n");
+ writePS("%%PageMedia: plain\n");
+ writePS("%%EndDefaults\n");
+ }
break;
case psModeEPS:
epsX1 = cropBox->x1;
@@ -1430,7 +1514,9 @@ void PSOutputDev::writeDocSetup(PDFDoc *doc, Catalog *catalog,
Page *page;
Dict *resDict;
Annots *annots;
- Object obj1, obj2;
+ Object *acroForm;
+ Object obj1, obj2, obj3;
+ GooString *s;
int pg, i;
if (mode == psModeForm) {
@@ -1462,10 +1548,31 @@ void PSOutputDev::writeDocSetup(PDFDoc *doc, Catalog *catalog,
}
delete annots;
}
+ if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) {
+ if (acroForm->dictLookup("DR", &obj1)->isDict()) {
+ setupResources(obj1.getDict());
+ }
+ obj1.free();
+ if (acroForm->dictLookup("Fields", &obj1)->isArray()) {
+ for (i = 0; i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &obj2)->isDict()) {
+ if (obj2.dictLookup("DR", &obj3)->isDict()) {
+ setupResources(obj3.getDict());
+ }
+ obj3.free();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ }
if (mode != psModeForm) {
if (mode != psModeEPS && !manualCtrl) {
- writePSFmt("{0:d} {1:d} {2:s} pdfSetup\n",
- paperWidth, paperHeight, duplexA ? "true" : "false");
+ writePSFmt("{0:s} pdfSetup\n",
+ duplexA ? "true" : "false");
+ if (!paperMatch) {
+ writePSFmt("{0:d} {1:d} pdfSetupPaper\n", paperWidth, paperHeight);
+ }
}
#if OPI_SUPPORT
if (globalParams->getPSOPI()) {
@@ -1473,6 +1580,13 @@ void PSOutputDev::writeDocSetup(PDFDoc *doc, Catalog *catalog,
}
#endif
}
+ if (customCodeCbk) {
+ if ((s = (*customCodeCbk)(this, psOutCustomDocSetup, 0,
+ customCodeCbkData))) {
+ writePS(s->getCString());
+ delete s;
+ }
+ }
}
void PSOutputDev::writePageTrailer() {
@@ -1627,8 +1741,6 @@ void PSOutputDev::setupFonts(Dict *resDict) {
GfxFont *font;
int i;
- if (forceRasterize) return;
-
gfxFontDict = NULL;
resDict->lookupNF("Font", &obj1);
if (obj1.isRef()) {
@@ -1891,18 +2003,10 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GooString *psName) {
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
- return;
- }
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (fontNames->lookupInt(psName)) {
+ return;
}
- fontFileIDs[fontFileIDLen++] = *id;
+ fontNames->add(psName->copy(), 1);
// get the font stream and info
refObj.initRef(id->num, id->gen);
@@ -2041,26 +2145,11 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GooString *psName) {
void PSOutputDev::setupExternalType1Font(GooString *fileName, GooString *psName) {
FILE *fontFile;
int c;
- int i;
- // check if font is already embedded
- for (i = 0; i < fontFileNameLen; ++i) {
- if (!fontFileNames[i]->cmp(fileName)) {
- return;
- }
- }
-
- // add entry to fontFileNames list
- if (fontFileNameLen >= fontFileNameSize) {
- fontFileNameSize += 64;
- fontFileNames = (GooString **)greallocn(fontFileNames,
- fontFileNameSize, sizeof(GooString *));
- psFileNames = (GooString **)greallocn(psFileNames,
- fontFileNameSize, sizeof(GooString *));
+ if (fontNames->lookupInt(psName)) {
+ return;
}
- fontFileNames[fontFileNameLen] = fileName->copy();
- psFileNames[fontFileNameLen] = psName->copy();
- fontFileNameLen++;
+ fontNames->add(psName->copy(), 1);
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2090,18 +2179,22 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2110,13 +2203,14 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 1 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
- ffT1C->convertToType1(psName->getCString(), NULL, gTrue,
- outputFunc, outputStream);
- delete ffT1C;
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ ffT1C->convertToType1(psName->getCString(), NULL, gTrue,
+ outputFunc, outputStream);
+ delete ffT1C;
+ }
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2130,18 +2224,22 @@ void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2150,15 +2248,16 @@ void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 1 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (ffTT->isOpenTypeCFF()) {
- ffTT->convertToType1(psName->getCString(), NULL, gTrue,
- outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (ffTT->isOpenTypeCFF()) {
+ ffTT->convertToType1(psName->getCString(), NULL, gTrue,
+ outputFunc, outputStream);
+ }
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2170,25 +2269,6 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
int fontLen;
FoFiTrueType *ffTT;
int *codeToGID;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen) {
- psName->appendf("_{0:d}", nextTrueTypeNum++);
- break;
- }
- }
-
- // add entry to fontFileIDs list
- if (i == fontFileIDLen) {
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
- }
- fontFileIDs[fontFileIDLen++] = *id;
- }
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2197,28 +2277,29 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 42 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
- ffTT->convertToType42(psName->getCString(),
- ((Gfx8BitFont *)font)->getHasEncoding()
- ? ((Gfx8BitFont *)font)->getEncoding()
- : (char **)NULL,
- codeToGID, outputFunc, outputStream);
- if (codeToGID) {
- if (font8InfoLen >= font8InfoSize) {
- font8InfoSize += 16;
- font8Info = (PSFont8Info *)greallocn(font8Info,
- font8InfoSize,
- sizeof(PSFont8Info));
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
+ ffTT->convertToType42(psName->getCString(),
+ ((Gfx8BitFont *)font)->getHasEncoding()
+ ? ((Gfx8BitFont *)font)->getEncoding()
+ : (char **)NULL,
+ codeToGID, outputFunc, outputStream);
+ if (codeToGID) {
+ if (font8InfoLen >= font8InfoSize) {
+ font8InfoSize += 16;
+ font8Info = (PSFont8Info *)greallocn(font8Info,
+ font8InfoSize,
+ sizeof(PSFont8Info));
+ }
+ font8Info[font8InfoLen].fontID = *font->getID();
+ font8Info[font8InfoLen].codeToGID = codeToGID;
+ ++font8InfoLen;
}
- font8Info[font8InfoLen].fontID = *font->getID();
- font8Info[font8InfoLen].codeToGID = codeToGID;
- ++font8InfoLen;
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2300,13 +2381,18 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
codeToGIDLen = ctu->getLength();
codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int));
for (code = 0; code < codeToGIDLen; ++code) {
- if (ctu->mapToUnicode(code, &uBuf) > 0) {
+ int n = ctu->mapToUnicode(code, &uBuf);
+ if (n > 0) {
codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]);
} else {
codeToGID[code] = 0;
}
}
- if (globalParams->getPSLevel() >= psLevel3) {
+ if (ffTT->isOpenTypeCFF()) {
+ ffTT->convertToCIDType0(psName->getCString(),
+ codeToGID, codeToGIDLen,
+ outputFunc, outputStream);
+ } else if (globalParams->getPSLevel() >= psLevel3) {
// Level 3: use a CID font
ffTT->convertToCIDType2(psName->getCString(),
codeToGID, codeToGIDLen,
@@ -2348,18 +2434,22 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2368,20 +2458,21 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 0 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffT1C->convertToCIDType0(psName->getCString(), NULL, 0,
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffT1C->convertToType0(psName->getCString(), NULL, 0,
- outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffT1C->convertToCIDType0(psName->getCString(), NULL, 0,
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffT1C->convertToType0(psName->getCString(), NULL, 0,
+ outputFunc, outputStream);
+ }
+ delete ffT1C;
}
- delete ffT1C;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2393,23 +2484,6 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
char *fontBuf;
int fontLen;
FoFiTrueType *ffTT;
- int i;
-
- // check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen) {
- psName->appendf("_{0:d}", nextTrueTypeNum++);
- break;
- }
- }
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
- }
- fontFileIDs[fontFileIDLen++] = *id;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2418,26 +2492,27 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 0 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType2(psName->getCString(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- needVerticalMetrics,
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffTT->convertToType0(psName->getCString(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- needVerticalMetrics,
- outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType2(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ needVerticalMetrics,
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ needVerticalMetrics,
+ outputFunc, outputStream);
+ }
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2451,18 +2526,22 @@ void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id,
int i;
// check if font is already embedded
- for (i = 0; i < fontFileIDLen; ++i) {
- if (fontFileIDs[i].num == id->num &&
- fontFileIDs[i].gen == id->gen)
+ for (i = 0; i < t1FontNameLen; ++i) {
+ if (t1FontNames[i].fontFileID.num == id->num &&
+ t1FontNames[i].fontFileID.gen == id->gen) {
+ psName->clear();
+ psName->insert(0, t1FontNames[i].psName);
return;
+ }
}
-
- // add entry to fontFileIDs list
- if (fontFileIDLen >= fontFileIDSize) {
- fontFileIDSize += 64;
- fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref));
+ if (t1FontNameLen == t1FontNameSize) {
+ t1FontNameSize *= 2;
+ t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize,
+ sizeof(PST1FontName));
}
- fontFileIDs[fontFileIDLen++] = *id;
+ t1FontNames[t1FontNameLen].fontFileID = *id;
+ t1FontNames[t1FontNameLen].psName = psName->copy();
+ ++t1FontNameLen;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2471,26 +2550,27 @@ void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id,
embFontList->append("\n");
// convert it to a Type 0 font
- fontBuf = font->readEmbFontFile(xref, &fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
- if (ffTT->isOpenTypeCFF()) {
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType0(psName->getCString(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- outputFunc, outputStream);
- } else {
- // otherwise: use a non-CID composite font
- ffTT->convertToType0(psName->getCString(),
- ((GfxCIDFont *)font)->getCIDToGID(),
- ((GfxCIDFont *)font)->getCIDToGIDLen(),
- outputFunc, outputStream);
+ if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) {
+ if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if (ffTT->isOpenTypeCFF()) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ ffTT->convertToCIDType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ffTT->convertToType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
+ }
}
+ delete ffTT;
}
- delete ffTT;
+ gfree(fontBuf);
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
@@ -2552,6 +2632,7 @@ void PSOutputDev::setupType3Font(GfxFont *font, GooString *psName,
gfx = new Gfx(doc, this, resDict, &box, NULL);
inType3Char = gTrue;
for (i = 0; i < charProcs->getLength(); ++i) {
+ t3FillColorOnly = gFalse;
t3Cacheable = gFalse;
t3NeedsRestore = gFalse;
writePS("/");
@@ -2625,8 +2706,9 @@ GooString *PSOutputDev::makePSFontName(GfxFont *font, Ref *id) {
}
void PSOutputDev::setupImages(Dict *resDict) {
- Object xObjDict, xObj, xObjRef, subtypeObj;
- int i;
+ Object xObjDict, xObj, xObjRef, subtypeObj, maskObj, maskRef;
+ Ref imgID;
+ int i, j;
if (!(mode == psModeForm || inType3Char || preload)) {
return;
@@ -2642,7 +2724,29 @@ void PSOutputDev::setupImages(Dict *resDict) {
xObj.streamGetDict()->lookup("Subtype", &subtypeObj);
if (subtypeObj.isName("Image")) {
if (xObjRef.isRef()) {
- setupImage(xObjRef.getRef(), xObj.getStream());
+ imgID = xObjRef.getRef();
+ for (j = 0; j < imgIDLen; ++j) {
+ if (imgIDs[j].num == imgID.num && imgIDs[j].gen == imgID.gen) {
+ break;
+ }
+ }
+ if (j == imgIDLen) {
+ if (imgIDLen >= imgIDSize) {
+ if (imgIDSize == 0) {
+ imgIDSize = 64;
+ } else {
+ imgIDSize *= 2;
+ }
+ imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref));
+ }
+ imgIDs[imgIDLen++] = imgID;
+ setupImage(imgID, xObj.getStream(), gFalse);
+ if (level >= psLevel3 &&
+ xObj.streamGetDict()->lookup("Mask", &maskObj)->isStream()) {
+ setupImage(imgID, maskObj.getStream(), gTrue);
+ }
+ maskObj.free();
+ }
} else {
error(errSyntaxError, -1,
"Image in resource dict is not an indirect reference");
@@ -2657,31 +2761,13 @@ void PSOutputDev::setupImages(Dict *resDict) {
xObjDict.free();
}
-void PSOutputDev::setupImage(Ref id, Stream *str) {
+void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) {
GBool useRLE, useCompressed, useASCIIHex;
GooString *s;
int c;
int size, line, col, i;
int outerSize, outer;
- // check if image is already setup
- for (i = 0; i < imgIDLen; ++i) {
- if (imgIDs[i].num == id.num && imgIDs[i].gen == id.gen) {
- return;
- }
- }
-
- // add entry to imgIDs list
- if (imgIDLen >= imgIDSize) {
- if (imgIDSize == 0) {
- imgIDSize = 64;
- } else {
- imgIDSize *= 2;
- }
- imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref));
- }
- imgIDs[imgIDLen++] = id;
-
// filters
//~ this does not correctly handle the DeviceN color space
//~ -- need to use DeviceNRecoder
@@ -2690,17 +2776,21 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
useCompressed = gFalse;
useASCIIHex = gTrue;
} else {
- s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
- if (s) {
+ if (globalParams->getPSUncompressPreloadedImages()) {
useRLE = gFalse;
- useCompressed = gTrue;
- delete s;
- } else {
- useRLE = gTrue;
useCompressed = gFalse;
+ } else {
+ s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
+ if (s) {
+ useRLE = gFalse;
+ useCompressed = gTrue;
+ delete s;
+ } else {
+ useRLE = gTrue;
+ useCompressed = gFalse;
+ }
}
- useASCIIHex = level == psLevel1 || level == psLevel1Sep ||
- globalParams->getPSASCIIHex();
+ useASCIIHex = globalParams->getPSASCIIHex();
}
if (useCompressed) {
str = str->getUndecodedStream();
@@ -2754,8 +2844,8 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
}
outerSize = size/65535 + 1;
- writePSFmt("{0:d} array dup /ImData_{1:d}_{2:d} exch def\n",
- outerSize, id.num, id.gen);
+ writePSFmt("{0:d} array dup /{1:s}Data_{2:d}_{3:d} exch def\n",
+ size, mask ? "Mask" : "Im", id.num, id.gen);
str->close();
// write the data into the array
@@ -2945,9 +3035,11 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
GBool printing,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
-#if HAVE_SPLASH
PreScanOutputDev *scan;
GBool rasterize;
+#if HAVE_SPLASH
+ GBool mono;
+ double dpi;
SplashOutputDev *splashOut;
SplashColor paperColor;
PDFRectangle box;
@@ -2957,422 +3049,233 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
Object obj;
Guchar *p;
Guchar col[4];
+ double hDPI2, vDPI2;
double m0, m1, m2, m3, m4, m5;
+ int nStripes, stripeH, stripeY;
int c, w, h, x, y, comp, i;
- double splashDPI;
- char hexBuf[32*2 + 2]; // 32 values X 2 chars/value + line ending + null
- Guchar digit;
- GBool useBinary;
- GBool isGray;
- int compCyan;
+#endif
- if (!forceRasterize) {
+ if (globalParams->getPSAlwaysRasterize()) {
+ rasterize = gTrue;
+ } else {
scan = new PreScanOutputDev(doc);
page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- printing, abortCheckCbk, abortCheckCbkData);
- rasterize = scan->usesTransparency() || scan->hasLevel1PSBug();
+ sliceX, sliceY, sliceW, sliceH,
+ printing, abortCheckCbk, abortCheckCbkData);
+ rasterize = scan->usesTransparency() || scan->usesPatternImageMask();
delete scan;
- } else {
- rasterize = gTrue;
}
if (!rasterize) {
return gTrue;
}
- // rasterize the page
- if (level == psLevel1) {
+#if HAVE_SPLASH
+ // get the rasterization parameters
+ dpi = globalParams->getPSRasterResolution();
+ mono = globalParams->getPSRasterMono();
+
+ // start the PS page
+ page->makeBox(dpi, dpi, rotateA, useMediaBox, gFalse,
+ sliceX, sliceY, sliceW, sliceH, &box, &crop);
+ rotateA += page->getRotate();
+ if (rotateA >= 360) {
+ rotateA -= 360;
+ } else if (rotateA < 0) {
+ rotateA += 360;
+ }
+ state = new GfxState(dpi, dpi, &box, rotateA, gFalse);
+ startPage(page->getNum(), state);
+ delete state;
+
+ // set up the SplashOutputDev
+ if (mono || level == psLevel1) {
paperColor[0] = 0xff;
splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse,
- paperColor, gTrue, gFalse);
+ paperColor, gFalse,
+ globalParams->getAntialiasPrinting());
#if SPLASH_CMYK
- } else if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
+ } else if (level == psLevel1Sep) {
paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
splashOut = new SplashOutputDev(splashModeCMYK8, 1, gFalse,
- paperColor, gTrue, gFalse);
-#else
- } else if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
- error(errInternal, -1, "pdftops was built without CMYK support, levelnsep needs it to work in this file");
- return gFalse;
+ paperColor, gFalse,
+ globalParams->getAntialiasPrinting());
#endif
} else {
paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse,
- paperColor, gTrue, gFalse);
+ paperColor, gFalse,
+ globalParams->getAntialiasPrinting());
}
splashOut->startDoc(doc);
- splashDPI = globalParams->getSplashResolution();
- if (splashDPI < 1.0) {
- splashDPI = defaultSplashDPI;
- }
- page->displaySlice(splashOut, splashDPI, splashDPI, rotateA,
- useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- printing, abortCheckCbk, abortCheckCbkData);
- // start the PS page
- page->makeBox(splashDPI, splashDPI, rotateA, useMediaBox, gFalse,
- sliceX, sliceY, sliceW, sliceH, &box, &crop);
- rotateA += page->getRotate();
- if (rotateA >= 360) {
- rotateA -= 360;
- } else if (rotateA < 0) {
- rotateA += 360;
+ // break the page into stripes
+ hDPI2 = xScale * dpi;
+ vDPI2 = yScale * dpi;
+ if (sliceW < 0 || sliceH < 0) {
+ if (useMediaBox) {
+ box = *page->getMediaBox();
+ } else {
+ box = *page->getCropBox();
+ }
+ sliceX = sliceY = 0;
+ sliceW = (int)((box.x2 - box.x1) * hDPI2 / 72.0);
+ sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0);
}
- state = new GfxState(splashDPI, splashDPI, &box, rotateA, gFalse);
- startPage(page->getNum(), state);
- delete state;
- switch (rotateA) {
- case 0:
- default: // this should never happen
+ nStripes = (int)ceil((double)(sliceW * sliceH) /
+ (double)rasterizationSliceSize);
+ stripeH = (sliceH + nStripes - 1) / nStripes;
+
+ // render the stripes
+ for (stripeY = sliceY; stripeY < sliceH; stripeY += stripeH) {
+
+ // rasterize a stripe
+ page->makeBox(hDPI2, vDPI2, 0, useMediaBox, gFalse,
+ sliceX, stripeY, sliceW, stripeH, &box, &crop);
m0 = box.x2 - box.x1;
m1 = 0;
m2 = 0;
m3 = box.y2 - box.y1;
m4 = box.x1;
m5 = box.y1;
- break;
- case 90:
- m0 = 0;
- m1 = box.y2 - box.y1;
- m2 = -(box.x2 - box.x1);
- m3 = 0;
- m4 = box.x2;
- m5 = box.y1;
- break;
- case 180:
- m0 = -(box.x2 - box.x1);
- m1 = 0;
- m2 = 0;
- m3 = -(box.y2 - box.y1);
- m4 = box.x2;
- m5 = box.y2;
- break;
- case 270:
- m0 = 0;
- m1 = -(box.y2 - box.y1);
- m2 = box.x2 - box.x1;
- m3 = 0;
- m4 = box.x1;
- m5 = box.y2;
- break;
- }
-
- //~ need to add the process colors
-
- // draw the rasterized image
- bitmap = splashOut->getBitmap();
- w = bitmap->getWidth();
- h = bitmap->getHeight();
- writePS("gsave\n");
- writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
- m0, m1, m2, m3, m4, m5);
- switch (level) {
- case psLevel1:
- useBinary = globalParams->getPSBinary();
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}\n",
- w, h, w, -h, h,
- useBinary ? "Bin" : "");
- p = bitmap->getDataPtr();
- i = 0;
- if (useBinary) {
+ page->displaySlice(splashOut, hDPI2, vDPI2,
+ (360 - page->getRotate()) % 360, useMediaBox, crop,
+ sliceX, stripeY, sliceW, stripeH,
+ printing, abortCheckCbk, abortCheckCbkData);
+
+ // draw the rasterized image
+ bitmap = splashOut->getBitmap();
+ w = bitmap->getWidth();
+ h = bitmap->getHeight();
+ writePS("gsave\n");
+ writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
+ m0, m1, m2, m3, m4, m5);
+ switch (level) {
+ case psLevel1:
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n",
+ w, h, w, -h, h);
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ i = 0;
for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- hexBuf[i++] = *p++;
- if (i >= 64) {
- writePSBuf(hexBuf, i);
+ for (x = 0; x < w; ++x) {
+ writePSFmt("{0:02x}", *p++);
+ if (++i == 32) {
+ writePSChar('\n');
i = 0;
}
}
}
- } else {
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ break;
+ case psLevel1Sep:
+ writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n",
+ w, h, w, -h, h);
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ i = 0;
+ col[0] = col[1] = col[2] = col[3] = 0;
for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- digit = *p / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = *p++ % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
+ for (comp = 0; comp < 4; ++comp) {
+ for (x = 0; x < w; ++x) {
+ writePSFmt("{0:02x}", p[4*x + comp]);
+ col[comp] |= p[4*x + comp];
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
}
}
+ p -= bitmap->getRowSize();
}
- }
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
+ if (i != 0) {
+ writePSChar('\n');
}
- writePSBuf(hexBuf, i);
- }
- break;
- case psLevel1Sep:
- useBinary = globalParams->getPSBinary();
- p = bitmap->getDataPtr();
- isGray = gTrue;
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- if (p[4*x] != p[4*x + 1] || p[4*x] != p[4*x + 2]) {
- isGray = gFalse;
- y = h;
- break;
- }
+ if (col[0]) {
+ processColors |= psProcessCyan;
}
- p += bitmap->getRowSize();
- }
- writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n",
- w, h, w, -h, h,
- isGray ? "" : "Sep",
- useBinary ? "Bin" : "");
- p = bitmap->getDataPtr();
- i = 0;
- col[0] = col[1] = col[2] = col[3] = 0;
- if (isGray) {
- int g;
- if ((psProcessBlack & processColors) == 0) {
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- if (p[4*x] > 0 || p[4*x + 3] > 0) {
- col[3] = 1;
- y = h;
- break;
- }
- }
- p += bitmap->getRowSize();
- }
- p = bitmap->getDataPtr();
+ if (col[1]) {
+ processColors |= psProcessMagenta;
}
- for (y = 0; y < h; ++y) {
- if (useBinary) {
- for (x = 0; x < w; ++x) {
- g = p[4*x] + p[4*x + 3];
- g = 255 - g;
- if (g < 0) g = 0;
- hexBuf[i++] = (Guchar) g;
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- } else {
- for (x = 0; x < w; ++x) {
- g = p[4*x] + p[4*x + 3];
- g = 255 - g;
- if (g < 0) g = 0;
- digit = g / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = g % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- p += bitmap->getRowSize();
+ if (col[2]) {
+ processColors |= psProcessYellow;
}
- } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) {
- for (y = 0; y < h; ++y) {
- for (comp = 0; comp < 4; ++comp) {
- if (useBinary) {
- for (x = 0; x < w; ++x) {
- col[comp] |= p[4*x + comp];
- hexBuf[i++] = p[4*x + comp];
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- } else {
- for (x = 0; x < w; ++x) {
- col[comp] |= p[4*x + comp];
- digit = p[4*x + comp] / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = p[4*x + comp] % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- }
- p += bitmap->getRowSize();
+ if (col[3]) {
+ processColors |= psProcessBlack;
}
- } else {
- for (y = 0; y < h; ++y) {
- for (comp = 0; comp < 4; ++comp) {
- if (useBinary) {
- for (x = 0; x < w; ++x) {
- hexBuf[i++] = p[4*x + comp];
- if (i >= 64) {
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- } else {
- for (x = 0; x < w; ++x) {
- digit = p[4*x + comp] / 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- digit = p[4*x + comp] % 16;
- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
- if (i >= 64) {
- hexBuf[i++] = '\n';
- writePSBuf(hexBuf, i);
- i = 0;
- }
- }
- }
- }
- p += bitmap->getRowSize();
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ case psLevel3:
+ case psLevel3Sep:
+ if (mono) {
+ writePS("/DeviceGray setcolorspace\n");
+ } else {
+ writePS("/DeviceRGB setcolorspace\n");
}
- }
- if (i != 0) {
- if (!useBinary) {
- hexBuf[i++] = '\n';
+ writePS("<<\n /ImageType 1\n");
+ writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
+ writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
+ writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
+ writePS(" /BitsPerComponent 8\n");
+ if (mono) {
+ writePS(" /Decode [0 1]\n");
+ } else {
+ writePS(" /Decode [0 1 0 1 0 1]\n");
}
- writePSBuf(hexBuf, i);
- }
- if (col[0]) {
- processColors |= psProcessCyan;
- }
- if (col[1]) {
- processColors |= psProcessMagenta;
- }
- if (col[2]) {
- processColors |= psProcessYellow;
- }
- if (col[3]) {
- processColors |= psProcessBlack;
- }
- break;
- case psLevel2Sep:
- case psLevel3Sep:
- obj.initNull();
- str0 = new MemStream((char *)bitmap->getDataPtr(), 0, w * h * 4, &obj);
- isGray = gTrue;
- while ((compCyan = str0->getChar()) != EOF) {
- if (str0->getChar() != compCyan ||
- str0->getChar() != compCyan) {
- isGray = gFalse;
- break;
+ writePS(" /DataSource currentfile\n");
+ if (globalParams->getPSASCIIHex()) {
+ writePS(" /ASCIIHexDecode filter\n");
+ } else {
+ writePS(" /ASCII85Decode filter\n");
}
- str0->getChar();
- }
- str0->reset();
- if (isGray) {
- writePS("/DeviceGray setcolorspace\n");
- str = new RunLengthEncoder(new CMKYGrayEncoder(str0));
- } else {
- processColors |= psProcessCMYK;
- writePS("/DeviceCMYK setcolorspace\n");
+ writePS(" /RunLengthDecode filter\n");
+ writePS(">>\n");
+ writePS("image\n");
+ obj.initNull();
+ p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+ str0 = new MemStream((char *)p, 0, w * h * (mono ? 1 : 3), &obj);
str = new RunLengthEncoder(str0);
- }
- writePS("<<\n /ImageType 1\n");
- writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
- writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
- writePS(" /BitsPerComponent 8\n");
- if (isGray) {
- writePS(" /Decode [1 0]\n");
- } else {
- writePS(" /Decode [0 1 0 1 0 1 0 1]\n");
- }
- writePS(" /DataSource currentfile\n");
- useBinary = globalParams->getPSBinary();
- if (useBinary) {
- /* nothing to do */;
- } else if (globalParams->getPSASCIIHex()) {
- writePS(" /ASCIIHexDecode filter\n");
- } else {
- writePS(" /ASCII85Decode filter\n");
- }
- writePS(" /RunLengthDecode filter\n");
- writePS(">>\n");
- if (useBinary) {
- /* nothing to do */;
- } else if (globalParams->getPSASCIIHex()) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
- str->reset();
- if (useBinary) {
- int len = 0;
- while (str->getChar() != EOF) {
- len++;
+ if (globalParams->getPSASCIIHex()) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
}
str->reset();
- writePSFmt("%%BeginData: {0:d} Binary Bytes\n", len+6+1);
- }
- writePS("image\n");
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- if (useBinary) {
- writePS("\n%%EndData\n");
- } else if (isGray) {
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
+ delete str;
+ delete str0;
writePSChar('\n');
+ processColors |= mono ? psProcessBlack : psProcessCMYK;
+ break;
}
- str->close();
- delete str;
- delete str0;
- break;
- case psLevel2:
- case psLevel3:
- writePS("/DeviceRGB setcolorspace\n");
- writePS("<<\n /ImageType 1\n");
- writePSFmt(" /Width {0:d}\n", bitmap->getWidth());
- writePSFmt(" /Height {0:d}\n", bitmap->getHeight());
- writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
- writePS(" /BitsPerComponent 8\n");
- writePS(" /Decode [0 1 0 1 0 1]\n");
- writePS(" /DataSource currentfile\n");
- if (globalParams->getPSASCIIHex()) {
- writePS(" /ASCIIHexDecode filter\n");
- } else {
- writePS(" /ASCII85Decode filter\n");
- }
- writePS(" /RunLengthDecode filter\n");
- writePS(">>\n");
- writePS("image\n");
- obj.initNull();
- str0 = new MemStream((char *)bitmap->getDataPtr(), 0, w * h * 3, &obj);
- str = new RunLengthEncoder(str0);
- if (globalParams->getPSASCIIHex()) {
- str = new ASCIIHexEncoder(str);
- } else {
- str = new ASCII85Encoder(str);
- }
- str->reset();
- while ((c = str->getChar()) != EOF) {
- writePSChar(c);
- }
- str->close();
- delete str;
- delete str0;
- processColors |= psProcessCMYK;
- break;
+ writePS("grestore\n");
}
+
delete splashOut;
- writePS("grestore\n");
// finish the PS page
endPage();
return gFalse;
-#else
+
+#else // HAVE_SPLASH
+
+ error(errSyntaxWarning, -1,
+ "PDF page uses transparency and PSOutputDev was built without"
+ " the Splash rasterizer - output may not be correct");
return gTrue;
-#endif
+#endif // HAVE_SPLASH
}
void PSOutputDev::startPage(int pageNum, GfxState *state) {
- int x1, y1, x2, y2, width, height;
+ Page *page;
+ int x1, y1, x2, y2, width, height, t;
int imgWidth, imgHeight, imgWidth2, imgHeight2;
GBool landscape;
+ GooString *s;
if (mode == psModePS || mode == psModePSOrigPageSizes) {
@@ -3391,6 +3294,19 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
} else {
writePSFmt("%%Page: {0:d} {1:d}\n", pageNum, seqPage);
}
+ if (paperMatch) {
+ page = doc->getCatalog()->getPage(pageNum);
+ imgLLX = imgLLY = 0;
+ imgURX = (int)ceil(page->getMediaWidth());
+ imgURY = (int)ceil(page->getMediaHeight());
+ if (state->getRotate() == 90 || state->getRotate() == 270) {
+ t = imgURX;
+ imgURX = imgURY;
+ imgURY = t;
+ }
+ writePSFmt("%%PageMedia: {0:d}x{1:d}\n", imgURX, imgURY);
+ writePSFmt("%%PageBoundingBox: 0 0 {0:d} {1:d}\n", imgURX, imgURY);
+ }
if (mode != psModePSOrigPageSizes)
writePS("%%BeginPageSetup\n");
}
@@ -3446,20 +3362,25 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
height = y2 - y1;
tx = ty = 0;
// rotation and portrait/landscape mode
- if (rotate0 >= 0) {
+ if (paperMatch) {
+ rotate = (360 - state->getRotate()) % 360;
+ landscape = gFalse;
+ } else if (rotate0 >= 0) {
rotate = (360 - rotate0) % 360;
landscape = gFalse;
} else {
rotate = (360 - state->getRotate()) % 360;
if (rotate == 0 || rotate == 180) {
- if (width > height && width > imgWidth) {
+ if ((width < height && imgWidth > imgHeight && height > imgHeight) ||
+ (width > height && imgWidth < imgHeight && width > imgWidth)) {
rotate += 90;
landscape = gTrue;
} else {
landscape = gFalse;
}
} else { // rotate == 90 || rotate == 270
- if (height > width && height > imgWidth) {
+ if ((height < width && imgWidth > imgHeight && width > imgHeight) ||
+ (height > width && imgWidth < imgHeight && height > imgWidth)) {
rotate = 270 - rotate;
landscape = gTrue;
} else {
@@ -3469,6 +3390,9 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
}
writePSFmt("%%PageOrientation: {0:s}\n",
landscape ? "Landscape" : "Portrait");
+ if (paperMatch) {
+ writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
+ }
writePS("pdfStartPage\n");
if (rotate == 0) {
imgWidth2 = imgWidth;
@@ -3518,8 +3442,8 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
}
// center
if (tx0 >= 0 && ty0 >= 0) {
- tx += rotate == 0 ? tx0 : ty0;
- ty += rotate == 0 ? ty0 : -tx0;
+ tx += (rotate == 0 || rotate == 180) ? tx0 : ty0;
+ ty += (rotate == 0 || rotate == 180) ? ty0 : -tx0;
} else if (globalParams->getPSCenter()) {
if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) {
tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2;
@@ -3529,8 +3453,8 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
ty += (imgHeight2 - yScale * height) / 2;
}
}
- tx += rotate == 0 ? imgLLX : imgLLY;
- ty += rotate == 0 ? imgLLY : -imgLLX;
+ tx += (rotate == 0 || rotate == 180) ? imgLLX : imgLLY;
+ ty += (rotate == 0 || rotate == 180) ? imgLLY : -imgLLX;
if (tx != 0 || ty != 0) {
writePSFmt("{0:.6g} {1:.6g} translate\n", tx, ty);
}
@@ -3544,7 +3468,6 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
writePSFmt("{0:d} {1:d} {2:d} {3:d} re W\n", x1, y1, x2 - x1, y2 - y1);
}
- writePS("%%EndPageSetup\n");
++seqPage;
break;
@@ -3581,6 +3504,18 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) {
rotate = 0;
break;
}
+
+ if (customCodeCbk) {
+ if ((s = (*customCodeCbk)(this, psOutCustomPageSetup, pageNum,
+ customCodeCbkData))) {
+ writePS(s->getCString());
+ delete s;
+ }
+ }
+
+ if (mode == psModePS) {
+ writePS("%%EndPageSetup\n");
+ }
}
void PSOutputDev::endPage() {
@@ -3963,7 +3898,7 @@ void PSOutputDev::restoreTextPos(GfxState *state) {
void PSOutputDev::stroke(GfxState *state) {
doPath(state->getPath());
- if (t3String) {
+ if (inType3Char && t3FillColorOnly) {
// if we're construct a cacheable Type 3 glyph, we need to do
// everything in the fill color
writePS("Sf\n");
@@ -4019,6 +3954,7 @@ GBool PSOutputDev::tilingPatternFillL1(GfxState *state, Catalog *cat, Object *st
if (paintType == 2) {
writePSFmt("{0:.6g} 0 {1:.6g} {2:.6g} {3:.6g} {4:.6g} setcachedevice\n",
xStep, bbox[0], bbox[1], bbox[2], bbox[3]);
+ t3FillColorOnly = gTrue;
} else
{
if (x1 - 1 <= x0) {
@@ -4026,6 +3962,7 @@ GBool PSOutputDev::tilingPatternFillL1(GfxState *state, Catalog *cat, Object *st
} else {
writePSFmt("{0:.6g} 0 setcharwidth\n", xStep);
}
+ t3FillColorOnly = gFalse;
}
inType3Char = gTrue;
++numTilingPatterns;
@@ -4040,6 +3977,7 @@ GBool PSOutputDev::tilingPatternFillL1(GfxState *state, Catalog *cat, Object *st
// draw the tiles
writePSFmt("/xpdfTile{0:d} findfont setfont\n", numTilingPatterns);
+ writePS("fCol\n");
writePSFmt("gsave [{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] concat\n",
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
writePSFmt("{0:d} 1 {1:d} {{ {2:.6g} exch {3:.6g} mul m {4:d} 1 {5:d} {{ pop (x) show }} for }} for\n",
@@ -4240,7 +4178,10 @@ GBool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading,
double xMin, yMin, xMax, yMax;
double x0, y0, r0, x1, y1, r1, t0, t1;
double xa, ya, ra;
- double sz, xz, yz, sMin, sMax, sa, ta;
+ double sz, sMin, sMax, h, ta;
+ double sLeft, sRight, sTop, sBottom, sZero, sDiag;
+ GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero;
+ GBool haveSMin, haveSMax;
double theta, alpha, a1, a2;
GBool enclosed;
int i;
@@ -4259,19 +4200,25 @@ GBool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading,
// Compute the point at which r(s) = 0; check for the enclosed
// circles case; and compute the angles for the tangent lines.
- if (r0 == r1) {
- enclosed = x0 == x1 && y0 == y1;
+ // Compute the point at which r(s) = 0; check for the enclosed
+ // circles case; and compute the angles for the tangent lines.
+ h = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
+ if (h == 0) {
+ enclosed = gTrue;
+ theta = 0; // make gcc happy
+ sz = 0; // make gcc happy
+ } else if (r1 - r0 == 0) {
+ enclosed = gFalse;
theta = 0;
sz = 0; // make gcc happy
+ } else if (fabs(r1 - r0) >= h) {
+ enclosed = gTrue;
+ theta = 0; // make gcc happy
+ sz = 0; // make gcc happy
} else {
+ enclosed = gFalse;
sz = -r0 / (r1 - r0);
- xz = x0 + sz * (x1 - x0);
- yz = y0 + sz * (y1 - y0);
- enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0;
- theta = asin(r0 / sqrt((x0 - xz) * (x0 - xz) + (y0 - yz) * (y0 - yz)));
- if (r0 > r1) {
- theta = -theta;
- }
+ theta = asin((r1 - r0) / h);
}
if (enclosed) {
a1 = 0;
@@ -4291,59 +4238,101 @@ GBool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading,
sMin = 0;
sMax = 1;
} else {
- sMin = 1;
- sMax = 0;
- // solve for x(s) + r(s) = xMin
- if ((x1 + r1) - (x0 + r0) != 0) {
- sa = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // solve for x(s) - r(s) = xMax
- if ((x1 - r1) - (x0 - r0) != 0) {
- sa = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // solve for y(s) + r(s) = yMin
- if ((y1 + r1) - (y0 + r0) != 0) {
- sa = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // solve for y(s) - r(s) = yMax
- if ((y1 - r1) - (y0 - r0) != 0) {
- sa = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
- if (sa < sMin) {
- sMin = sa;
- } else if (sa > sMax) {
- sMax = sa;
- }
- }
- // check against sz
- if (r0 < r1) {
- if (sMin < sz) {
- sMin = sz;
- }
- } else if (r0 > r1) {
- if (sMax > sz) {
- sMax = sz;
- }
- }
- // check the 'extend' flags
- if (!shading->getExtend0() && sMin < 0) {
+ // solve x(sLeft) + r(sLeft) = xMin
+ if ((haveSLeft = fabs((x1 + r1) - (x0 + r0)) > 0.000001)) {
+ sLeft = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0));
+ } else {
+ sLeft = 0; // make gcc happy
+ }
+ // solve x(sRight) - r(sRight) = xMax
+ if ((haveSRight = fabs((x1 - r1) - (x0 - r0)) > 0.000001)) {
+ sRight = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0));
+ } else {
+ sRight = 0; // make gcc happy
+ }
+ // solve y(sBottom) + r(sBottom) = yMin
+ if ((haveSBottom = fabs((y1 + r1) - (y0 + r0)) > 0.000001)) {
+ sBottom = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0));
+ } else {
+ sBottom = 0; // make gcc happy
+ }
+ // solve y(sTop) - r(sTop) = yMax
+ if ((haveSTop = fabs((y1 - r1) - (y0 - r0)) > 0.000001)) {
+ sTop = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0));
+ } else {
+ sTop = 0; // make gcc happy
+ }
+ // solve r(sZero) = 0
+ if ((haveSZero = fabs(r1 - r0) > 0.000001)) {
+ sZero = -r0 / (r1 - r0);
+ } else {
+ sZero = 0; // make gcc happy
+ }
+ // solve r(sDiag) = sqrt((xMax-xMin)^2 + (yMax-yMin)^2)
+ if (haveSZero) {
+ sDiag = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ } else {
+ sDiag = 0; // make gcc happy
+ }
+ // compute sMin
+ if (shading->getExtend0()) {
+ sMin = 0;
+ haveSMin = gFalse;
+ if (x0 < x1 && haveSLeft && sLeft < 0) {
+ sMin = sLeft;
+ haveSMin = gTrue;
+ } else if (x0 > x1 && haveSRight && sRight < 0) {
+ sMin = sRight;
+ haveSMin = gTrue;
+ }
+ if (y0 < y1 && haveSBottom && sBottom < 0) {
+ if (!haveSMin || sBottom > sMin) {
+ sMin = sBottom;
+ haveSMin = gTrue;
+ }
+ } else if (y0 > y1 && haveSTop && sTop < 0) {
+ if (!haveSMin || sTop > sMin) {
+ sMin = sTop;
+ haveSMin = gTrue;
+ }
+ }
+ if (haveSZero && sZero < 0) {
+ if (!haveSMin || sZero > sMin) {
+ sMin = sZero;
+ }
+ }
+ } else {
sMin = 0;
}
- if (!shading->getExtend1() && sMax > 1) {
+ // compute sMax
+ if (shading->getExtend1()) {
+ sMax = 1;
+ haveSMax = gFalse;
+ if (x1 < x0 && haveSLeft && sLeft > 1) {
+ sMax = sLeft;
+ haveSMax = gTrue;
+ } else if (x1 > x0 && haveSRight && sRight > 1) {
+ sMax = sRight;
+ haveSMax = gTrue;
+ }
+ if (y1 < y0 && haveSBottom && sBottom > 1) {
+ if (!haveSMax || sBottom < sMax) {
+ sMax = sBottom;
+ haveSMax = gTrue;
+ }
+ } else if (y1 > y0 && haveSTop && sTop > 1) {
+ if (!haveSMax || sTop < sMax) {
+ sMax = sTop;
+ haveSMax = gTrue;
+ }
+ }
+ if (haveSZero && sDiag > 1) {
+ if (!haveSMax || sDiag < sMax) {
+ sMax = sDiag;
+ }
+ }
+ } else {
sMax = 1;
}
}
@@ -4514,13 +4503,14 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
int wMode;
int *codeToGID;
GooString *s2;
- double dx, dy, dx2, dy2, originX, originY;
+ double dx, dy, originX, originY;
char *p;
UnicodeMap *uMap;
CharCode code;
Unicode *u;
char buf[8];
- int len, nChars, uLen, n, m, i, j;
+ double *dxdy;
+ int dxdySize, len, nChars, uLen, n, m, i, j;
// for pdftohtml, output PS without text
if( displayText == gFalse )
@@ -4549,6 +4539,10 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
for (i = 0; i < font16EncLen; ++i) {
if (font->getID()->num == font16Enc[i].fontID.num &&
font->getID()->gen == font16Enc[i].fontID.gen) {
+ if (!font16Enc[i].enc) {
+ // font substitution failed, so don't output any text
+ return;
+ }
uMap = globalParams->getUnicodeMap(font16Enc[i].enc);
break;
}
@@ -4565,63 +4559,89 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
}
}
- // compute width of chars in string, ignoring char spacing and word
- // spacing -- the Tj operator will adjust for the metrics of the
- // font that's actually used
- dx = dy = 0;
+ // compute the positioning (dx, dy) for each char in the string
nChars = 0;
p = s->getCString();
len = s->getLength();
s2 = new GooString();
+ dxdySize = font->isCIDFont() ? 8 : s->getLength();
+ dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double));
while (len > 0) {
n = font->getNextChar(p, len, &code,
&u, &uLen,
- &dx2, &dy2, &originX, &originY);
+ &dx, &dy, &originX, &originY);
+ dx *= state->getFontSize();
+ dy *= state->getFontSize();
+ if (wMode) {
+ dy += state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dy += state->getWordSpace();
+ }
+ } else {
+ dx += state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dx += state->getWordSpace();
+ }
+ }
+ dx *= state->getHorizScaling();
if (font->isCIDFont()) {
if (uMap) {
+ if (nChars + uLen > dxdySize) {
+ do {
+ dxdySize *= 2;
+ } while (nChars + uLen > dxdySize);
+ dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
+ }
for (i = 0; i < uLen; ++i) {
m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf));
for (j = 0; j < m; ++j) {
s2->append(buf[j]);
}
+ //~ this really needs to get the number of chars in the target
+ //~ encoding - which may be more than the number of Unicode
+ //~ chars
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
}
- //~ this really needs to get the number of chars in the target
- //~ encoding - which may be more than the number of Unicode
- //~ chars
- nChars += uLen;
} else {
+ if (nChars + 1 > dxdySize) {
+ dxdySize *= 2;
+ dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double));
+ }
s2->append((char)((code >> 8) & 0xff));
s2->append((char)(code & 0xff));
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
++nChars;
}
} else {
if (!codeToGID || codeToGID[code] >= 0) {
s2->append((char)code);
+ dxdy[2 * nChars] = dx;
+ dxdy[2 * nChars + 1] = dy;
+ ++nChars;
}
}
- dx += dx2;
- dy += dy2;
p += n;
len -= n;
}
- dx *= state->getFontSize() * state->getHorizScaling();
- dy *= state->getFontSize();
if (uMap) {
uMap->decRefCnt();
}
- if (s2->getLength() > 0) {
+ if (nChars > 0) {
writePSString(s2);
- if (font->isCIDFont()) {
- if (wMode) {
- writePSFmt(" {0:d} {1:.6g} Tj16V\n", nChars, dy);
- } else {
- writePSFmt(" {0:d} {1:.6g} Tj16\n", nChars, dx);
+ writePS("\n[");
+ for (i = 0; i < 2 * nChars; ++i) {
+ if (i > 0) {
+ writePS("\n");
}
- } else {
- writePSFmt(" {0:.6g} Tj\n", dx);
+ writePSFmt("{0:.6g}", dxdy[i]);
}
+ writePS("] Tj\n");
}
+ gfree(dxdy);
delete s2;
if (state->getRender() & 4) {
@@ -4794,7 +4814,7 @@ void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap,
delete str;
} else {
// make sure the image is setup, it sometimes is not like on bug #17645
- setupImage(ref->getRef(), str);
+ setupImage(ref->getRef(), str, gFalse);
// set up to use the array already created by setupImages()
writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
}
@@ -5378,7 +5398,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
delete str2;
} else {
// make sure the image is setup, it sometimes is not like on bug #17645
- setupImage(ref->getRef(), str);
+ setupImage(ref->getRef(), str, gFalse);
// set up to use the array already created by setupImages()
writePSFmt("ImData_{0:d}_{1:d} 0 0\n",ref->getRefNum(), ref->getRefGen());
}
@@ -5435,7 +5455,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
// data source
if (mode == psModeForm || inType3Char || preload) {
if (inlineImg) {
- writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
+ writePS(" /DataSource { pdfImStr }\n");
} else {
writePS(" /DataSource { dup 65535 ge { pop 1 add 0 } if 2 index 2"
" index get 1 index get exch 1 add exch }\n");
@@ -5445,18 +5465,26 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
}
// filters
- s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
- if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
- inlineImg || !s) {
- useRLE = gTrue;
- useASCII = !(mode == psModeForm || inType3Char || preload);
+ if ((mode == psModeForm || inType3Char || preload) &&
+ globalParams->getPSUncompressPreloadedImages()) {
+ s = NULL;
+ useRLE = gFalse;
useCompressed = gFalse;
+ useASCII = gFalse;
} else {
- useRLE = gFalse;
- useASCII = str->isBinary() &&
- !(mode == psModeForm || inType3Char || preload);
- useCompressed = gTrue;
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
+ " ");
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
+ inlineImg || !s) {
+ useRLE = gTrue;
+ useASCII = !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gFalse;
+ } else {
+ useRLE = gFalse;
+ useASCII = str->isBinary() &&
+ !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gTrue;
+ }
}
if (useASCII) {
writePSFmt(" /ASCII{0:s}Decode filter\n",
@@ -5594,6 +5622,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
int n, numComps;
GBool useRLE, useASCII, useASCIIHex, useCompressed;
GBool maskUseRLE, maskUseASCII, maskUseCompressed;
+ GooString *maskFilters;
GfxSeparationColorSpace *sepCS;
GfxColor color;
GfxCMYK cmyk;
@@ -5603,6 +5632,83 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
useASCIIHex = globalParams->getPSASCIIHex();
useRLE = useASCII = useCompressed = gFalse; // make gcc happy
maskUseRLE = maskUseASCII = maskUseCompressed = gFalse; // make gcc happy
+ maskFilters = NULL; // make gcc happy
+
+ // explicit masking
+ if (maskStr) {
+
+ // mask data source
+ if ((mode == psModeForm || inType3Char || preload) &&
+ globalParams->getPSUncompressPreloadedImages()) {
+ s = NULL;
+ maskUseRLE = gFalse;
+ maskUseCompressed = gFalse;
+ maskUseASCII = gFalse;
+ } else {
+ s = maskStr->getPSFilter(3, " ");
+ if (!s) {
+ maskUseRLE = gTrue;
+ maskUseASCII = !(mode == psModeForm || inType3Char || preload);
+ maskUseCompressed = gFalse;
+ } else {
+ maskUseRLE = gFalse;
+ maskUseASCII = maskStr->isBinary() &&
+ !(mode == psModeForm || inType3Char || preload);
+ maskUseCompressed = gTrue;
+ }
+ }
+ maskFilters = new GooString();
+ if (maskUseASCII) {
+ maskFilters->appendf(" /ASCII{0:s}Decode filter\n",
+ useASCIIHex ? "Hex" : "85");
+ }
+ if (maskUseRLE) {
+ maskFilters->append(" /RunLengthDecode filter\n");
+ }
+ if (maskUseCompressed) {
+ maskFilters->append(s);
+ }
+ if (s) {
+ delete s;
+ }
+ if (mode == psModeForm || inType3Char || preload) {
+ writePSFmt("MaskData_{0:d}_{1:d} pdfMaskInit\n",
+ ref->getRefNum(), ref->getRefGen());
+ } else {
+ writePS("currentfile\n");
+ writePS(maskFilters->getCString());
+ writePS("pdfMask\n");
+
+ // add RunLengthEncode and ASCIIHex/85 encode filters
+ if (maskUseCompressed) {
+ maskStr = maskStr->getUndecodedStream();
+ }
+ if (maskUseRLE) {
+ maskStr = new RunLengthEncoder(maskStr);
+ }
+ if (maskUseASCII) {
+ if (useASCIIHex) {
+ maskStr = new ASCIIHexEncoder(maskStr);
+ } else {
+ maskStr = new ASCII85Encoder(maskStr);
+ }
+ }
+
+ // copy the stream data
+ maskStr->reset();
+ while ((c = maskStr->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ maskStr->close();
+ writePSChar('\n');
+ writePS("%-EOD-\n");
+
+ // delete encoders
+ if (maskUseRLE || maskUseASCII) {
+ delete maskStr;
+ }
+ }
+ }
// color space
if (colorMap) {
@@ -5666,7 +5772,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
delete str2;
} else {
// make sure the image is setup, it sometimes is not like on bug #17645
- setupImage(ref->getRef(), str);
+ setupImage(ref->getRef(), str, gFalse);
// set up to use the array already created by setupImages()
writePSFmt("ImData_{0:d}_{1:d} 0 0\n", ref->getRefNum(), ref->getRefGen());
}
@@ -5740,7 +5846,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
// data source
if (mode == psModeForm || inType3Char || preload) {
if (inlineImg) {
- writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
+ writePS(" /DataSource { pdfImStr }\n");
} else {
writePS(" /DataSource { dup 65535 ge { pop 1 add 0 } if 2 index 2"
" index get 1 index get exch 1 add exch }\n");
@@ -5750,18 +5856,26 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
}
// filters
- s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
- if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
- inlineImg || !s) {
- useRLE = gTrue;
- useASCII = !(mode == psModeForm || inType3Char || preload);
+ if ((mode == psModeForm || inType3Char || preload) &&
+ globalParams->getPSUncompressPreloadedImages()) {
+ s = NULL;
+ useRLE = gFalse;
useCompressed = gFalse;
+ useASCII = gFalse;
} else {
- useRLE = gFalse;
- useASCII = str->isBinary() &&
- !(mode == psModeForm || inType3Char || preload);
- useCompressed = gTrue;
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
+ " ");
+ if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) ||
+ inlineImg || !s) {
+ useRLE = gTrue;
+ useASCII = !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gFalse;
+ } else {
+ useRLE = gFalse;
+ useASCII = str->isBinary() &&
+ !(mode == psModeForm || inType3Char || preload);
+ useCompressed = gTrue;
+ }
}
if (useASCII) {
writePSFmt(" /ASCII{0:s}Decode filter\n",
@@ -5794,30 +5908,13 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
maskInvert ? 1 : 0, maskInvert ? 0 : 1);
// mask data source
- writePS(" /DataSource currentfile\n");
- s = maskStr->getPSFilter(3, " ");
- if (!s) {
- maskUseRLE = gTrue;
- maskUseASCII = gTrue;
- maskUseCompressed = gFalse;
+ if (mode == psModeForm || inType3Char || preload) {
+ writePS(" /DataSource {pdfMaskSrc}\n");
+ writePS(maskFilters->getCString());
} else {
- maskUseRLE = gFalse;
- maskUseASCII = maskStr->isBinary();
- maskUseCompressed = gTrue;
- }
- if (maskUseASCII) {
- writePSFmt(" /ASCII{0:s}Decode filter\n",
- useASCIIHex ? "Hex" : "85");
- }
- if (maskUseRLE) {
- writePS(" /RunLengthDecode filter\n");
- }
- if (maskUseCompressed) {
- writePS(s->getCString());
- }
- if (s) {
- delete s;
+ writePS(" /DataSource maskStream\n");
}
+ delete maskFilters;
writePS(">>\n");
writePS(">>\n");
@@ -5845,39 +5942,6 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
}
- // explicit masking
- if (maskStr) {
-
- if (maskUseCompressed) {
- maskStr = maskStr->getUndecodedStream();
- }
-
- // add RunLengthEncode and ASCIIHex/85 encode filters
- if (maskUseRLE) {
- maskStr = new RunLengthEncoder(maskStr);
- }
- if (maskUseASCII) {
- if (useASCIIHex) {
- maskStr = new ASCIIHexEncoder(maskStr);
- } else {
- maskStr = new ASCII85Encoder(maskStr);
- }
- }
-
- // copy the stream data
- maskStr->reset();
- while ((c = maskStr->getChar()) != EOF) {
- writePSChar(c);
- }
- maskStr->close();
- writePSChar('\n');
-
- // delete encoders
- if (maskUseRLE || maskUseASCII) {
- delete maskStr;
- }
- }
-
// get rid of the array and index
if (mode == psModeForm || inType3Char || preload) {
if (!inlineImg) writePS("pop ");
@@ -5926,6 +5990,13 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
delete str;
}
}
+
+ // close the mask stream
+ if (maskStr) {
+ if (!(mode == psModeForm || inType3Char || preload)) {
+ writePS("pdfMaskEnd\n");
+ }
+ }
}
void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
@@ -6598,6 +6669,7 @@ void PSOutputDev::type3D1(GfxState *state, double wx, double wy,
t3URY = ury;
t3String = new GooString();
writePS("q\n");
+ t3FillColorOnly = gTrue;
t3Cacheable = gTrue;
t3NeedsRestore = gTrue;
}
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 4666c06..b2d49af 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -43,16 +43,20 @@
#include "GlobalParams.h"
#include "OutputDev.h"
+class GHooash;
+class PDFDoc;
+class XRef;
+class Function;
class GfxPath;
class GfxFont;
class GfxColorSpace;
class GfxSeparationColorSpace;
class PDFRectangle;
+struct PST1FontName;
struct PSFont8Info;
struct PSFont16Enc;
class PSOutCustomColor;
-class Function;
-class PDFDoc;
+class PSOutputDev;
//------------------------------------------------------------------------
// PSOutputDev
@@ -72,8 +76,17 @@ enum PSFileType {
psGeneric // write to a generic stream
};
+enum PSOutCustomCodeLocation {
+ psOutCustomDocSetup,
+ psOutCustomPageSetup
+};
+
typedef void (*PSOutputFunc)(void *stream, const char *data, int len);
+typedef GooString *(*PSOutCustomCodeCbk)(PSOutputDev *psOut,
+ PSOutCustomCodeLocation loc, int n,
+ void *data);
+
class PSOutputDev: public OutputDev {
public:
@@ -85,8 +98,9 @@ public:
GBool duplexA = gTrue,
int imgLLXA = 0, int imgLLYA = 0,
int imgURXA = 0, int imgURYA = 0,
- GBool forceRasterizeA = gFalse,
- GBool manualCtrlA = gFalse);
+ GBool manualCtrlA = gFalse,
+ PSOutCustomCodeCbk customCodeCbkA = NULL,
+ void *customCodeCbkDataA = NULL);
// Open a PSOutputDev that will write to a generic stream.
PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
@@ -97,8 +111,9 @@ public:
GBool duplexA = gTrue,
int imgLLXA = 0, int imgLLYA = 0,
int imgURXA = 0, int imgURYA = 0,
- GBool forceRasterizeA = gFalse,
- GBool manualCtrlA = gFalse);
+ GBool manualCtrlA = gFalse,
+ PSOutCustomCodeCbk customCodeCbkA = NULL,
+ void *customCodeCbkDataA = NULL);
// Destructor -- writes the trailer and closes the file.
virtual ~PSOutputDev();
@@ -310,7 +325,7 @@ private:
void setupType3Font(GfxFont *font, GooString *psName, Dict *parentResDict);
GooString *makePSFontName(GfxFont *font, Ref *id);
void setupImages(Dict *resDict);
- void setupImage(Ref id, Stream *str);
+ void setupImage(Ref id, Stream *str, GBool mask);
void setupForms(Dict *resDict);
void setupForm(Ref id, Object *strObj);
void addProcessColor(double c, double m, double y, double k);
@@ -376,6 +391,7 @@ private:
PSOutMode mode; // PostScript mode (PS, EPS, form)
int paperWidth; // width of paper, in pts
int paperHeight; // height of paper, in pts
+ GBool paperMatch; // true if paper size is set to match each page
int prevWidth; // width of previous page
// (only psModePSOrigPageSizes output mode)
int prevHeight; // height of previous page
@@ -394,6 +410,10 @@ private:
void *underlayCbkData;
void (*overlayCbk)(PSOutputDev *psOut, void *data);
void *overlayCbkData;
+ GooString *(*customCodeCbk)(PSOutputDev *psOut,
+ PSOutCustomCodeLocation loc, int n,
+ void *data);
+ void *customCodeCbkData;
PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
@@ -402,15 +422,9 @@ private:
int fontIDLen; // number of entries in fontIDs array
int fontIDSize; // size of fontIDs array
GooHash *fontNames; // all used font names
- Ref *fontFileIDs; // list of object IDs of all embedded fonts
- int fontFileIDLen; // number of entries in fontFileIDs array
- int fontFileIDSize; // size of fontFileIDs array
- GooString **fontFileNames; // list of names of all embedded external fonts
- GooString **psFileNames; // list of names of all embedded external fonts
- int fontFileNameLen; // number of entries in fontFileNames array
- int fontFileNameSize; // size of fontFileNames array
- int nextTrueTypeNum; // next unique number to append to a TrueType
- // font name
+ PST1FontName *t1FontNames; // font names for Type 1/1C fonts
+ int t1FontNameLen; // number of entries in t1FontNames array
+ int t1FontNameSize; // size of t1FontNames array
PSFont8Info *font8Info; // info for 8-bit fonts
int font8InfoLen; // number of entries in font8Info array
int font8InfoSize; // size of font8Info array
@@ -429,6 +443,8 @@ private:
int numTilingPatterns; // current number of nested tiling patterns
int nextFunc; // next unique number to use for a function
+ GooList *paperSizes; // list of used paper sizes, if paperMatch
+ // is true [PSOutPaperSize]
double tx0, ty0; // global translation
double xScale0, yScale0; // global scaling
int rotate0; // rotation angle (0, 90, 180, 270)
@@ -453,9 +469,9 @@ private:
GooString *t3String; // Type 3 content string
double t3WX, t3WY, // Type 3 character parameters
t3LLX, t3LLY, t3URX, t3URY;
+ GBool t3FillColorOnly; // operators should only use the fill color
GBool t3Cacheable; // cleared if char is not cacheable
GBool t3NeedsRestore; // set if a 'q' operator was issued
- GBool forceRasterize; // forces the page to be rasterized into a image before printing
GBool displayText; // displayText
#if OPI_SUPPORT
@@ -465,7 +481,6 @@ private:
GBool ok; // set up ok?
-
friend class WinPDFPrinter;
};
diff --git a/poppler/Parser.cc b/poppler/Parser.cc
index 03b836e..400d8d7 100644
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@ -59,10 +59,11 @@ Parser::~Parser() {
Object *Parser::getObj(Object *obj, int recursion)
{
- return getObj(obj, NULL, cryptRC4, 0, 0, 0, recursion);
+ return getObj(obj, gFalse, NULL, cryptRC4, 0, 0, 0, recursion);
}
-Object *Parser::getObj(Object *obj, Guchar *fileKey,
+Object *Parser::getObj(Object *obj, GBool simpleOnly,
+ Guchar *fileKey,
CryptAlgorithm encAlgorithm, int keyLength,
int objNum, int objGen, int recursion) {
char *key;
@@ -83,18 +84,18 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
}
// array
- if (likely(recursion < recursionLimit) && buf1.isCmd("[")) {
+ if (!simpleOnly && likely(recursion < recursionLimit) && buf1.isCmd("[")) {
shift();
obj->initArray(xref);
while (!buf1.isCmd("]") && !buf1.isEOF())
- obj->arrayAdd(getObj(&obj2, fileKey, encAlgorithm, keyLength,
+ obj->arrayAdd(getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength,
objNum, objGen, recursion + 1));
if (buf1.isEOF())
error(errSyntaxError, getPos(), "End of file inside array");
shift();
// dictionary or stream
- } else if (likely(recursion < recursionLimit) && buf1.isCmd("<<")) {
+ } else if (!simpleOnly && likely(recursion < recursionLimit) && buf1.isCmd("<<")) {
shift(objNum);
obj->initDict(xref);
while (!buf1.isCmd(">>") && !buf1.isEOF()) {
@@ -109,7 +110,7 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
gfree(key);
break;
}
- obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength, objNum, objGen, recursion + 1));
+ obj->dictAdd(key, getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength, objNum, objGen, recursion + 1));
}
}
if (buf1.isEOF())
diff --git a/poppler/Parser.h b/poppler/Parser.h
index f1fa765..69cfc25 100644
--- a/poppler/Parser.h
+++ b/poppler/Parser.h
@@ -42,8 +42,11 @@ public:
// Destructor.
~Parser();
- // Get the next object from the input stream.
- Object *getObj(Object *obj, Guchar *fileKey = NULL,
+ // Get the next object from the input stream. If <simpleOnly> is
+ // true, do not parse compound objects (arrays, dictionaries, or
+ // streams).
+ Object *getObj(Object *obj, GBool simpleOnly = gFalse,
+ Guchar *fileKey = NULL,
CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0,
int objNum = 0, int objGen = 0, int recursion = 0);
diff --git a/poppler/PreScanOutputDev.cc b/poppler/PreScanOutputDev.cc
index d77bb5a..3a86d52 100644
--- a/poppler/PreScanOutputDev.cc
+++ b/poppler/PreScanOutputDev.cc
@@ -95,6 +95,46 @@ GBool PreScanOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *ca
return gTrue;
}
+GBool PreScanOutputDev::functionShadedFill(GfxState *state,
+ GfxFunctionShading *shading) {
+ if (shading->getColorSpace()->getMode() != csDeviceGray &&
+ shading->getColorSpace()->getMode() != csCalGray) {
+ gray = gFalse;
+ }
+ mono = gFalse;
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
+ transparency = gTrue;
+ }
+ return gTrue;
+}
+
+GBool PreScanOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double /*tMin*/, double /*tMax*/) {
+ if (shading->getColorSpace()->getMode() != csDeviceGray &&
+ shading->getColorSpace()->getMode() != csCalGray) {
+ gray = gFalse;
+ }
+ mono = gFalse;
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
+ transparency = gTrue;
+ }
+ return gTrue;
+}
+
+GBool PreScanOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/) {
+ if (shading->getColorSpace()->getMode() != csDeviceGray &&
+ shading->getColorSpace()->getMode() != csCalGray) {
+ gray = gFalse;
+ }
+ mono = gFalse;
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
+ transparency = gTrue;
+ }
+ return gTrue;
+}
+
void PreScanOutputDev::clip(GfxState * /*state*/) {
//~ check for a rectangle "near" the edge of the page;
//~ else set gdi to false
@@ -161,7 +201,7 @@ void PreScanOutputDev::drawImageMask(GfxState *state, Object * /*ref*/, Stream *
gdi = gFalse;
if ((level == psLevel1 || level == psLevel1Sep) &&
state->getFillColorSpace()->getMode() == csPattern) {
- level1PSBug = gTrue;
+ patternImgMask = gTrue;
}
if (inlineImg) {
@@ -184,12 +224,17 @@ void PreScanOutputDev::drawImage(GfxState *state, Object * /*ref*/, Stream *str,
if (colorSpace->getMode() == csIndexed) {
colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
}
- if (colorSpace->getMode() != csDeviceGray &&
- colorSpace->getMode() != csCalGray) {
+ if (colorSpace->getMode() == csDeviceGray ||
+ colorSpace->getMode() == csCalGray) {
+ if (colorMap->getBits() > 1) {
+ mono = gFalse;
+ }
+ } else {
gray = gFalse;
+ mono = gFalse;
}
- mono = gFalse;
- if (state->getBlendMode() != gfxBlendNormal) {
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
transparency = gTrue;
}
gdi = gFalse;
@@ -218,12 +263,17 @@ void PreScanOutputDev::drawMaskedImage(GfxState *state, Object * /*ref*/,
if (colorSpace->getMode() == csIndexed) {
colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase();
}
- if (colorSpace->getMode() != csDeviceGray &&
- colorSpace->getMode() != csCalGray) {
+ if (colorSpace->getMode() == csDeviceGray ||
+ colorSpace->getMode() == csCalGray) {
+ if (colorMap->getBits() > 1) {
+ mono = gFalse;
+ }
+ } else {
gray = gFalse;
+ mono = gFalse;
}
- mono = gFalse;
- if (state->getBlendMode() != gfxBlendNormal) {
+ if (state->getFillOpacity() != 1 ||
+ state->getBlendMode() != gfxBlendNormal) {
transparency = gTrue;
}
gdi = gFalse;
@@ -303,5 +353,5 @@ void PreScanOutputDev::clearStats() {
gray = gTrue;
transparency = gFalse;
gdi = gTrue;
- level1PSBug = gFalse;
+ patternImgMask = gFalse;
}
diff --git a/poppler/PreScanOutputDev.h b/poppler/PreScanOutputDev.h
index ac147f3..5260a3b 100644
--- a/poppler/PreScanOutputDev.h
+++ b/poppler/PreScanOutputDev.h
@@ -64,6 +64,11 @@ public:
// operations.
virtual GBool useTilingPatternFill() { return gTrue; }
+ // Does this device use functionShadedFill(), axialShadedFill(), and
+ // radialShadedFill()? If this returns false, these shaded fills
+ // will be reduced to a series of other drawing operations.
+ virtual GBool useShadedFills(int type) { return gTrue; }
+
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gTrue; }
@@ -85,6 +90,10 @@ public:
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
double xStep, double yStep);
+ virtual GBool functionShadedFill(GfxState *state,
+ GfxFunctionShading *shading);
+ virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax);
+ virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double tMin, double tMax);
//----- path clipping
virtual void clip(GfxState *state);
@@ -148,8 +157,9 @@ public:
GBool isAllGDI() { return gdi; }
// Returns true if the operations performed since the last call to
- // clearStats() processed a feature that PSOutputDev does not implement.
- GBool hasLevel1PSBug() { return level1PSBug; }
+ // clearStats() included any image mask fills with a pattern color
+ // space. (only level1!)
+ GBool usesPatternImageMask() { return patternImgMask; }
// Clear the stats used by the above functions.
void clearStats();
@@ -165,7 +175,7 @@ private:
GBool transparency;
GBool gdi;
PSLevel level; // PostScript level (1, 2, separation)
- GBool level1PSBug; // gTrue if it uses a feature not supported in PSOutputDev
+ GBool patternImgMask;
};
#endif
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index c455d6a..9fdb7c0 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -260,6 +260,7 @@ void XRef::init() {
entries = NULL;
capacity = 0;
size = 0;
+ last = -1;
streamEnds = NULL;
streamEndsLen = 0;
objStrs = new PopplerCache(5);
@@ -430,7 +431,7 @@ GBool XRef::readXRef(Guint *pos, std::vector<Guint> *followedXRefStm) {
new Lexer(NULL,
str->makeSubStream(start + *pos, gFalse, 0, &obj)),
gTrue);
- parser->getObj(&obj);
+ parser->getObj(&obj, gTrue);
// parse an old-style xref table
if (obj.isCmd("xref")) {
@@ -440,11 +441,11 @@ GBool XRef::readXRef(Guint *pos, std::vector<Guint> *followedXRefStm) {
// parse an xref stream
} else if (obj.isInt()) {
obj.free();
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
obj.free();
- if (!parser->getObj(&obj)->isCmd("obj")) {
+ if (!parser->getObj(&obj, gTrue)->isCmd("obj")) {
goto err1;
}
obj.free();
@@ -479,7 +480,7 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *follow
int first, n, i;
while (1) {
- parser->getObj(&obj);
+ parser->getObj(&obj, gTrue);
if (obj.isCmd("trailer")) {
obj.free();
break;
@@ -489,7 +490,7 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *follow
}
first = obj.getInt();
obj.free();
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
n = obj.getInt();
@@ -504,19 +505,19 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *follow
}
}
for (i = first; i < first + n; ++i) {
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
entry.offset = (Guint)obj.getInt();
obj.free();
- if (!parser->getObj(&obj)->isInt()) {
+ if (!parser->getObj(&obj, gTrue)->isInt()) {
goto err1;
}
entry.gen = obj.getInt();
entry.obj.initNull ();
entry.updated = false;
obj.free();
- parser->getObj(&obj);
+ parser->getObj(&obj, gTrue);
if (obj.isCmd("n")) {
entry.type = xrefEntryUncompressed;
} else if (obj.isCmd("f")) {
@@ -537,6 +538,9 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *follow
entries[0] = entries[1];
entries[1].offset = 0xffffffff;
}
+ if (i > last) {
+ last = i;
+ }
}
}
}
@@ -549,13 +553,25 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos, std::vector<Guint> *follow
// get the 'Prev' pointer
obj.getDict()->lookupNF("Prev", &obj2);
if (obj2.isInt()) {
- *pos = (Guint)obj2.getInt();
- more = gTrue;
+ pos2 = (Guint)obj2.getInt();
+ if (pos2 != *pos) {
+ *pos = pos2;
+ more = gTrue;
+ } else {
+ error(errSyntaxWarning, -1, "Infinite loop in xref table");
+ more = gFalse;
+ }
} else if (obj2.isRef()) {
// certain buggy PDF generators generate "/Prev NNN 0 R" instead
// of "/Prev NNN"
- *pos = (Guint)obj2.getRefNum();
- more = gTrue;
+ pos2 = (Guint)obj2.getRefNum();
+ if (pos2 != *pos) {
+ *pos = pos2;
+ more = gTrue;
+ } else {
+ error(errSyntaxWarning, -1, "Infinite loop in xref table");
+ more = gFalse;
+ }
} else {
more = gFalse;
}
@@ -743,6 +759,9 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
default:
return gFalse;
}
+ if (i > last) {
+ last = i;
+ }
}
}
@@ -769,7 +788,6 @@ GBool XRef::constructXRef(GBool *wasReconstructed) {
size = 0;
entries = NULL;
- error(errSyntaxWarning, -1, "PDF file is damaged - attempting to reconstruct xref table...");
gotRoot = gFalse;
streamEndsLen = streamEndsSize = 0;
@@ -826,32 +844,32 @@ GBool XRef::constructXRef(GBool *wasReconstructed) {
delete parser;
// look for object
- } else if (*p > 0 && isdigit(*p)) {
- num = atoi(p);
- if (num > 0) {
+ } else if (isdigit(*p & 0xff)) {
+ num = atoi(p);
+ if (num > 0) {
+ do {
+ ++p;
+ } while (*p && isdigit(*p & 0xff));
+ if (isspace(*p & 0xff)) {
do {
++p;
- } while (*p > 0 && isdigit(*p));
- if (*p > 0 && isspace(*p)) {
+ } while (*p && isspace(*p & 0xff));
+ if (isdigit(*p & 0xff)) {
+ gen = atoi(p);
do {
++p;
- } while (*p > 0 && isspace(*p));
- if (*p > 0 && isdigit(*p)) {
- gen = atoi(p);
+ } while (*p && isdigit(*p & 0xff));
+ if (isspace(*p & 0xff)) {
do {
- ++p;
- } while (*p > 0 && isdigit(*p));
- if (*p > 0 && isspace(*p)) {
- do {
- ++p;
- } while (*p > 0 && isspace(*p));
- if (!strncmp(p, "obj", 3)) {
- if (num >= size) {
- newSize = (num + 1 + 255) & ~255;
- if (newSize < 0) {
- error(errSyntaxError, -1, "Bad object number");
- return gFalse;
- }
+ ++p;
+ } while (*p && isspace(*p & 0xff));
+ if (!strncmp(p, "obj", 3)) {
+ if (num >= size) {
+ newSize = (num + 1 + 255) & ~255;
+ if (newSize < 0) {
+ error(errSyntaxError, -1, "Bad object number");
+ return gFalse;
+ }
if (resize(newSize) != newSize) {
error(errSyntaxError, -1, "Invalid 'obj' parameters");
return gFalse;
@@ -862,7 +880,10 @@ GBool XRef::constructXRef(GBool *wasReconstructed) {
entries[num].offset = pos - start;
entries[num].gen = gen;
entries[num].type = xrefEntryUncompressed;
+ if (num > last) {
+ last = num;
}
+ }
}
}
}
@@ -1030,7 +1051,7 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
delete parser;
goto err;
}
- parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL,
+ parser->getObj(obj, gFalse, encrypted ? fileKey : (Guchar *)NULL,
encAlgorithm, keyLength, num, gen, recursion);
obj1.free();
obj2.free();
diff --git a/poppler/XRef.h b/poppler/XRef.h
index adfdc1a..848947c 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -109,7 +109,7 @@ public:
Object *getDocInfoNF(Object *obj);
// Return the number of objects in the xref table.
- int getNumObjects() { return size; }
+ int getNumObjects() { return last + 1; }
// Return the catalog object reference.
int getRootNum() { return rootNum; }
@@ -141,6 +141,7 @@ private:
XRefEntry *entries; // xref entries
int capacity; // size of <entries> array
int size; // number of entries
+ int last; // last used index in <entries>
int rootNum, rootGen; // catalog dict
GBool ok; // true if xref table is valid
int errCode; // error code (if <ok> is false)
diff --git a/utils/pdftops.cc b/utils/pdftops.cc
index 7f5f511..542838b 100644
--- a/utils/pdftops.cc
+++ b/utils/pdftops.cc
@@ -273,7 +273,7 @@ int main(int argc, char *argv[]) {
globalParams->setPSLevel(level);
}
if (splashResolution > 0) {
- globalParams->setSplashResolution(splashResolution);
+ globalParams->setPSRasterResolution(splashResolution);
}
if (noEmbedT1Fonts) {
globalParams->setPSEmbedType1(!noEmbedT1Fonts);
More information about the poppler
mailing list