From feb59a5d4f65470a4574082b46b05f0358894f95 Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:38:57 +0200 Subject: [PATCH 01/10] Update aconf --- Makefile | 6 ++++-- src/xpdf-4.04/aconf.h | 33 +++++++++++++++++++++----------- src/xpdf-4.04/aconf.h.in | 27 ++++++++++++++++++++++---- src/xpdf-4.04/aconf2.h | 41 ---------------------------------------- 4 files changed, 49 insertions(+), 58 deletions(-) delete mode 100644 src/xpdf-4.04/aconf2.h diff --git a/Makefile b/Makefile index c28dc5c..97eb59d 100644 --- a/Makefile +++ b/Makefile @@ -163,8 +163,10 @@ clean: cleanft: rm -fv $(PROGNAME) $(FREE_OBJ) +install: + pip install . + test: - $(info $(FREE_DIRS)) - $(info $(SKIP_DIRS)) + python -m unittest -v -include $(OBJFILES:.o=.d) diff --git a/src/xpdf-4.04/aconf.h b/src/xpdf-4.04/aconf.h index 659efed..41dcd12 100644 --- a/src/xpdf-4.04/aconf.h +++ b/src/xpdf-4.04/aconf.h @@ -3,13 +3,21 @@ * * This file is modified by cmake. * - * Copyright 2002-2015 Glyph & Cog, LLC + * Copyright 2002-2022 Glyph & Cog, LLC */ #ifndef ACONF_H #define ACONF_H -#include +/* + * Speed up Windows compilation. This will only work for the command + * line tools. + */ +/* + *#ifdef _WIN32 + *# define WIN32_LEAN_AND_MEAN + *#endif + */ /* * Use A4 paper size instead of Letter for PostScript output. @@ -29,7 +37,7 @@ /* * Enable multithreading support. */ -#define MULTITHREADED 0 +#define MULTITHREADED 1 /* * Enable C++ exceptions. @@ -56,6 +64,11 @@ */ /* #undef HIGHLIGHTED_REGIONS */ +/* + * Enable support for XDG config/state file paths. + */ +#define USE_XDG 0 + /* * Full path for the system-wide xpdfrc file. */ @@ -67,6 +80,12 @@ */ /* #undef XPDFRC_DATADIR */ +/* + * Directory where the Base14 fonts are installed -- URW Type 1 fonts + * on Linux, system TrueType fonts on Windows + */ +/* #undef BASE14_FONT_DIR */ + /* * Various include files and functions. */ @@ -74,17 +93,9 @@ #define HAVE_MKSTEMPS 1 #define HAVE_POPEN #define HAVE_STD_SORT 1 - -#if defined(_WIN32) || defined(_WIN64) -#define HAVE_FSEEKO 0 -#define HAVE_FSEEK64 0 -#define HAVE_FSEEKI64 1 -#else #define HAVE_FSEEKO 1 #define HAVE_FSEEK64 0 #define HAVE_FSEEKI64 0 -#endif - #define _FILE_OFFSET_BITS 64 #define _LARGE_FILES 1 #define _LARGEFILE_SOURCE 1 diff --git a/src/xpdf-4.04/aconf.h.in b/src/xpdf-4.04/aconf.h.in index 99eb78b..8754db6 100644 --- a/src/xpdf-4.04/aconf.h.in +++ b/src/xpdf-4.04/aconf.h.in @@ -3,13 +3,21 @@ * * This file is modified by cmake. * - * Copyright 2002-2015 Glyph & Cog, LLC + * Copyright 2002-2022 Glyph & Cog, LLC */ #ifndef ACONF_H #define ACONF_H -#include +/* + * Speed up Windows compilation. This will only work for the command + * line tools. + */ +/* + *#ifdef _WIN32 + *# define WIN32_LEAN_AND_MEAN + *#endif + */ /* * Use A4 paper size instead of Letter for PostScript output. @@ -56,16 +64,27 @@ */ #cmakedefine HIGHLIGHTED_REGIONS +/* + * Enable support for XDG config/state file paths. + */ +#cmakedefine01 USE_XDG + /* * Full path for the system-wide xpdfrc file. */ -@SYSTEM_XPDFRC_DEFINE@ +#cmakedefine SYSTEM_XPDFRC "@SYSTEM_XPDFRC@" /* * Directory to use for the ${DATADIR} variable in the xpdfrc config * file. */ -@XPDFRC_DATADIR_DEFINE@ +#cmakedefine XPDFRC_DATADIR "@XPDFRC_DATADIR@" + +/* + * Directory where the Base14 fonts are installed -- URW Type 1 fonts + * on Linux, system TrueType fonts on Windows + */ +#cmakedefine BASE14_FONT_DIR "@BASE14_FONT_DIR@" /* * Various include files and functions. diff --git a/src/xpdf-4.04/aconf2.h b/src/xpdf-4.04/aconf2.h deleted file mode 100644 index 05d785c..0000000 --- a/src/xpdf-4.04/aconf2.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * aconf2.h - * - * This gets included by aconf.h, and contains miscellaneous global - * settings not directly controlled by autoconf. This is a separate - * file because otherwise the configure script will munge any - * #define/#undef constructs. - * - * Copyright 2002-2003 Glyph & Cog, LLC - */ - -#ifndef ACONF2_H -#define ACONF2_H - -/* - * This controls the use of the interface/implementation pragmas. - */ -#if defined(__GNUC__) && !defined(__clang__) -#define USE_GCC_PRAGMAS -#endif -/* There is a bug in the version of gcc which ships with MacOS X 10.2 */ -#if defined(__APPLE__) && defined(__MACH__) -# include -#endif -#ifdef MAC_OS_X_VERSION_MAX_ALLOWED -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 -# undef USE_GCC_PRAGMAS -# endif -#endif - -/* - * Speed up Windows compilation. This will only work for the command - * line tools. - */ -/* - *#ifdef _WIN32 - *# define WIN32_LEAN_AND_MEAN - *#endif - */ - -#endif From f44cded0d6d521d9faa48eba34fa30c05f8de02b Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:43:04 +0200 Subject: [PATCH 02/10] Update fofi --- src/xpdf-4.04/fofi/FoFiBase.cc | 4 - src/xpdf-4.04/fofi/FoFiBase.h | 4 - src/xpdf-4.04/fofi/FoFiEncodings.cc | 4 - src/xpdf-4.04/fofi/FoFiEncodings.h | 4 - src/xpdf-4.04/fofi/FoFiIdentifier.cc | 6 +- src/xpdf-4.04/fofi/FoFiIdentifier.h | 4 - src/xpdf-4.04/fofi/FoFiTrueType.cc | 68 +++++++-- src/xpdf-4.04/fofi/FoFiTrueType.h | 4 - src/xpdf-4.04/fofi/FoFiType1.cc | 9 +- src/xpdf-4.04/fofi/FoFiType1.h | 4 - src/xpdf-4.04/fofi/FoFiType1C.cc | 199 ++++++++++++++++++--------- src/xpdf-4.04/fofi/FoFiType1C.h | 4 - 12 files changed, 195 insertions(+), 119 deletions(-) diff --git a/src/xpdf-4.04/fofi/FoFiBase.cc b/src/xpdf-4.04/fofi/FoFiBase.cc index e1951b0..73cf2f5 100644 --- a/src/xpdf-4.04/fofi/FoFiBase.cc +++ b/src/xpdf-4.04/fofi/FoFiBase.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" diff --git a/src/xpdf-4.04/fofi/FoFiBase.h b/src/xpdf-4.04/fofi/FoFiBase.h index c9f93eb..ffa14cf 100644 --- a/src/xpdf-4.04/fofi/FoFiBase.h +++ b/src/xpdf-4.04/fofi/FoFiBase.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/fofi/FoFiEncodings.cc b/src/xpdf-4.04/fofi/FoFiEncodings.cc index 6b3debb..01ae5ac 100644 --- a/src/xpdf-4.04/fofi/FoFiEncodings.cc +++ b/src/xpdf-4.04/fofi/FoFiEncodings.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include "gmempp.h" #include "FoFiEncodings.h" diff --git a/src/xpdf-4.04/fofi/FoFiEncodings.h b/src/xpdf-4.04/fofi/FoFiEncodings.h index dd85458..6094387 100644 --- a/src/xpdf-4.04/fofi/FoFiEncodings.h +++ b/src/xpdf-4.04/fofi/FoFiEncodings.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/fofi/FoFiIdentifier.cc b/src/xpdf-4.04/fofi/FoFiIdentifier.cc index 4c6797b..fff1e26 100644 --- a/src/xpdf-4.04/fofi/FoFiIdentifier.cc +++ b/src/xpdf-4.04/fofi/FoFiIdentifier.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -843,6 +839,8 @@ static GList *getDfontFontList(FILE *f) { resNameListOffset >= resMapLength) { goto err2; } + nFonts = 0; + refListOffset = 0; for (i = 0; i < nTypes; ++i) { offset = resTypeListOffset + 2 + 8 * i; if (resMap[offset] == 0x73 && // 'sfnt' diff --git a/src/xpdf-4.04/fofi/FoFiIdentifier.h b/src/xpdf-4.04/fofi/FoFiIdentifier.h index b0307a0..497be44 100644 --- a/src/xpdf-4.04/fofi/FoFiIdentifier.h +++ b/src/xpdf-4.04/fofi/FoFiIdentifier.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class GList; //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/fofi/FoFiTrueType.cc b/src/xpdf-4.04/fofi/FoFiTrueType.cc index 57b12b1..a97b9fa 100644 --- a/src/xpdf-4.04/fofi/FoFiTrueType.cc +++ b/src/xpdf-4.04/fofi/FoFiTrueType.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #if HAVE_STD_SORT @@ -405,7 +401,7 @@ int FoFiTrueType::mapCodeToGID(int i, int c) { // to be 0xffff return 0; } - // invariant: seg[a].end < code <= seg[b].end + // invariant: seg[a].end < c <= seg[b].end while (b - a > 1 && ok) { m = (a + b) / 2; segEnd = getU16BE(pos + 14 + 2*m, &ok); @@ -439,6 +435,31 @@ int FoFiTrueType::mapCodeToGID(int i, int c) { } gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok); break; + case 12: + segCnt = getU32BE(pos + 12, &ok); + a = -1; + b = segCnt - 1; + segEnd = getU32BE(pos + 16 + 12*b + 4, &ok); + if (c > segEnd) { + return 0; + } + // invariant: seg[a].end < c <= seg[b].end + while (b - a > 1 && ok) { + m = (a + b) / 2; + segEnd = getU32BE(pos + 16 + 12*m + 4, &ok); + if (segEnd < c) { + a = m; + } else { + b = m; + } + } + segStart = getU32BE(pos + 16 + 12*b, &ok); + if (c < segStart) { + return 0; + } + segOffset = getU32BE(pos + 16 + 12*b + 8, &ok); + gid = segOffset + (c - segStart); + break; default: return 0; } @@ -1065,7 +1086,7 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, 0, 0, 0, 0 // ulCodePageRange2 }; GBool missingCmap, missingName, missingPost, missingOS2; - GBool unsortedLoca, emptyCmap, badCmapLen, abbrevHMTX; + GBool unsortedLoca, bogusLastLoca, emptyCmap, badCmapLen, abbrevHMTX; int nZeroLengthTables, nBogusTables; int nHMetrics, advWidth, lsb; TrueTypeLoca *locaTable; @@ -1098,6 +1119,7 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, // read the loca table, check to see if it's sorted locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); unsortedLoca = gFalse; + bogusLastLoca = gFalse; i = seekTable("loca"); pos = tables[i].offset; glyfLen = tables[seekTable("glyf")].len; @@ -1114,7 +1136,11 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, unsortedLoca = gTrue; } if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) { - unsortedLoca = gTrue; + if (i < nGlyphs) { + unsortedLoca = gTrue; + } else { + bogusLastLoca = gTrue; + } } // glyph descriptions must be at least 12 bytes long (nContours, // xMin, yMin, xMax, yMax, instructionLength - two bytes each); @@ -1131,6 +1157,9 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, } locaTable[i].idx = i; } + if (unsortedLoca) { + bogusLastLoca = gFalse; + } // check for zero-length tables and bogus tags nZeroLengthTables = nBogusTables = 0; @@ -1188,7 +1217,8 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, // if nothing is broken, just write the TTF file as is if (!missingCmap && !missingName && !missingPost && !missingOS2 && - !unsortedLoca && !emptyCmap && !badCmapLen && !abbrevHMTX && + !unsortedLoca && !bogusLastLoca && + !emptyCmap && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 && nBogusTables == 0 && !name && !codeToGID && !replacementCmapTable && !isDfont && !isTTC) { (*outputFunc)(outputStream, (char *)file, len); @@ -1236,9 +1266,21 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, glyfLen = pos; } + // if only the last loca entry is bogus (less than the one before + // it), just replace it with the glyf table size -- the last entry + // is just the end of the previous glyph, i.e., not the start of a + // valid glyph + if (bogusLastLoca) { + for (i = 0; i < nGlyphs; ++i) { + locaTable[i].newOffset = locaTable[i].origOffset; + } + i = seekTable("glyf"); + locaTable[nGlyphs].newOffset = tables[i].len; + } + // compute checksums for the loca and glyf tables locaChecksum = glyfChecksum = 0; - if (unsortedLoca) { + if (unsortedLoca || bogusLastLoca) { if (locaFmt) { for (j = 0; j <= nGlyphs; ++j) { locaChecksum += locaTable[j].newOffset; @@ -1251,6 +1293,8 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, } } } + } + if (unsortedLoca) { pos = tables[seekTable("glyf")].offset; for (j = 0; j < nGlyphs; ++j) { n = locaTable[j].len; @@ -1455,7 +1499,8 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, newTables[j].len = sizeof(cmapTab); } else if (newTables[j].tag == cmapTag && badCmapLen) { newTables[j].len = cmapLen; - } else if (newTables[j].tag == locaTag && unsortedLoca) { + } else if (newTables[j].tag == locaTag && + (unsortedLoca || bogusLastLoca)) { newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2); newTables[j].checksum = locaChecksum; } else if (newTables[j].tag == glyfTag && unsortedLoca) { @@ -1620,7 +1665,8 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, (*outputFunc)(outputStream, newHHEATab, newTables[i].len); } else if (newTables[i].tag == hmtxTag && abbrevHMTX) { (*outputFunc)(outputStream, newHMTXTab, newTables[i].len); - } else if (newTables[i].tag == locaTag && unsortedLoca) { + } else if (newTables[i].tag == locaTag && + (unsortedLoca || bogusLastLoca)) { for (j = 0; j <= nGlyphs; ++j) { if (locaFmt) { locaBuf[0] = (char)(locaTable[j].newOffset >> 24); diff --git a/src/xpdf-4.04/fofi/FoFiTrueType.h b/src/xpdf-4.04/fofi/FoFiTrueType.h index 619e1bd..568ee84 100644 --- a/src/xpdf-4.04/fofi/FoFiTrueType.h +++ b/src/xpdf-4.04/fofi/FoFiTrueType.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "FoFiBase.h" diff --git a/src/xpdf-4.04/fofi/FoFiType1.cc b/src/xpdf-4.04/fofi/FoFiType1.cc index 83ec53e..66b1932 100644 --- a/src/xpdf-4.04/fofi/FoFiType1.cc +++ b/src/xpdf-4.04/fofi/FoFiType1.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -197,7 +193,8 @@ void FoFiType1::parse() { char *line, *line1, *p, *p2; char buf[256]; char c; - int n, code, base, i, j; + unsigned int code; + int n, base, i, j; GBool gotMatrix, startsWithDup, endsWithDup; gotMatrix = gFalse; @@ -266,7 +263,7 @@ void FoFiType1::parse() { } ++p; for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ; - if (code >= 0 && code < 256) { + if (code < 256) { c = *p2; *p2 = '\0'; gfree(encoding[code]); diff --git a/src/xpdf-4.04/fofi/FoFiType1.h b/src/xpdf-4.04/fofi/FoFiType1.h index 4a64f24..3576391 100644 --- a/src/xpdf-4.04/fofi/FoFiType1.h +++ b/src/xpdf-4.04/fofi/FoFiType1.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "FoFiBase.h" diff --git a/src/xpdf-4.04/fofi/FoFiType1C.cc b/src/xpdf-4.04/fofi/FoFiType1C.cc index b6a1339..64d676b 100644 --- a/src/xpdf-4.04/fofi/FoFiType1C.cc +++ b/src/xpdf-4.04/fofi/FoFiType1C.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -181,16 +177,16 @@ GString *FoFiType1C::getGlyphName(int gid) { GHash *FoFiType1C::getNameToGIDMap() { GHash *map; - char name[256]; + char glyphName[256]; GBool ok; int gid; map = new GHash(gTrue); for (gid = 0; gid < nGlyphs; ++gid) { ok = gTrue; - getString(charset[gid], name, &ok); + getString(charset[gid], glyphName, &ok); if (ok) { - map->add(new GString(name), gid); + map->add(new GString(glyphName), gid); } } return map; @@ -1527,7 +1523,7 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf, if (nOps < 6 || nOps % 6 != 0) { //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps); } - for (k = 0; k < nOps; k += 6) { + for (k = 0; k+5 < nOps; k += 6) { cvtNum(ops[k], charBuf); cvtNum(ops[k+1], charBuf); cvtNum(ops[k+2], charBuf); @@ -1696,9 +1692,11 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf, cvtNum(ops[k+5], charBuf); charBuf->append((char)8); } - cvtNum(ops[k], charBuf); - cvtNum(ops[k+1], charBuf); - charBuf->append((char)5); + if (k+1 < nOps) { + cvtNum(ops[k], charBuf); + cvtNum(ops[k+1], charBuf); + charBuf->append((char)5); + } nOps = 0; openPath = gTrue; break; @@ -1711,13 +1709,15 @@ void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf, cvtNum(ops[k+1], charBuf); charBuf->append((char)5); } - cvtNum(ops[k], charBuf); - cvtNum(ops[k+1], charBuf); - cvtNum(ops[k+2], charBuf); - cvtNum(ops[k+3], charBuf); - cvtNum(ops[k+4], charBuf); - cvtNum(ops[k+5], charBuf); - charBuf->append((char)8); + if (k+5 < nOps) { + cvtNum(ops[k], charBuf); + cvtNum(ops[k+1], charBuf); + cvtNum(ops[k+2], charBuf); + cvtNum(ops[k+3], charBuf); + cvtNum(ops[k+4], charBuf); + cvtNum(ops[k+5], charBuf); + charBuf->append((char)8); + } nOps = 0; openPath = gTrue; break; @@ -2251,43 +2251,7 @@ void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc, void *outputStream, int nWidths, Gushort *widths, Guchar *cmapTable, int cmapTableLen) { - // dummy OS/2 table (taken from FoFiTrueType::writeTTF) - static Guchar os2Tab[86] = { - 0, 1, // version - 0, 1, // xAvgCharWidth - 0x01, 0x90, // usWeightClass - 0, 5, // usWidthClass - 0, 0, // fsType - 0, 0, // ySubscriptXSize - 0, 0, // ySubscriptYSize - 0, 0, // ySubscriptXOffset - 0, 0, // ySubscriptYOffset - 0, 0, // ySuperscriptXSize - 0, 0, // ySuperscriptYSize - 0, 0, // ySuperscriptXOffset - 0, 0, // ySuperscriptYOffset - 0, 0, // yStrikeoutSize - 0, 0, // yStrikeoutPosition - 0, 0, // sFamilyClass - 0, 0, 0, 0, 0, // panose - 0, 0, 0, 0, 0, - 0, 0, 0, 0, // ulUnicodeRange1 - 0, 0, 0, 0, // ulUnicodeRange2 - 0, 0, 0, 0, // ulUnicodeRange3 - 0, 0, 0, 0, // ulUnicodeRange4 - 0, 0, 0, 0, // achVendID - 0, 0, // fsSelection - 0, 0, // usFirstCharIndex - 0, 0, // usLastCharIndex - 0, 0, // sTypoAscender - 0, 0, // sTypoDescender - 0, 0, // sTypoLineGap - 0x20, 0x00, // usWinAscent - 0x20, 0x00, // usWinDescent - 0, 0, 0, 1, // ulCodePageRange1 - 0, 0, 0, 0 // ulCodePageRange2 - }; - Guchar headTable[54], hheaTable[36], maxpTable[6]; + Guchar os2Table[96], headTable[54], hheaTable[36], maxpTable[6]; Guchar nameTable[26], postTable[32]; Guchar *hmtxTable; static const char *tableTag[9] = { @@ -2307,15 +2271,118 @@ void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc, double mat[6]; Gushort maxWidth; Guint checksum, fileChecksum; - int unitsPerEm, xMin, yMin, xMax, yMax, offset, i; + int unitsPerEm, xMin, yMin, xMax, yMax, ascent, descent, offset, i; + + xMin = (int)(topDict.fontBBox[0] + 0.5); + yMin = (int)(topDict.fontBBox[1] + 0.5); + xMax = (int)(topDict.fontBBox[2] + 0.5); + yMax = (int)(topDict.fontBBox[3] + 0.5); + ascent = yMax; + descent = -yMin; //--- CFF_ table tableData[0] = file; tableLength[0] = len; //--- OS/2 table - tableData[1] = os2Tab; - tableLength[1] = 86; + os2Table[ 0] = 0; // version + os2Table[ 1] = 4; + os2Table[ 2] = 0; // xAvgCharWidth + os2Table[ 3] = 1; + os2Table[ 4] = 0x01; // usWeightClass + os2Table[ 5] = 0x90; + os2Table[ 6] = 0; // usWidthClass + os2Table[ 7] = 5; + os2Table[ 8] = 0; // fsType + os2Table[ 9] = 0; + os2Table[10] = 0; // ySubscriptXSize + os2Table[11] = 0; + os2Table[12] = 0; // ySubscriptYSize + os2Table[13] = 0; + os2Table[14] = 0; // ySubscriptXOffset + os2Table[15] = 0; + os2Table[16] = 0; // ySubscriptYOffset + os2Table[17] = 0; + os2Table[18] = 0; // ySuperscriptXSize + os2Table[19] = 0; + os2Table[20] = 0; // ySuperscriptYSize + os2Table[21] = 0; + os2Table[22] = 0; // ySuperscriptXOffset + os2Table[23] = 0; + os2Table[24] = 0; // ySuperscriptYOffset + os2Table[25] = 0; + os2Table[26] = 0; // yStrikeoutSize + os2Table[27] = 0; + os2Table[28] = 0; // yStrikeoutPosition + os2Table[29] = 0; + os2Table[30] = 0; // sFamilyClass + os2Table[31] = 0; + os2Table[32] = 0; // panose + os2Table[33] = 0; + os2Table[34] = 0; + os2Table[35] = 0; + os2Table[36] = 0; + os2Table[37] = 0; + os2Table[38] = 0; + os2Table[39] = 0; + os2Table[40] = 0; + os2Table[41] = 0; + os2Table[42] = 0; // ulUnicodeRange1 + os2Table[43] = 0; + os2Table[44] = 0; + os2Table[45] = 0; + os2Table[46] = 0; // ulUnicodeRange2 + os2Table[47] = 0; + os2Table[48] = 0; + os2Table[49] = 0; + os2Table[50] = 0; // ulUnicodeRange3 + os2Table[51] = 0; + os2Table[52] = 0; + os2Table[53] = 0; + os2Table[54] = 0; // ulUnicodeRange4 + os2Table[55] = 0; + os2Table[56] = 0; + os2Table[57] = 0; + os2Table[58] = 0; // achVendID + os2Table[59] = 0; + os2Table[60] = 0; + os2Table[61] = 0; + os2Table[62] = 0; // fsSelection + os2Table[63] = 0; + os2Table[64] = 0; // usFirstCharIndex + os2Table[65] = 0; + os2Table[66] = 0; // usLastCharIndex + os2Table[67] = 0; + os2Table[68] = 0; // sTypoAscender + os2Table[69] = 0; + os2Table[70] = 0; // sTypoDescender + os2Table[71] = 0; + os2Table[72] = 0; // sTypoLineGap + os2Table[73] = 0; + os2Table[74] = (Guchar)(ascent >> 8); // usWinAscent + os2Table[75] = (Guchar)ascent; + os2Table[76] = (Guchar)(descent >> 8); // usWinDescent + os2Table[77] = (Guchar)descent; + os2Table[78] = 0; // ulCodePageRange1 + os2Table[79] = 0; + os2Table[80] = 0; + os2Table[81] = 1; + os2Table[82] = 0; // ulCodePageRange2 + os2Table[83] = 0; + os2Table[84] = 0; + os2Table[85] = 0; + os2Table[86] = 0; // sxHeight + os2Table[87] = 0; + os2Table[88] = 0; // sCapHeight + os2Table[89] = 0; + os2Table[90] = 0; // usDefaultChar + os2Table[91] = 0; + os2Table[92] = 0; // usBreakChar + os2Table[93] = 0; + os2Table[94] = 0; // usMaxContext + os2Table[95] = 0; + tableData[1] = os2Table; + tableLength[1] = 96; //--- cmap table tableData[2] = cmapTable; @@ -2328,18 +2395,14 @@ void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc, } else { unitsPerEm = (int)(1 / mat[0] + 0.5); } - xMin = (int)(topDict.fontBBox[0] + 0.5); - yMin = (int)(topDict.fontBBox[1] + 0.5); - xMax = (int)(topDict.fontBBox[2] + 0.5); - yMax = (int)(topDict.fontBBox[3] + 0.5); headTable[ 0] = 0x00; // version headTable[ 1] = 0x01; headTable[ 2] = 0x00; headTable[ 3] = 0x00; headTable[ 4] = 0x00; // revision - headTable[ 5] = 0x00; + headTable[ 5] = 0x01; // (needs to be non-zero) headTable[ 6] = 0x00; - headTable[ 7] = 0x00; + headTable[ 7] = 0x01; headTable[ 8] = 0x00; // checksumAdjustment headTable[ 9] = 0x00; // (set later) headTable[10] = 0x00; @@ -2390,8 +2453,8 @@ void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc, tableLength[3] = 54; //--- hhea table - maxWidth = widths[0]; - for (i = 1; i < nWidths; ++i) { + maxWidth = 0; + for (i = 0; i < nWidths; ++i) { if (widths[i] > maxWidth) { maxWidth = widths[i]; } @@ -2659,6 +2722,10 @@ GBool FoFiType1C::parse() { return gFalse; } nFDs = fdIdx.len; + if (nFDs < 1) { + parsedOk = gFalse; + return gFalse; + } privateDicts = (Type1CPrivateDict *) gmallocn(nFDs, sizeof(Type1CPrivateDict)); for (i = 0; i < nFDs; ++i) { diff --git a/src/xpdf-4.04/fofi/FoFiType1C.h b/src/xpdf-4.04/fofi/FoFiType1C.h index 15a823c..301f42d 100644 --- a/src/xpdf-4.04/fofi/FoFiType1C.h +++ b/src/xpdf-4.04/fofi/FoFiType1C.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "FoFiBase.h" From fdd13d0f5c314bf0ebbd40c8c1b502152800ede8 Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:44:49 +0200 Subject: [PATCH 03/10] Update goo --- src/xpdf-4.04/goo/FixedPoint.cc | 4 ---- src/xpdf-4.04/goo/FixedPoint.h | 4 ---- src/xpdf-4.04/goo/GHash.cc | 4 ---- src/xpdf-4.04/goo/GHash.h | 4 ---- src/xpdf-4.04/goo/GList.cc | 9 +++++---- src/xpdf-4.04/goo/GList.h | 7 +++---- src/xpdf-4.04/goo/GString.cc | 6 ++---- src/xpdf-4.04/goo/GString.h | 4 ---- src/xpdf-4.04/goo/gfile.cc | 25 ++++++++++++++++++++++++- src/xpdf-4.04/goo/gfile.h | 6 ++++++ src/xpdf-4.04/goo/gmem.cc | 6 +++--- 11 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/xpdf-4.04/goo/FixedPoint.cc b/src/xpdf-4.04/goo/FixedPoint.cc index 503a06a..8c4c474 100644 --- a/src/xpdf-4.04/goo/FixedPoint.cc +++ b/src/xpdf-4.04/goo/FixedPoint.cc @@ -12,10 +12,6 @@ #if USE_FIXEDPOINT -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmempp.h" #include "FixedPoint.h" diff --git a/src/xpdf-4.04/goo/FixedPoint.h b/src/xpdf-4.04/goo/FixedPoint.h index 9f0c324..31f2ca4 100644 --- a/src/xpdf-4.04/goo/FixedPoint.h +++ b/src/xpdf-4.04/goo/FixedPoint.h @@ -15,10 +15,6 @@ #if USE_FIXEDPOINT -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include #include "gtypes.h" diff --git a/src/xpdf-4.04/goo/GHash.cc b/src/xpdf-4.04/goo/GHash.cc index e6b3244..c77a1b9 100644 --- a/src/xpdf-4.04/goo/GHash.cc +++ b/src/xpdf-4.04/goo/GHash.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmem.h" #include "gmempp.h" #include "GString.h" diff --git a/src/xpdf-4.04/goo/GHash.h b/src/xpdf-4.04/goo/GHash.h index 179753a..92ce226 100644 --- a/src/xpdf-4.04/goo/GHash.h +++ b/src/xpdf-4.04/goo/GHash.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" class GString; diff --git a/src/xpdf-4.04/goo/GList.cc b/src/xpdf-4.04/goo/GList.cc index c194818..7aaa5d7 100644 --- a/src/xpdf-4.04/goo/GList.cc +++ b/src/xpdf-4.04/goo/GList.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -100,6 +96,11 @@ void GList::sort(int (*cmp)(const void *obj1, const void *obj2)) { qsort(data, length, sizeof(void *), cmp); } +void GList::sort(int first, int n, + int (*cmp)(const void *ptr1, const void *ptr2)) { + qsort(data + first, n, sizeof(void *), cmp); +} + void GList::reverse() { void *t; int n, i; diff --git a/src/xpdf-4.04/goo/GList.h b/src/xpdf-4.04/goo/GList.h index 0050437..ee12346 100644 --- a/src/xpdf-4.04/goo/GList.h +++ b/src/xpdf-4.04/goo/GList.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" //------------------------------------------------------------------------ @@ -70,6 +66,9 @@ class GList { // be double-dereferenced. void sort(int (*cmp)(const void *ptr1, const void *ptr2)); + // Sort items starting at . + void sort(int first, int n, int (*cmp)(const void *ptr1, const void *ptr2)); + // Reverse the list. void reverse(); diff --git a/src/xpdf-4.04/goo/GString.cc b/src/xpdf-4.04/goo/GString.cc index 54de35b..1e41bca 100644 --- a/src/xpdf-4.04/goo/GString.cc +++ b/src/xpdf-4.04/goo/GString.cc @@ -10,10 +10,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -416,6 +412,8 @@ GString *GString::appendfv(const char *fmt, va_list argList) { // format the argument arg = args[idx]; + str = NULL; + len = 0; switch (ft) { case fmtIntDecimal: formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len); diff --git a/src/xpdf-4.04/goo/GString.h b/src/xpdf-4.04/goo/GString.h index 6b342f8..2e67fd0 100644 --- a/src/xpdf-4.04/goo/GString.h +++ b/src/xpdf-4.04/goo/GString.h @@ -13,10 +13,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include // for LLONG_MAX and ULLONG_MAX #include #include "gtypes.h" diff --git a/src/xpdf-4.04/goo/gfile.cc b/src/xpdf-4.04/goo/gfile.cc index 9ec8bae..69dce6e 100644 --- a/src/xpdf-4.04/goo/gfile.cc +++ b/src/xpdf-4.04/goo/gfile.cc @@ -415,6 +415,18 @@ GBool pathIsFile(const char *path) { #endif } +GBool pathIsDir(const char *path) { +#ifdef _WIN32 + wchar_t wPath[winMaxLongPath + 1]; + fileNameToUCS2(path, wPath, winMaxLongPath + 1); + DWORD attr = GetFileAttributesW(wPath); + return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY); +#else + struct stat statBuf; + return stat(path, &statBuf) == 0 && S_ISDIR(statBuf.st_mode); +#endif +} + time_t getModTime(char *fileName) { #ifdef _WIN32 //~ should implement this, but it's (currently) only used in xpdf @@ -597,6 +609,17 @@ GString *fileNameToUTF8(wchar_t *path) { return s; } +GString *fileNameMultiByteToUTF8(char *path) { + wchar_t fileNameW[winMaxLongPath + 1]; + if (MultiByteToWideChar(CP_ACP, 0, path, -1, + fileNameW, sizeof(fileNameW) / sizeof(wchar_t))) { + return fileNameToUTF8(fileNameW); + } else { + // shouldn't happen, but just in case... + return new GString(path); + } +} + wchar_t *fileNameToUCS2(const char *path, wchar_t *out, size_t outSize) { const char *p; size_t i; @@ -671,7 +694,7 @@ void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) { } hres = persistFile->Load(wPath, STGM_READ); if (FAILED(hres)) { - fprintf(stderr, "IPersistFile.Load failed: 0x%08x\n", hres); + fprintf(stderr, "IPersistFile.Load failed: 0x%08lx\n", hres); exit(1); } wchar_t target[winMaxLongPath + 1]; diff --git a/src/xpdf-4.04/goo/gfile.h b/src/xpdf-4.04/goo/gfile.h index 202e6ee..a246b65 100644 --- a/src/xpdf-4.04/goo/gfile.h +++ b/src/xpdf-4.04/goo/gfile.h @@ -64,6 +64,9 @@ extern GString *makePathAbsolute(GString *path); // Returns true if [path] exists and is a regular file. extern GBool pathIsFile(const char *path); +// Returns true if [path] exists and is a directory. +extern GBool pathIsDir(const char *path); + // Get the modification time for . Returns 0 if there is an // error. extern time_t getModTime(char *fileName); @@ -90,6 +93,9 @@ extern GString *fileNameToUTF8(char *path); // Convert a file name from UCS-2 to UTF-8. extern GString *fileNameToUTF8(wchar_t *path); +// Convert a file name from the OEM code page to UTF-8. +extern GString *fileNameMultiByteToUTF8(char *path); + // Convert a file name from UTF-8 to UCS-2. [out] has space for // [outSize] wchar_t elements (including the trailing zero). Returns // [out]. diff --git a/src/xpdf-4.04/goo/gmem.cc b/src/xpdf-4.04/goo/gmem.cc index 7291f20..00fde9b 100644 --- a/src/xpdf-4.04/goo/gmem.cc +++ b/src/xpdf-4.04/goo/gmem.cc @@ -207,10 +207,10 @@ void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { if (nObjs == 0) { return NULL; } - n = nObjs * objSize; if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { gMemError("Bogus memory allocation size"); } + n = nObjs * objSize; return gmalloc(n); } @@ -281,10 +281,10 @@ void *gmallocn64(int nObjs, size_t objSize) GMEM_EXCEP { if (nObjs == 0) { return NULL; } - n = nObjs * objSize; if (nObjs < 0 || (size_t)nObjs >= SIZE_MAX / objSize) { gMemError("Bogus memory allocation size"); } + n = nObjs * objSize; return gmalloc64(n); } @@ -297,10 +297,10 @@ void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { } return NULL; } - n = nObjs * objSize; if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { gMemError("Bogus memory allocation size"); } + n = nObjs * objSize; return grealloc(p, n); } From 321689594e929e9b8d5997581109631dadd14d3c Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:46:48 +0200 Subject: [PATCH 04/10] Update splash --- src/xpdf-4.04/splash/Splash.cc | 2101 +++++++++++--------- src/xpdf-4.04/splash/Splash.h | 142 +- src/xpdf-4.04/splash/SplashBitmap.cc | 159 +- src/xpdf-4.04/splash/SplashBitmap.h | 77 +- src/xpdf-4.04/splash/SplashClip.cc | 6 +- src/xpdf-4.04/splash/SplashClip.h | 14 +- src/xpdf-4.04/splash/SplashFTFont.cc | 14 +- src/xpdf-4.04/splash/SplashFTFont.h | 10 +- src/xpdf-4.04/splash/SplashFTFontEngine.cc | 4 - src/xpdf-4.04/splash/SplashFTFontEngine.h | 4 - src/xpdf-4.04/splash/SplashFTFontFile.cc | 4 - src/xpdf-4.04/splash/SplashFTFontFile.h | 4 - src/xpdf-4.04/splash/SplashFont.cc | 8 +- src/xpdf-4.04/splash/SplashFont.h | 10 +- src/xpdf-4.04/splash/SplashFontEngine.cc | 4 - src/xpdf-4.04/splash/SplashFontEngine.h | 4 - src/xpdf-4.04/splash/SplashFontFile.cc | 4 - src/xpdf-4.04/splash/SplashFontFile.h | 4 - src/xpdf-4.04/splash/SplashFontFileID.cc | 4 - src/xpdf-4.04/splash/SplashFontFileID.h | 4 - src/xpdf-4.04/splash/SplashPath.cc | 4 - src/xpdf-4.04/splash/SplashPath.h | 4 - src/xpdf-4.04/splash/SplashPattern.cc | 4 - src/xpdf-4.04/splash/SplashPattern.h | 4 - src/xpdf-4.04/splash/SplashScreen.cc | 4 - src/xpdf-4.04/splash/SplashScreen.h | 4 - src/xpdf-4.04/splash/SplashState.cc | 7 +- src/xpdf-4.04/splash/SplashState.h | 5 +- src/xpdf-4.04/splash/SplashXPath.cc | 65 +- src/xpdf-4.04/splash/SplashXPath.h | 11 +- src/xpdf-4.04/splash/SplashXPathScanner.cc | 36 +- src/xpdf-4.04/splash/SplashXPathScanner.h | 4 - 32 files changed, 1540 insertions(+), 1193 deletions(-) diff --git a/src/xpdf-4.04/splash/Splash.cc b/src/xpdf-4.04/splash/Splash.cc index 4afe21b..1259b4f 100644 --- a/src/xpdf-4.04/splash/Splash.cc +++ b/src/xpdf-4.04/splash/Splash.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -86,9 +82,12 @@ struct SplashPipe { //~ null pointers, since it's rarely used Guint *srcOverprintMaskPtr; + // alpha is shape + GBool alphaIsShape; + // special cases and result color GBool noTransparency; - GBool shapeOnly; + GBool alphaOnly; SplashPipeResultColorCtrl resultColorCtrl; // non-isolated group correction @@ -98,7 +97,8 @@ struct SplashPipe { // the "run" function void (Splash::*run)(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapPetr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); }; SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = { @@ -168,8 +168,9 @@ inline void Splash::updateModY(int y) { //------------------------------------------------------------------------ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, - Guchar aInput, GBool usesShape, - GBool nonIsolatedGroup, GBool usesSrcOverprint) { + Guchar aInput, GBool usesShape, GBool usesAlpha, + GBool nonIsolatedGroup, GBool usesSrcOverprint, + GBool alphaIsShape) { SplashColorMode mode; mode = bitmap->mode; @@ -190,17 +191,22 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, // source overprint mask pipe->srcOverprintMaskPtr = NULL; + // alpha is shape + pipe->alphaIsShape = alphaIsShape; + // special cases pipe->noTransparency = aInput == 255 && !state->softMask && !usesShape && + !usesAlpha && !state->inNonIsolatedGroup && !state->inKnockoutGroup && !nonIsolatedGroup && state->overprintMask == 0xffffffff; - pipe->shapeOnly = aInput == 255 && + pipe->alphaOnly = aInput == 255 && !state->softMask && - usesShape && + !usesShape && + usesAlpha && !state->inNonIsolatedGroup && !state->inKnockoutGroup && !nonIsolatedGroup && @@ -221,7 +227,7 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, // select the 'run' function pipe->run = &Splash::pipeRun; - if (overprintMaskBitmap || usesSrcOverprint) { + if (shapeBitmap || overprintMaskBitmap || usesSrcOverprint) { // use Splash::pipeRun } else if (!pipe->pattern && pipe->noTransparency && !state->blendFunc) { if (mode == splashModeMono1 && !bitmap->alpha) { @@ -237,7 +243,7 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, pipe->run = &Splash::pipeRunSimpleCMYK8; #endif } - } else if (!pipe->pattern && pipe->shapeOnly && !state->blendFunc) { + } else if (!pipe->pattern && pipe->alphaOnly && !state->blendFunc) { if (mode == splashModeMono1 && !bitmap->alpha) { pipe->run = &Splash::pipeRunShapeMono1; } else if (mode == splashModeMono8 && bitmap->alpha) { @@ -255,8 +261,9 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, pipe->run = &Splash::pipeRunShapeNoAlphaMono8; } } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask && - usesShape && - !(state->inNonIsolatedGroup && groupBackBitmap->alpha) && + usesAlpha && + !(state->inNonIsolatedGroup && (alpha0Bitmap || + parent->bitmap->alpha)) && !state->inKnockoutGroup && !state->blendFunc && !pipe->nonIsolatedGroup) { if (mode == splashModeMono1 && !bitmap->alpha) { @@ -275,7 +282,7 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, } else if (!pipe->pattern && aInput == 255 && state->softMask && - usesShape && + usesAlpha && !state->inNonIsolatedGroup && !state->inKnockoutGroup && !nonIsolatedGroup && @@ -293,8 +300,9 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, #endif } } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask && - usesShape && - state->inNonIsolatedGroup && groupBackBitmap->alpha && + usesAlpha && + state->inNonIsolatedGroup && (alpha0Bitmap || + parent->bitmap->alpha) && !state->inKnockoutGroup && !state->blendFunc && !pipe->nonIsolatedGroup) { if (mode == splashModeMono8 && bitmap->alpha) { @@ -313,15 +321,18 @@ inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, // general case void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar *shapePtr2; - Guchar shape, aSrc, aDest, alphaI, alphaIm1, alpha0, aResult; - SplashColor cSrc, cDest, cBlend; - Guchar shapeVal, cResult0, cResult1, cResult2, cResult3; - int cSrcStride, shapeStride, x, lastX, t; - SplashColorPtr destColorPtr; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar *shapePtr2, *alphaPtr2; + Guchar shape, alpha, fSrc, aSrc, fDest, aDest; + Guchar alphaI, alphaIm1, alpha0, fResult, aResult; + Guchar m1, m2, m3, m4; + SplashColor cSrc, cDest, c0, cBlend; + Guchar shapeVal, alphaVal, cResult0, cResult1, cResult2, cResult3; + int cSrcStride, shapeStride, alphaStride, x, lastX, t; + SplashColorPtr cBlendIn, destColorPtr; Guchar destColorMask; - Guchar *destAlphaPtr; + Guchar *destShapePtr, *destAlphaPtr; SplashColorPtr color0Ptr; Guchar color0Mask; Guchar *alpha0Ptr; @@ -330,8 +341,9 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, Guint *overprintMaskPtr; #if SPLASH_CMYK Guchar aPrev; - SplashColor cSrc2, cDest2; + SplashColor cSrc2, cBlendIn2; #endif + int i; if (cSrcPtr && !pipe->pattern) { cSrcStride = bitmapComps; @@ -339,24 +351,46 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cSrcPtr = pipe->cSrcVal; cSrcStride = 0; } - if (shapePtr) { shapePtr2 = shapePtr; shapeStride = 1; + } else { + shapeVal = 0xff; + shapePtr2 = &shapeVal; + shapeStride = 0; + } + if (alphaPtr) { + alphaPtr2 = alphaPtr; + alphaStride = 1; + } else { + alphaVal = 0xff; + alphaPtr2 = &alphaVal; + alphaStride = 0; + } + + if (shapePtr) { for (; x0 <= x1; ++x0) { if (*shapePtr2) { break; } cSrcPtr += cSrcStride; ++shapePtr2; + ++alphaPtr2; + if (pipe->srcOverprintMaskPtr) { + ++pipe->srcOverprintMaskPtr; + } + } + } else if (alphaPtr) { + for (; x0 <= x1; ++x0) { + if (*alphaPtr2) { + break; + } + cSrcPtr += cSrcStride; + ++alphaPtr2; if (pipe->srcOverprintMaskPtr) { ++pipe->srcOverprintMaskPtr; } } - } else { - shapeVal = 0xff; - shapePtr2 = &shapeVal; - shapeStride = 0; } if (x0 > x1) { return; @@ -365,7 +399,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); if (bitmap->mode == splashModeMono1) { destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; @@ -374,6 +408,11 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * bitmapComps]; destColorMask = 0; // make gcc happy } + if (shapeBitmap) { + destShapePtr = &shapeBitmap->alpha[y * shapeBitmap->alphaRowSize + x0]; + } else { + destShapePtr = NULL; + } if (bitmap->alpha) { destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; } else { @@ -387,24 +426,25 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, if (state->inKnockoutGroup) { if (bitmap->mode == splashModeMono1) { color0Ptr = - &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize + - ((groupBackX + x0) >> 3)]; - color0Mask = (Guchar)(0x80 >> ((groupBackX + x0) & 7)); + &parent->bitmap->data[(parentOffsetY + y) * parent->bitmap->rowSize + + ((parentOffsetX + x0) >> 3)]; + color0Mask = (Guchar)(0x80 >> ((parentOffsetX + x0) & 7)); } else { color0Ptr = - &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize + - (groupBackX + x0) * bitmapComps]; + &parent->bitmap->data[(parentOffsetY + y) * parent->bitmap->rowSize + + (parentOffsetX + x0) * bitmapComps]; color0Mask = 0; // make gcc happy } } else { color0Ptr = NULL; color0Mask = 0; // make gcc happy } - if (state->inNonIsolatedGroup && groupBackBitmap->alpha) { - alpha0Ptr = - &groupBackBitmap->alpha[(groupBackY + y) - * groupBackBitmap->alphaRowSize + - (groupBackX + x0)]; + if (alpha0Bitmap) { + alpha0Ptr = &alpha0Bitmap->alpha[y * alpha0Bitmap->alphaRowSize + x0]; + } else if (state->inNonIsolatedGroup && parent->bitmap->alpha) { + alpha0Ptr = &parent->bitmap->alpha[ + (parentOffsetY + y) * parent->bitmap->alphaRowSize + + (parentOffsetX + x0)]; } else { alpha0Ptr = NULL; } @@ -414,18 +454,29 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, overprintMaskPtr = NULL; } + // c0 is only used for non-iso knockout groups, but in some other + // cases we use m2 * c0[i], with m2=0 -- so initialize c0[i]=0 here + // to avoid valgrind warnings + for (i = 0; i < bitmapComps; ++i) { + c0[i] = 0; + } + for (x = x0; x <= x1; ++x) { - //----- shape + //----- shape and alpha shape = *shapePtr2; - if (!shape) { + alpha = *alphaPtr2; + if (!(shapePtr ? shape : alpha)) { if (bitmap->mode == splashModeMono1) { destColorPtr += destColorMask & 1; destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1)); } else { destColorPtr += bitmapComps; } + if (destShapePtr) { + ++destShapePtr; + } if (destAlphaPtr) { ++destAlphaPtr; } @@ -445,6 +496,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, } cSrcPtr += cSrcStride; shapePtr2 += shapeStride; + alphaPtr2 += alphaStride; if (pipe->srcOverprintMaskPtr) { ++pipe->srcOverprintMaskPtr; } @@ -497,76 +549,86 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, break; #endif } + fResult = 255; aResult = 255; } else { // if (noTransparency && !blendFunc) - //----- read destination pixel - // (or backdrop color, for knockout groups) + //----- read destination color - if (color0Ptr) { + switch (bitmap->mode) { + case splashModeMono1: + cDest[0] = (*destColorPtr & destColorMask) ? 0xff : 0x00; + break; + case splashModeMono8: + cDest[0] = *destColorPtr; + break; + case splashModeRGB8: + cDest[0] = destColorPtr[0]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[2]; + break; + case splashModeBGR8: + cDest[0] = destColorPtr[2]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[0]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + cDest[0] = destColorPtr[0]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[2]; + cDest[3] = destColorPtr[3]; + break; +#endif + } + + //----- read backdrop color + // (only used for non-iso knockout groups) + if (color0Ptr && alpha0Ptr) { switch (bitmap->mode) { case splashModeMono1: - cDest[0] = (*color0Ptr & color0Mask) ? 0xff : 0x00; + c0[0] = (*color0Ptr & color0Mask) ? 0xff : 0x00; color0Ptr += color0Mask & 1; color0Mask = (Guchar)((color0Mask << 7) | (color0Mask >> 1)); break; case splashModeMono8: - cDest[0] = *color0Ptr++; + c0[0] = *color0Ptr++; break; case splashModeRGB8: - cDest[0] = color0Ptr[0]; - cDest[1] = color0Ptr[1]; - cDest[2] = color0Ptr[2]; + c0[0] = color0Ptr[0]; + c0[1] = color0Ptr[1]; + c0[2] = color0Ptr[2]; color0Ptr += 3; break; case splashModeBGR8: - cDest[2] = color0Ptr[0]; - cDest[1] = color0Ptr[1]; - cDest[0] = color0Ptr[2]; + c0[2] = color0Ptr[0]; + c0[1] = color0Ptr[1]; + c0[0] = color0Ptr[2]; color0Ptr += 3; break; #if SPLASH_CMYK case splashModeCMYK8: - cDest[0] = color0Ptr[0]; - cDest[1] = color0Ptr[1]; - cDest[2] = color0Ptr[2]; - cDest[3] = color0Ptr[3]; + c0[0] = color0Ptr[0]; + c0[1] = color0Ptr[1]; + c0[2] = color0Ptr[2]; + c0[3] = color0Ptr[3]; color0Ptr += 4; break; #endif } - + cBlendIn = c0; } else { + cBlendIn = cDest; + } - switch (bitmap->mode) { - case splashModeMono1: - cDest[0] = (*destColorPtr & destColorMask) ? 0xff : 0x00; - break; - case splashModeMono8: - cDest[0] = *destColorPtr; - break; - case splashModeRGB8: - cDest[0] = destColorPtr[0]; - cDest[1] = destColorPtr[1]; - cDest[2] = destColorPtr[2]; - break; - case splashModeBGR8: - cDest[0] = destColorPtr[2]; - cDest[1] = destColorPtr[1]; - cDest[2] = destColorPtr[0]; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - cDest[0] = destColorPtr[0]; - cDest[1] = destColorPtr[1]; - cDest[2] = destColorPtr[2]; - cDest[3] = destColorPtr[3]; - break; -#endif - } + //----- read destination shape and alpha + if (destShapePtr) { + fDest = *destShapePtr; + } else { + fDest = 0xff; } if (destAlphaPtr) { @@ -636,26 +698,24 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, #endif } - //----- source alpha + //----- source shape and alpha + fSrc = shape; + aSrc = div255(pipe->aInput * alpha); if (softMaskPtr) { - if (shapePtr) { - aSrc = div255(div255(pipe->aInput * *softMaskPtr++) * shape); - } else { - aSrc = div255(pipe->aInput * *softMaskPtr++); + if (pipe->alphaIsShape) { + fSrc = div255(fSrc * *softMaskPtr); } - } else if (shapePtr) { - aSrc = div255(pipe->aInput * shape); - } else { - aSrc = pipe->aInput; + aSrc = div255(aSrc * *softMaskPtr); + ++softMaskPtr; } //----- non-isolated group correction - if (pipe->nonIsolatedGroup) { + if (pipe->nonIsolatedGroup && alpha != 0) { // This path is only used when Splash::composite() is called to // composite a non-isolated group onto the backdrop. In this - // case, shape is the source (group) alpha. + // case, alpha is the source (group) alpha. // // In a nested non-isolated group, i.e., if the destination is // also a non-isolated group (state->inNonIsolatedGroup), we @@ -668,7 +728,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, } else { t = aDest; } - t = (t * 255) / shape - t; + t = (t * 255) / alpha - t; switch (bitmap->mode) { #if SPLASH_CMYK case splashModeCMYK8: @@ -695,11 +755,11 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cSrc2[1] = (Guchar)(0xff - cSrc[1]); cSrc2[2] = (Guchar)(0xff - cSrc[2]); cSrc2[3] = (Guchar)(0xff - cSrc[3]); - cDest2[0] = (Guchar)(0xff - cDest[0]); - cDest2[1] = (Guchar)(0xff - cDest[1]); - cDest2[2] = (Guchar)(0xff - cDest[2]); - cDest2[3] = (Guchar)(0xff - cDest[3]); - (*state->blendFunc)(cSrc2, cDest2, cBlend, bitmap->mode); + cBlendIn2[0] = (Guchar)(0xff - cBlendIn[0]); + cBlendIn2[1] = (Guchar)(0xff - cBlendIn[1]); + cBlendIn2[2] = (Guchar)(0xff - cBlendIn[2]); + cBlendIn2[3] = (Guchar)(0xff - cBlendIn[3]); + (*state->blendFunc)(cSrc2, cBlendIn2, cBlend, bitmap->mode); // convert result back to subtractive cBlend[0] = (Guchar)(0xff - cBlend[0]); cBlend[1] = (Guchar)(0xff - cBlend[1]); @@ -707,41 +767,58 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cBlend[3] = (Guchar)(0xff - cBlend[3]); } else #endif - (*state->blendFunc)(cSrc, cDest, cBlend, bitmap->mode); + (*state->blendFunc)(cSrc, cBlendIn, cBlend, bitmap->mode); } - //----- result alpha and non-isolated group element correction + //----- result shape + + fResult = (Guchar)(fSrc + fDest - div255(fSrc * fDest)); + + //----- result alpha + // and setup for result color // alphaI = alpha_i // alphaIm1 = alpha_(i-1) if (pipe->noTransparency) { - alphaI = alphaIm1 = aResult = 255; - } else if (alpha0Ptr) { - if (color0Ptr) { - // non-isolated, knockout - aResult = aSrc; - alpha0 = *alpha0Ptr++; - alphaI = (Guchar)(aSrc + alpha0 - div255(aSrc * alpha0)); - alphaIm1 = alpha0; - } else { - // non-isolated, non-knockout + alphaI = aResult = 255; + m1 = m2 = m3 = m4 = 0; // make gcc happy + } else if (alpha0Ptr) { // non-isolated + alpha0 = *alpha0Ptr++; + if (color0Ptr) { // non-isolated, knockout + aResult = (Guchar)(div255((255 - fSrc) * aDest) + aSrc); + alphaI = (Guchar)(alpha0 + aResult - div255(alpha0 * aResult)); + alphaIm1 = (Guchar)(alpha0 + aDest - div255(alpha0 * aDest)); + m1 = div255((255 - fSrc) * alphaIm1); + m2 = div255((fSrc - aSrc) * alpha0); + m3 = div255(aSrc * (255 - alpha0)); + m4 = div255(aSrc * alpha0); + } else { // non-isolated, non-knockout aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); - alpha0 = *alpha0Ptr++; - alphaI = (Guchar)(aResult + alpha0 - div255(aResult * alpha0)); + alphaI = (Guchar)(alpha0 + aResult - div255(alpha0 * aResult)); alphaIm1 = (Guchar)(alpha0 + aDest - div255(alpha0 * aDest)); + m1 = alphaI - aSrc; + m2 = 0; + m3 = div255(aSrc * (255 - alphaIm1)); + m4 = div255(aSrc * alphaIm1); } } else { - if (color0Ptr) { - // isolated, knockout - aResult = aSrc; - alphaI = aSrc; - alphaIm1 = 0; - } else { - // isolated, non-knockout + if (color0Ptr) { // isolated, knockout + aResult = (Guchar)(div255((255 - fSrc) * aDest) + aSrc); + alphaI = aResult; + alphaIm1 = aDest; + m1 = div255((255 - fSrc) * alphaIm1); + m2 = 0; + m3 = aSrc; + m4 = 0; + } else { // isolated, non-knockout aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); alphaI = aResult; alphaIm1 = aDest; + m1 = alphaI - aSrc; + m2 = 0; + m3 = div255(aSrc * (255 - alphaIm1)); + m4 = div255(aSrc * alphaIm1); } } @@ -770,7 +847,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, if (alphaI == 0) { cResult0 = 0; } else { - cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) + cResult0 = (Guchar)((m1 * cDest[0] + m2 * c0[0] + aSrc * cSrc[0]) / alphaI); } break; @@ -780,11 +857,11 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cResult1 = 0; cResult2 = 0; } else { - cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) + cResult0 = (Guchar)((m1 * cDest[0] + m2 * c0[0] + aSrc * cSrc[0]) / alphaI); - cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1]) + cResult1 = (Guchar)((m1 * cDest[1] + m2 * c0[1] + aSrc * cSrc[1]) / alphaI); - cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2]) + cResult2 = (Guchar)((m1 * cDest[2] + m2 * c0[2] + aSrc * cSrc[2]) / alphaI); } break; @@ -796,13 +873,13 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cResult2 = 0; cResult3 = 0; } else { - cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) + cResult0 = (Guchar)((m1 * cDest[0] + m2 * c0[0] + aSrc * cSrc[0]) / alphaI); - cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1]) + cResult1 = (Guchar)((m1 * cDest[1] + m2 * c0[1] + aSrc * cSrc[1]) / alphaI); - cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2]) + cResult2 = (Guchar)((m1 * cDest[2] + m2 * c0[2] + aSrc * cSrc[2]) / alphaI); - cResult3 = (Guchar)(((alphaI - aSrc) * cDest[3] + aSrc * cSrc[3]) + cResult3 = (Guchar)((m1 * cDest[3] + m2 * c0[2] + aSrc * cSrc[3]) / alphaI); } break; @@ -812,9 +889,8 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, if (alphaI == 0) { cResult0 = 0; } else { - cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + - aSrc * ((255 - alphaIm1) * cSrc[0] + - alphaIm1 * cBlend[0]) / 255) + cResult0 = (Guchar)((m1 * cDest[0] + m2 * c0[0] + + m3 * cSrc[0] + m4 * cBlend[0]) / alphaI); } break; @@ -824,17 +900,14 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cResult1 = 0; cResult2 = 0; } else { - cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + - aSrc * ((255 - alphaIm1) * cSrc[0] + - alphaIm1 * cBlend[0]) / 255) + cResult0 = (Guchar)((m1 * cDest[0] + m2 * c0[0] + + m3 * cSrc[0] + m4 * cBlend[0]) / alphaI); - cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] + - aSrc * ((255 - alphaIm1) * cSrc[1] + - alphaIm1 * cBlend[1]) / 255) + cResult1 = (Guchar)((m1 * cDest[1] + m2 * c0[1] + + m3 * cSrc[1] + m4 * cBlend[1]) / alphaI); - cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] + - aSrc * ((255 - alphaIm1) * cSrc[2] + - alphaIm1 * cBlend[2]) / 255) + cResult2 = (Guchar)((m1 * cDest[2] + m2 * c0[2] + + m3 * cSrc[2] + m4 * cBlend[2]) / alphaI); } break; @@ -846,21 +919,17 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, cResult2 = 0; cResult3 = 0; } else { - cResult0 = (Guchar)(((alphaI - aSrc) * cDest[0] + - aSrc * ((255 - alphaIm1) * cSrc[0] + - alphaIm1 * cBlend[0]) / 255) + cResult0 = (Guchar)((m1 * cDest[0] + m2 * c0[0] + + m3 * cSrc[0] + m4 * cBlend[0]) / alphaI); - cResult1 = (Guchar)(((alphaI - aSrc) * cDest[1] + - aSrc * ((255 - alphaIm1) * cSrc[1] + - alphaIm1 * cBlend[1]) / 255) + cResult1 = (Guchar)((m1 * cDest[1] + m2 * c0[1] + + m3 * cSrc[1] + m4 * cBlend[1]) / alphaI); - cResult2 = (Guchar)(((alphaI - aSrc) * cDest[2] + - aSrc * ((255 - alphaIm1) * cSrc[2] + - alphaIm1 * cBlend[2]) / 255) + cResult2 = (Guchar)((m1 * cDest[2] + m2 * c0[2] + + m3 * cSrc[2] + m4 * cBlend[2]) / alphaI); - cResult3 = (Guchar)(((alphaI - aSrc) * cDest[3] + - aSrc * ((255 - alphaIm1) * cSrc[3] + - alphaIm1 * cBlend[3]) / 255) + cResult3 = (Guchar)((m1 * cDest[3] + m2 * c0[3] + + m3 * cSrc[3] + m4 * cBlend[3]) / alphaI); } break; @@ -906,12 +975,16 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, break; #endif } + if (destShapePtr) { + *destShapePtr++ = fResult; + } if (destAlphaPtr) { *destAlphaPtr++ = aResult; } cSrcPtr += cSrcStride; shapePtr2 += shapeStride; + alphaPtr2 += alphaStride; } // for (x ...) updateModX(lastX); @@ -921,7 +994,8 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, // !pipe->pattern && pipe->noTransparency && !state->blendFunc && // bitmap->mode == splashModeMono1 && !bitmap->alpha) { void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { Guchar cResult0; SplashColorPtr destColorPtr; Guchar destColorMask; @@ -941,7 +1015,7 @@ void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, updateModX(x1); updateModY(y); - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; destColorMask = (Guchar)(0x80 >> (x0 & 7)); @@ -968,7 +1042,8 @@ void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, // !pipe->pattern && pipe->noTransparency && !state->blendFunc && // bitmap->mode == splashModeMono8 && bitmap->alpha) { void Splash::pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { SplashColorPtr destColorPtr; Guchar *destAlphaPtr; int cSrcStride, x; @@ -986,7 +1061,7 @@ void Splash::pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, updateModX(x1); updateModY(y); - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -1005,7 +1080,8 @@ void Splash::pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, // !pipe->pattern && pipe->noTransparency && !state->blendFunc && // bitmap->mode == splashModeRGB8 && bitmap->alpha) { void Splash::pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { SplashColorPtr destColorPtr; Guchar *destAlphaPtr; int cSrcStride, x; @@ -1023,7 +1099,7 @@ void Splash::pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, updateModX(x1); updateModY(y); - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -1045,7 +1121,8 @@ void Splash::pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, // !pipe->pattern && pipe->noTransparency && !state->blendFunc && // bitmap->mode == splashModeBGR8 && bitmap->alpha) { void Splash::pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { SplashColorPtr destColorPtr; Guchar *destAlphaPtr; int cSrcStride, x; @@ -1063,7 +1140,7 @@ void Splash::pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, updateModX(x1); updateModY(y); - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -1086,7 +1163,8 @@ void Splash::pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, // !pipe->pattern && pipe->noTransparency && !state->blendFunc && // bitmap->mode == splashModeCMYK8 && bitmap->alpha) { void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { SplashColorPtr destColorPtr; Guchar *destAlphaPtr; int cSrcStride, x; @@ -1104,7 +1182,7 @@ void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, updateModX(x1); updateModY(y); - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -1126,11 +1204,12 @@ void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, // special case: -// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// !pipe->pattern && pipe->alphaOnly && !state->blendFunc && // bitmap->mode == splashModeMono1 && !bitmap->alpha void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, cSrc0, cDest0, cResult0; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; Guchar destColorMask; SplashScreenCursor screenCursor; @@ -1143,11 +1222,11 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1156,7 +1235,7 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; destColorMask = (Guchar)(0x80 >> (x0 & 7)); @@ -1165,13 +1244,13 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += destColorMask & 1; destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1)); cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1180,7 +1259,7 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = shape; + aSrc = alpha; //----- special case for aSrc = 255 if (aSrc == 255) { @@ -1205,18 +1284,19 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1)); cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); } // special case: -// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// !pipe->pattern && pipe->alphaOnly && !state->blendFunc && // bitmap->mode == splashModeMono8 && bitmap->alpha void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; Guchar *destAlphaPtr; int cSrcStride, x, lastX; @@ -1228,11 +1308,11 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1241,20 +1321,20 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { ++destColorPtr; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1263,7 +1343,7 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = shape; + aSrc = alpha; //----- special case for aSrc = 255 if (aSrc == 255) { @@ -1297,18 +1377,19 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); } // special case: -// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// !pipe->pattern && pipe->alphaOnly && !state->blendFunc && // bitmap->mode == splashModeRGB8 && bitmap->alpha void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -1323,11 +1404,11 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1336,20 +1417,20 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1360,7 +1441,7 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = shape; + aSrc = alpha; //----- special case for aSrc = 255 if (aSrc == 255) { @@ -1405,18 +1486,19 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); } // special case: -// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// !pipe->pattern && pipe->alphaOnly && !state->blendFunc && // bitmap->mode == splashModeBGR8 && bitmap->alpha void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -1431,11 +1513,11 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1444,20 +1526,20 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1468,7 +1550,7 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = shape; + aSrc = alpha; //----- special case for aSrc = 255 if (aSrc == 255) { @@ -1513,7 +1595,7 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -1521,11 +1603,12 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, #if SPLASH_CMYK // special case: -// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// !pipe->pattern && pipe->alphaOnly && !state->blendFunc && // bitmap->mode == splashModeCMYK8 && bitmap->alpha void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2, cSrc3; Guchar cDest0, cDest1, cDest2, cDest3; Guchar cResult0, cResult1, cResult2, cResult3; @@ -1540,11 +1623,11 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1553,20 +1636,20 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 4; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1585,7 +1668,7 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, cSrc3 = state->cmykTransferK[cSrcPtr[3]]; //----- source alpha - aSrc = shape; + aSrc = alpha; //----- special case for aSrc = 255 if (aSrc == 255) { @@ -1626,7 +1709,7 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -1635,12 +1718,12 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, // special case: -// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// !pipe->pattern && pipe->alphaOnly && !state->blendFunc && // bitmap->mode == splashModeMono8 && !bitmap->alpha void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, + Guchar *shapePtr, Guchar *alphaPtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, cSrc0, cDest0, cResult0; + Guchar alpha, aSrc, cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; int cSrcStride, x, lastX; @@ -1651,11 +1734,11 @@ void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1664,18 +1747,18 @@ void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { ++destColorPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1684,7 +1767,7 @@ void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = shape; + aSrc = alpha; //----- special case for aSrc = 255 if (aSrc == 255) { @@ -1702,7 +1785,7 @@ void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, *destColorPtr++ = cResult0; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -1710,12 +1793,13 @@ void Splash::pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, // special case: // !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// usesAlpha && !pipe->alpha0Ptr && !state->blendFunc && // !pipe->nonIsolatedGroup && // bitmap->mode == splashModeMono1 && !bitmap->alpha void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, cSrc0, cDest0, cResult0; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; Guchar destColorMask; SplashScreenCursor screenCursor; @@ -1728,11 +1812,11 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1741,7 +1825,7 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; destColorMask = (Guchar)(0x80 >> (x0 & 7)); @@ -1750,13 +1834,13 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += destColorMask & 1; destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1)); cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1768,7 +1852,7 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result color // note: aDest = alphaI = aResult = 0xff @@ -1784,7 +1868,7 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, destColorMask = (Guchar)((destColorMask << 7) | (destColorMask >> 1)); cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -1792,12 +1876,13 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, // special case: // !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// usesAlpha && !pipe->alpha0Ptr && !state->blendFunc && // !pipe->nonIsolatedGroup && // bitmap->mode == splashModeMono8 && bitmap->alpha void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; Guchar *destAlphaPtr; int cSrcStride, x, lastX; @@ -1809,11 +1894,11 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1822,20 +1907,20 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { ++destColorPtr; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1848,7 +1933,7 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -1866,7 +1951,7 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -1874,12 +1959,13 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, // special case: // !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// usesAlpha && !pipe->alpha0Ptr && !state->blendFunc && // !pipe->nonIsolatedGroup && // bitmap->mode == splashModeRGB8 && bitmap->alpha void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -1894,11 +1980,11 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -1907,20 +1993,20 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -1937,7 +2023,7 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -1962,7 +2048,7 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -1970,12 +2056,13 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, // special case: // !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// usesAlpha && !pipe->alpha0Ptr && !state->blendFunc && // !pipe->nonIsolatedGroup && // bitmap->mode == splashModeBGR8 && bitmap->alpha void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -1990,11 +2077,11 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2003,20 +2090,20 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2033,7 +2120,7 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -2058,7 +2145,7 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -2067,12 +2154,13 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, #if SPLASH_CMYK // special case: // !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// usesAlpha && !pipe->alpha0Ptr && !state->blendFunc && // !pipe->nonIsolatedGroup && // bitmap->mode == splashModeCMYK8 && bitmap->alpha void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2, cSrc3; Guchar cDest0, cDest1, cDest2, cDest3; Guchar cResult0, cResult1, cResult2, cResult3; @@ -2087,11 +2175,11 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2100,20 +2188,20 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 4; ++destAlphaPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2148,7 +2236,7 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, } //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -2176,7 +2264,7 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -2185,14 +2273,15 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, // special case: -// !pipe->pattern && aInput == 255 && state->softMask && usesShape && +// !pipe->pattern && aInput == 255 && state->softMask && usesAlpha && // !state->inNonIsolatedGroup && !state->inKnockoutGroup && // !nonIsolatedGroup && state->overprintMask == 0xffffffff && // !state->blendFunc && // bitmap->mode == splashModeMono8 && bitmap->alpha void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; Guchar *destAlphaPtr; @@ -2206,11 +2295,11 @@ void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2219,7 +2308,7 @@ void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -2227,14 +2316,14 @@ void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { ++destColorPtr; ++destAlphaPtr; ++softMaskPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2243,7 +2332,7 @@ void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = div255(*softMaskPtr++ * shape); + aSrc = div255(*softMaskPtr++ * alpha); //----- special case for aSrc = 255 if (aSrc == 255) { @@ -2278,21 +2367,22 @@ void Splash::pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); } // special case: -// !pipe->pattern && aInput == 255 && state->softMask && usesShape && +// !pipe->pattern && aInput == 255 && state->softMask && usesAlpha && // !state->inNonIsolatedGroup && !state->inKnockoutGroup && // !nonIsolatedGroup && state->overprintMask == 0xffffffff && // !state->blendFunc && // bitmap->mode == splashModeRGB8 && bitmap->alpha void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -2308,11 +2398,11 @@ void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2321,7 +2411,7 @@ void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -2329,14 +2419,14 @@ void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; ++softMaskPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2347,7 +2437,7 @@ void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = div255(*softMaskPtr++ * shape); + aSrc = div255(*softMaskPtr++ * alpha); //----- special case for aSrc = 255 if (aSrc == 255) { @@ -2392,21 +2482,22 @@ void Splash::pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); } // special case: -// !pipe->pattern && aInput == 255 && state->softMask && usesShape && +// !pipe->pattern && aInput == 255 && state->softMask && usesAlpha && // !state->inNonIsolatedGroup && !state->inKnockoutGroup && // !nonIsolatedGroup && state->overprintMask == 0xffffffff && // !state->blendFunc && // bitmap->mode == splashModeBGR8 && bitmap->alpha void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -2422,11 +2513,11 @@ void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2435,7 +2526,7 @@ void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -2443,14 +2534,14 @@ void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; ++softMaskPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2461,7 +2552,7 @@ void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = div255(*softMaskPtr++ * shape); + aSrc = div255(*softMaskPtr++ * alpha); //----- special case for aSrc = 255 if (aSrc == 255) { @@ -2506,7 +2597,7 @@ void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -2514,14 +2605,15 @@ void Splash::pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, #if SPLASH_CMYK // special case: -// !pipe->pattern && aInput == 255 && state->softMask && usesShape && +// !pipe->pattern && aInput == 255 && state->softMask && usesAlpha && // !state->inNonIsolatedGroup && !state->inKnockoutGroup && // !nonIsolatedGroup && state->overprintMask == 0xffffffff && // !state->blendFunc && // bitmap->mode == splashModeCMYK8 && bitmap->alpha void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, aResult; Guchar cSrc0, cSrc1, cSrc2, cSrc3; Guchar cDest0, cDest1, cDest2, cDest3; Guchar cResult0, cResult1, cResult2, cResult3; @@ -2537,11 +2629,11 @@ void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2550,7 +2642,7 @@ void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 4]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; @@ -2558,14 +2650,14 @@ void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 4; ++destAlphaPtr; ++softMaskPtr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2586,7 +2678,7 @@ void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, cSrc3 = state->cmykTransferK[cSrcPtr[3]]; //----- source alpha - aSrc = div255(*softMaskPtr++ * shape); + aSrc = div255(*softMaskPtr++ * alpha); //----- special case for aSrc = 255 if (aSrc == 255) { @@ -2627,7 +2719,7 @@ void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } updateModX(lastX); @@ -2636,8 +2728,9 @@ void Splash::pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, void Splash::pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, alpha0, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, alpha0, aResult; Guchar cSrc0, cDest0, cResult0; SplashColorPtr destColorPtr; Guchar *destAlphaPtr; @@ -2651,11 +2744,11 @@ void Splash::pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2664,24 +2757,28 @@ void Splash::pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; - alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y) - * groupBackBitmap->alphaRowSize + - (groupBackX + x0)]; + if (alpha0Bitmap) { + alpha0Ptr = &alpha0Bitmap->alpha[y * alpha0Bitmap->alphaRowSize + x0]; + } else { + alpha0Ptr = &parent->bitmap->alpha[ + (parentOffsetY + y) * parent->bitmap->alphaRowSize + + (parentOffsetX + x0)]; + } for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 1; ++destAlphaPtr; ++alpha0Ptr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2694,7 +2791,7 @@ void Splash::pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y, cSrc0 = state->grayTransfer[cSrcPtr[0]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -2713,15 +2810,16 @@ void Splash::pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } // for (x ...) updateModX(lastX); } void Splash::pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, alpha0, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, alpha0, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -2737,11 +2835,11 @@ void Splash::pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2750,24 +2848,28 @@ void Splash::pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; - alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y) - * groupBackBitmap->alphaRowSize + - (groupBackX + x0)]; + if (alpha0Bitmap) { + alpha0Ptr = &alpha0Bitmap->alpha[y * alpha0Bitmap->alphaRowSize + x0]; + } else { + alpha0Ptr = &parent->bitmap->alpha[ + (parentOffsetY + y) * parent->bitmap->alphaRowSize + + (parentOffsetX + x0)]; + } for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; ++alpha0Ptr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2784,7 +2886,7 @@ void Splash::pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -2810,15 +2912,16 @@ void Splash::pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } // for (x ...) updateModX(lastX); } void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, alpha0, aResult; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, alpha0, aResult; Guchar cSrc0, cSrc1, cSrc2; Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; @@ -2834,11 +2937,11 @@ void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2847,24 +2950,28 @@ void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 3]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; - alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y) - * groupBackBitmap->alphaRowSize + - (groupBackX + x0)]; + if (alpha0Bitmap) { + alpha0Ptr = &alpha0Bitmap->alpha[y * alpha0Bitmap->alphaRowSize + x0]; + } else { + alpha0Ptr = &parent->bitmap->alpha[ + (parentOffsetY + y) * parent->bitmap->alphaRowSize + + (parentOffsetX + x0)]; + } for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 3; ++destAlphaPtr; ++alpha0Ptr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2881,7 +2988,7 @@ void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, cSrc2 = state->rgbTransferB[cSrcPtr[2]]; //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -2907,7 +3014,7 @@ void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } // for (x ...) updateModX(lastX); @@ -2915,8 +3022,9 @@ void Splash::pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, #if SPLASH_CMYK void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr) { - Guchar shape, aSrc, aDest, alphaI, alpha0, aResult, aPrev; + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr) { + Guchar alpha, aSrc, aDest, alphaI, alpha0, aResult, aPrev; Guchar cSrc0, cSrc1, cSrc2, cSrc3; Guchar cDest0, cDest1, cDest2, cDest3; Guchar cResult0, cResult1, cResult2, cResult3; @@ -2932,11 +3040,11 @@ void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, cSrcStride = 0; } for (; x0 <= x1; ++x0) { - if (*shapePtr) { + if (*alphaPtr) { break; } cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } if (x0 > x1) { return; @@ -2945,24 +3053,28 @@ void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, updateModY(y); lastX = x0; - useDestRow(y); + useBitmapRow(y); destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * 4]; destAlphaPtr = &bitmap->alpha[y * bitmap->alphaRowSize + x0]; - alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + y) - * groupBackBitmap->alphaRowSize + - (groupBackX + x0)]; + if (alpha0Bitmap) { + alpha0Ptr = &alpha0Bitmap->alpha[y * alpha0Bitmap->alphaRowSize + x0]; + } else { + alpha0Ptr = &parent->bitmap->alpha[ + (parentOffsetY + y) * parent->bitmap->alphaRowSize + + (parentOffsetX + x0)]; + } for (x = x0; x <= x1; ++x) { - //----- shape - shape = *shapePtr; - if (!shape) { + //----- alpha + alpha = *alphaPtr; + if (!alpha) { destColorPtr += 4; ++destAlphaPtr; ++alpha0Ptr; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; continue; } lastX = x; @@ -2998,7 +3110,7 @@ void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, } //----- source alpha - aSrc = div255(pipe->aInput * shape); + aSrc = div255(pipe->aInput * alpha); //----- result alpha and non-isolated group element correction aResult = (Guchar)(aSrc + aDest - div255(aSrc * aDest)); @@ -3027,7 +3139,7 @@ void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, *destAlphaPtr++ = aResult; cSrcPtr += cSrcStride; - ++shapePtr; + ++alphaPtr; } // for (x ...) updateModX(lastX); @@ -3035,58 +3147,61 @@ void Splash::pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, #endif -void Splash::useDestRow(int y) { - int y0, y1, yy; - - if (groupDestInitMode == splashGroupDestPreInit) { +void Splash::useBitmapRow(int y) { + if (!deferredInit) { return; } - if (groupDestInitYMin > groupDestInitYMax) { + + int y0, y1; + if (deferredInitYMin > deferredInitYMax) { y0 = y1 = y; - groupDestInitYMin = groupDestInitYMax = y; - } else if (y < groupDestInitYMin) { + deferredInitYMin = deferredInitYMax = y; + } else if (y < deferredInitYMin) { y0 = y; - y1 = groupDestInitYMin - 1; - groupDestInitYMin = y; - } else if (y > groupDestInitYMax) { - y0 = groupDestInitYMax + 1; + y1 = deferredInitYMin - 1; + deferredInitYMin = y; + } else if (y > deferredInitYMax) { + y0 = deferredInitYMax + 1; y1 = y; - groupDestInitYMax = y; + deferredInitYMax = y; } else { return; } - for (yy = y0; yy <= y1; ++yy) { - if (groupDestInitMode == splashGroupDestInitZero) { - // same as clear(color=0, alpha=0) - memset(bitmap->data + bitmap->rowSize * yy, 0, - bitmap->rowSize < 0 ? -bitmap->rowSize : bitmap->rowSize); - if (bitmap->alpha) { - memset(bitmap->alpha + bitmap->alphaRowSize * yy, 0, - bitmap->alphaRowSize); - } - } else { // (groupDestInitMode == splashGroupDestInitCopy) - // same as blitTransparent - copyGroupBackdropRow(yy); + + parent->useBitmapRow(parentOffsetY + y); + if (state->inNonIsolatedGroup) { + for (int yy = y0; yy <= y1; ++yy) { + copyParentRowColor(yy); + } + } else { + for (int yy = y0; yy <= y1; ++yy) { + zeroRowColor(yy); + } + } + if (bitmap->alpha) { + for (int yy = y0; yy <= y1; ++yy) { + zeroRowAlpha(yy); + } + } + if (alpha0Bitmap) { + for (int yy = y0; yy <= y1; ++yy) { + computeAlpha0Row(yy); } } } -void Splash::copyGroupBackdropRow(int y) { - SplashColorPtr p, q; - Guchar mask, srcMask; - int x; - - if (groupBackBitmap->mode != bitmap->mode) { +void Splash::copyParentRowColor(int y) { + if (parent->bitmap->mode != bitmap->mode) { return; } - if (bitmap->mode == splashModeMono1) { - p = &bitmap->data[y * bitmap->rowSize]; - mask = (Guchar)0x80; - q = &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize - + (groupBackX >> 3)]; - srcMask = (Guchar)(0x80 >> (groupBackX & 7)); - for (x = 0; x < bitmap->width; ++x) { + SplashColorPtr p = &bitmap->data[y * bitmap->rowSize]; + Guchar mask = (Guchar)0x80; + SplashColorPtr q = + &parent->bitmap->data[(parentOffsetY + y) * parent->bitmap->rowSize + + (parentOffsetX >> 3)]; + Guchar srcMask = (Guchar)(0x80 >> (parentOffsetX & 7)); + for (int x = 0; x < bitmap->width; ++x) { if (*q & srcMask) { *p |= mask; } else { @@ -3102,14 +3217,44 @@ void Splash::copyGroupBackdropRow(int y) { } } } else { - p = &bitmap->data[y * bitmap->rowSize]; - q = &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize - + bitmapComps * groupBackX]; + SplashColorPtr p = &bitmap->data[y * bitmap->rowSize]; + SplashColorPtr q = + &parent->bitmap->data[(parentOffsetY + y) * parent->bitmap->rowSize + + bitmapComps * parentOffsetX]; memcpy(p, q, bitmapComps * bitmap->width); } +} - if (bitmap->alpha) { - memset(&bitmap->alpha[y * bitmap->alphaRowSize], 0, bitmap->width); +void Splash::zeroRowColor(int y) { + memset(&bitmap->data[y * bitmap->rowSize], 0, + bitmap->rowSize < 0 ? -bitmap->rowSize : bitmap->rowSize); +} + +void Splash::zeroRowAlpha(int y) { + memset(&bitmap->alpha[y * bitmap->alphaRowSize], 0, bitmap->width); +} + +void Splash::computeAlpha0Row(int y) { + Guchar *p = &alpha0Bitmap->alpha[y * alpha0Bitmap->alphaRowSize]; + Guchar *q0; + if (parent->alpha0Bitmap) { + q0 = &parent->alpha0Bitmap->alpha[ + (parentOffsetY + y) * parent->alpha0Bitmap->alphaRowSize + + parentOffsetX]; + } else { + q0 = &parent->parent->bitmap->alpha[ + (parentOffsetY + parent->parentOffsetY + y) + * parent->parent->bitmap->alphaRowSize + + parentOffsetX + parent->parentOffsetX]; + } + Guchar *q1 = &parent->bitmap->alpha[ + (parentOffsetY + y) * parent->bitmap->alphaRowSize + + parentOffsetX]; + int w = alpha0Bitmap->width; + for (int x = 0; x < w; ++x) { + Guchar a0 = *q0++; + Guchar a1 = *q1++; + *p++ = (Guchar)(a0 + a1 - div255(a0 * a1)); } } @@ -4492,7 +4637,6 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, bitmap = bitmapA; bitmapComps = splashColorModeNComps[bitmap->mode]; vectorAntialias = vectorAntialiasA; - inShading = gFalse; state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, screenParams); scanBuf = (Guchar *)gmalloc(bitmap->width); @@ -4501,8 +4645,10 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, } else { scanBuf2 = NULL; } - groupBackBitmap = NULL; - groupDestInitMode = splashGroupDestPreInit; + parent = NULL; + deferredInit = gFalse; + alpha0Bitmap = NULL; + shapeBitmap = NULL; overprintMaskBitmap = NULL; minLineWidth = 0; clearModRegion(); @@ -4521,7 +4667,6 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, bitmap = bitmapA; bitmapComps = splashColorModeNComps[bitmap->mode]; vectorAntialias = vectorAntialiasA; - inShading = gFalse; state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, screenA); scanBuf = (Guchar *)gmalloc(bitmap->width); @@ -4530,8 +4675,10 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, } else { scanBuf2 = NULL; } - groupBackBitmap = NULL; - groupDestInitMode = splashGroupDestPreInit; + parent = NULL; + deferredInit = gFalse; + alpha0Bitmap = NULL; + shapeBitmap = NULL; overprintMaskBitmap = NULL; minLineWidth = 0; clearModRegion(); @@ -4713,6 +4860,10 @@ void Splash::setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust) { state->strokeAdjust = strokeAdjust; } +void Splash::setAlphaIsShape(GBool alphaIsShape) { + state->alphaIsShape = alphaIsShape; +} + void Splash::clipResetToRect(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1) { state->clipResetToRect(x0, y0, x1, y1); @@ -4731,23 +4882,26 @@ void Splash::setSoftMask(SplashBitmap *softMask, GBool deleteBitmap) { state->setSoftMask(softMask, deleteBitmap); } -void Splash::setInTransparencyGroup(SplashBitmap *groupBackBitmapA, - int groupBackXA, int groupBackYA, - SplashGroupDestInitMode groupDestInitModeA, +void Splash::setInTransparencyGroup(Splash *parentA, + int parentOffsetXA, int parentOffsetYA, + SplashAlphaBitmap *alpha0BitmapA, + SplashAlphaBitmap *shapeBitmapA, GBool nonIsolated, GBool knockout) { - groupBackBitmap = groupBackBitmapA; - groupBackX = groupBackXA; - groupBackY = groupBackYA; - groupDestInitMode = groupDestInitModeA; - groupDestInitYMin = 1; - groupDestInitYMax = 0; + parent = parentA; + parentOffsetX = parentOffsetXA; + parentOffsetY = parentOffsetYA; + deferredInit = gTrue; + deferredInitYMin = 1; + deferredInitYMax = 0; + alpha0Bitmap = alpha0BitmapA; + shapeBitmap = shapeBitmapA; state->inNonIsolatedGroup = nonIsolated; state->inKnockoutGroup = knockout; } void Splash::forceDeferredInit(int y, int h) { - useDestRow(y); - useDestRow(y + h - 1); + useBitmapRow(y); + useBitmapRow(y + h - 1); } // Check that alpha is 0 in the specified rectangle. @@ -4763,15 +4917,14 @@ GBool Splash::checkTransparentRect(int x, int y, int w, int h) { return gFalse; } int yy0, yy1; - if (groupDestInitMode == splashGroupDestPreInit) { + if (deferredInit) { + // all transparency groups initialize alpha to zero, so anything + // outside of groupDestInit[YMin,YMax] will have alpha=0 + yy0 = (y > deferredInitYMin) ? y : deferredInitYMin; + yy1 = (y + h - 1 < deferredInitYMax) ? y + h - 1 : deferredInitYMax; + } else { yy0 = y; yy1 = y + h - 1; - } else { - // both splashGroupDestInitZero and splashGroupDestInitCopy set - // alpha to zero, so anything outside of groupDestInit[YMin,YMax] - // will have alpha=0 - yy0 = (y > groupDestInitYMin) ? y : groupDestInitYMin; - yy1 = (y + h - 1 < groupDestInitYMax) ? y + h - 1 : groupDestInitYMax; } Guchar *alphaP = &bitmap->alpha[yy0 * bitmap->alphaRowSize + x]; for (int yy = yy0; yy <= yy1; ++yy) { @@ -4930,7 +5083,7 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) { SplashError Splash::stroke(SplashPath *path) { SplashPath *path2, *dPath; - SplashCoord t0, t1, t2, t3, w, w2, lineDashMax, lineDashTotal; + SplashCoord w, w2, lineDashMax, lineDashTotal; int lineCap, lineJoin, i; if (debugMode) { @@ -4942,6 +5095,9 @@ SplashError Splash::stroke(SplashPath *path) { if (path->length == 0) { return splashErrEmptyPath; } + if (pathAllOutside(path, gTrue)) { + return splashOk; + } path2 = flattenPath(path, state->matrix, state->flatness); // Compute an approximation of the transformed line width. @@ -4953,15 +5109,13 @@ SplashError Splash::stroke(SplashPath *path) { // [0 +/-s] [+/-s 0] // well, and still does something reasonable for the uncommon // case transforms. - t0 = splashAbs(state->matrix[0]); - t1 = splashAbs(state->matrix[1]); - t2 = splashAbs(state->matrix[2]); - t3 = splashAbs(state->matrix[3]); - if (t0 * t3 >= t1 * t2) { - w = (t0 < t3) ? t0 : t3; - } else { - w = (t1 < t2) ? t1 : t2; - } + double t0 = splashAbs(state->matrix[0]); + double t1 = splashAbs(state->matrix[1]); + double t2 = splashAbs(state->matrix[2]); + double t3 = splashAbs(state->matrix[3]); + double t01 = t0 * t0 + t1 * t1; + double t23 = t2 * t2 + t3 * t3; + w = sqrt((t01 > t23) ? t01 : t23); w2 = w * state->lineWidth; // construct the dashed path @@ -4972,6 +5126,10 @@ SplashError Splash::stroke(SplashPath *path) { // pixel, don't apply the dash pattern; this avoids a huge // performance/memory hit with PDF files that use absurd dash // patterns like [0.0007 0.0003] + // + // we also skip the dash pattern for very long paths with short + // (but not necessarily sub-pixel) dash patterns -- Adobe appears + // to do something similar lineDashTotal = 0; lineDashMax = 0; for (i = 0; i < state->lineDashLength; ++i) { @@ -4985,8 +5143,8 @@ SplashError Splash::stroke(SplashPath *path) { delete path2; return splashOk; } - if (w * lineDashMax > 0.1) { - + if (w * lineDashMax > 0.1 && + w * lineDashMax > 0.0001 * path->length) { dPath = makeDashedPath(path2); delete path2; path2 = dPath; @@ -5056,11 +5214,11 @@ void Splash::strokeNarrow(SplashPath *path) { xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse, state->enablePathSimplification, - state->strokeAdjust); + state->strokeAdjust, state->clip); pipeInit(&pipe, state->strokePattern, (Guchar)splashRound(state->strokeAlpha * 255), - gTrue, gFalse); + gFalse, gTrue, gFalse); for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) { if (seg->y0 <= seg->y1) { @@ -5074,6 +5232,44 @@ void Splash::strokeNarrow(SplashPath *path) { x0 = splashFloor(seg->x1); x1 = splashFloor(seg->x0); } + + // With CAD-mode stroke adjustment, and a simple rectangular clip + // region, horizontal and vertical stroke-adjusted edges that fall + // slightly outside the clip region are adjusted back inside the + // clip region. This avoids problems with narrow lines in + // slightly mismatched clip rectangles, which appear to be + // generated somewhat commonly by buggy CAD software. This is + // similar to the code in SplashXPath::strokeAdjust() -- narrow + // strokes aren't stroke-adjusted, so this tweak has to be done + // here. + if (y0 == y1 && + seg->y0 == seg->y1 && + state->clip->getIsSimple() && + state->strokeAdjust == splashStrokeAdjustCAD) { + SplashCoord cy0 = state->clip->getYMin(); + SplashCoord cy1 = state->clip->getYMax(); + int cyi0 = state->clip->getYMinI(state->strokeAdjust); + int cyi1 = state->clip->getYMaxI(state->strokeAdjust); + if (y0 == cyi0 - 1 && cy0 - seg->y0 < 0.5) { + y0 = y1 = y0 + 1; + } else if (y0 == cyi1 + 1 && seg->y0 - cy1 < 0.5) { + y0 = y1 = y0 - 1; + } + } else if (x0 == x1 && + seg->x0 == seg->x1 && + state->clip->getIsSimple() && + state->strokeAdjust == splashStrokeAdjustCAD) { + SplashCoord cx0 = state->clip->getXMin(); + SplashCoord cx1 = state->clip->getXMax(); + int cxi0 = state->clip->getXMinI(state->strokeAdjust); + int cxi1 = state->clip->getXMaxI(state->strokeAdjust); + if (x0 == cxi0 - 1 && cx0 - seg->x0 < 0.5) { + x0 = x1 = x0 + 1; + } else if (x0 == cxi1 + 1 && seg->x0 - cx1 < 0.5) { + x0 = x1 = x0 - 1; + } + } + if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, x0 <= x1 ? x1 : x0, y1, state->strokeAdjust)) @@ -5084,6 +5280,18 @@ void Splash::strokeNarrow(SplashPath *path) { } else { drawStrokeSpan(&pipe, x1, x0, y0, clipRes == splashClipAllInside); } + } else if (x0 == x1) { + y = state->clip->getYMinI(state->strokeAdjust); + if (y0 < y) { + y0 = y; + } + y = state->clip->getYMaxI(state->strokeAdjust); + if (y1 > y) { + y1 = y; + } + for (y = y0; y <= y1; ++y) { + drawStrokeSpan(&pipe, x0, x0, y, clipRes == splashClipAllInside); + } } else { dxdy = seg->dxdy; y = state->clip->getYMinI(state->strokeAdjust); @@ -5094,7 +5302,7 @@ void Splash::strokeNarrow(SplashPath *path) { y = state->clip->getYMaxI(state->strokeAdjust); if (y1 > y) { y1 = y; - x1 = splashFloor(seg->x0 + ((SplashCoord)y1 - seg->y0) * dxdy); + x1 = splashFloor(seg->x0 + ((SplashCoord)y1 + 1 - seg->y0) * dxdy); } if (x0 <= x1) { xa = x0; @@ -5135,6 +5343,7 @@ void Splash::strokeNarrow(SplashPath *path) { } ++nClipRes[clipRes]; } + if (nClipRes[splashClipPartial] || (nClipRes[splashClipAllInside] && nClipRes[splashClipAllOutside])) { opClipRes = splashClipPartial; @@ -5170,7 +5379,7 @@ void Splash::drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, return; } } - (this->*pipe->run)(pipe, x0, x1, y, scanBuf + x0, NULL); + (this->*pipe->run)(pipe, x0, x1, y, scanBuf + x0, scanBuf + x0, NULL); } void Splash::strokeWide(SplashPath *path, SplashCoord w, @@ -5326,16 +5535,14 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) { return new SplashPath(); } lineDashStartPhase = state->lineDashPhase; - if (lineDashStartPhase > lineDashTotal * 2) { - i = splashFloor(lineDashStartPhase / (lineDashTotal * 2)); - lineDashStartPhase -= lineDashTotal * i * 2; - } else if (lineDashStartPhase < 0) { - i = splashCeil(-lineDashStartPhase / (lineDashTotal * 2)); - lineDashStartPhase += lineDashTotal * i * 2; - } - i = splashFloor(lineDashStartPhase / lineDashTotal); - lineDashStartPhase -= (SplashCoord)i * lineDashTotal; - lineDashStartOn = gTrue; + if (lineDashStartPhase > 0) { + i = splashFloor(lineDashStartPhase / lineDashTotal); + lineDashStartPhase -= lineDashTotal * i; + } else { + i = splashCeil(-lineDashStartPhase / lineDashTotal); + lineDashStartPhase += lineDashTotal * i; + } + lineDashStartOn = !((state->lineDashLength & 1) && (i & 1)); lineDashStartIdx = 0; if (lineDashStartPhase > 0) { while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) { @@ -5377,6 +5584,14 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) { y1 = path->pts[k+1].y; segLen = splashDist(x0, y0, x1, y1); + // Special case for zero-length subpath: copy the zero-length + // segment into the dashed path so that the round line cap + // special case is handled. + if (j == i+1 && segLen == 0) { + dPath->moveTo(x0, y0); + dPath->lineTo(x0, y0); + } + // process the segment while (segLen > 0) { @@ -5477,6 +5692,13 @@ SplashError Splash::fill(SplashPath *path, GBool eo) { printf("fill [eo:%d]:\n", eo); dumpPath(path); } + if (path->length == 0) { + return splashErrEmptyPath; + } + if (pathAllOutside(path, gFalse)) { + opClipRes = splashClipAllOutside; + return splashOk; + } return fillWithPattern(path, eo, state->fillPattern, state->fillAlpha); } @@ -5490,19 +5712,11 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, int xMin, yMin, xMax, xMin2, xMax2, yMax, y, t; SplashClipResult clipRes; - if (path->length == 0) { - return splashErrEmptyPath; - } - if (pathAllOutside(path)) { - opClipRes = splashClipAllOutside; - return splashOk; - } - path2 = tweakFillPath(path); xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue, state->enablePathSimplification, - state->strokeAdjust); + state->strokeAdjust, state->clip); if (path2 != path) { delete path2; } @@ -5540,10 +5754,10 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, } pipeInit(&pipe, pattern, (Guchar)splashRound(alpha * 255), - gTrue, gFalse); + gFalse, gTrue, gFalse); // draw the spans - if (vectorAntialias && !inShading) { + if (vectorAntialias) { for (y = yMin; y <= yMax; ++y) { scanner->getSpan(scanBuf, y, xMin, xMax, &xMin2, &xMax2); if (xMin2 <= xMax2) { @@ -5551,7 +5765,8 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, state->clip->clipSpan(scanBuf, y, xMin2, xMax2, state->strokeAdjust); } - (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL); + (this->*pipe.run)(&pipe, xMin2, xMax2, y, + NULL, scanBuf + xMin2, NULL); } } } else { @@ -5562,7 +5777,8 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, state->clip->clipSpanBinary(scanBuf, y, xMin2, xMax2, state->strokeAdjust); } - (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL); + (this->*pipe.run)(&pipe, xMin2, xMax2, y, + NULL, scanBuf + xMin2, NULL); } } } @@ -5678,13 +5894,17 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) { return path2; } -GBool Splash::pathAllOutside(SplashPath *path) { +// Returns true if [path] is entirely outside the current clipping +// path. The path coordinates have not been stroke adjusted, so we +// compare against the floating point clip rect. If [stroke] is true, +// allow for the stroke width and miter limit. +GBool Splash::pathAllOutside(SplashPath *path, GBool stroke) { SplashCoord xMin1, yMin1, xMax1, yMax1; SplashCoord xMin2, yMin2, xMax2, yMax2; SplashCoord x, y; - int xMinI, yMinI, xMaxI, yMaxI; int i; + //--- compute the path's bbox in user space xMin1 = xMax1 = path->pts[0].x; yMin1 = yMax1 = path->pts[0].y; for (i = 1; i < path->length; ++i) { @@ -5700,6 +5920,19 @@ GBool Splash::pathAllOutside(SplashPath *path) { } } + //--- allow for stroke width and miter limit + if (stroke && state->lineWidth > 0) { + SplashCoord w = state->lineWidth * 0.5; + if (state->lineJoin == splashLineJoinMiter) { + w *= state->miterLimit; + } + xMin1 -= w; + yMin1 -= w; + xMax1 += w; + yMax1 += w; + } + + //--- convert path bbox to device space transform(state->matrix, xMin1, yMin1, &x, &y); xMin2 = xMax2 = x; yMin2 = yMax2 = y; @@ -5736,29 +5969,31 @@ GBool Splash::pathAllOutside(SplashPath *path) { } else if (y > yMax2) { yMax2 = y; } - // sanity-check the coordinates - xMinI/yMinI/xMaxI/yMaxI are - // 32-bit integers, so coords need to be < 2^31 - SplashXPath::clampCoords(&xMin2, &yMin2); - SplashXPath::clampCoords(&xMax2, &yMax2); - xMinI = splashFloor(xMin2); - yMinI = splashFloor(yMin2); - xMaxI = splashFloor(xMax2); - yMaxI = splashFloor(yMax2); - return state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI, - state->strokeAdjust) == - splashClipAllOutside; + //--- handle zero-width strokes + if (stroke && state->lineWidth == 0) { + xMin1 -= 1; + yMin1 -= 1; + xMax1 += 1; + yMax1 += 1; + } + + //--- check against the clip rect + return xMin2 > state->clip->getXMax() || + xMax2 < state->clip->getXMin() || + yMin2 > state->clip->getYMax() || + yMax2 < state->clip->getYMin(); } SplashError Splash::fillChar(SplashCoord x, SplashCoord y, - int c, SplashFont *font) { + Guint c, SplashFont *font) { SplashGlyphBitmap glyph; SplashCoord xt, yt; int x0, y0, xFrac, yFrac; SplashError err; if (debugMode) { - printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n", + printf("fillChar: x=%.2f y=%.2f c=%3u=0x%02x='%c'\n", (double)x, (double)y, c, c, c); } transform(state->matrix, x, y, &xt, &yt); @@ -5806,13 +6041,15 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { != splashClipAllOutside) { pipeInit(&pipe, state->fillPattern, (Guchar)splashRound(state->fillAlpha * 255), - gTrue, gFalse); + gFalse, gTrue, gFalse); if (clipRes == splashClipAllInside) { if (glyph->aa) { p = glyph->data; for (y = yMin; y <= yMax; ++y) { (this->*pipe.run)(&pipe, xMin, xMax, y, - glyph->data + (y - yMin) * glyph->w, NULL); + NULL, + glyph->data + (y - yMin) * glyph->w, + NULL); } } else { p = glyph->data; @@ -5824,7 +6061,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { alpha = (Guchar)(alpha << 1); } } - (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); + (this->*pipe.run)(&pipe, xMin, xMax, y, + NULL, scanBuf + xMin, NULL); } } } else { @@ -5847,7 +6085,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { memcpy(scanBuf + xMin, p, xMax - xMin + 1); state->clip->clipSpan(scanBuf, y, xMin, xMax, state->strokeAdjust); - (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); + (this->*pipe.run)(&pipe, xMin, xMax, y, + NULL, scanBuf + xMin, NULL); } } else { for (y = yMin; y <= yMax; ++y) { @@ -5869,7 +6108,8 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { } state->clip->clipSpanBinary(scanBuf, y, xMin, xMax, state->strokeAdjust); - (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); + (this->*pipe.run)(&pipe, xMin, xMax, y, + NULL, scanBuf + xMin, NULL); } } } @@ -6022,6 +6262,9 @@ SplashError Splash::fillImageMask(GString *imageTag, SplashClipResult clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1, state->strokeAdjust); + if (clipRes == splashClipAllOutside) { + return splashOk; + } // If the scaled mask is much wider and/or taller than the clip // region, we use the "arbitrary" scaling path, to avoid a // potentially very slow loop in the flips-only path (which scans @@ -6038,7 +6281,7 @@ SplashError Splash::fillImageMask(GString *imageTag, SplashDrawImageMaskRowData dd; pipeInit(&dd.pipe, state->fillPattern, (Guchar)splashRound(state->fillAlpha * 255), - gTrue, gFalse); + gFalse, gTrue, gFalse); //--- choose the drawRow function SplashDrawImageMaskRowFunc drawRowFunc; @@ -6054,93 +6297,89 @@ SplashError Splash::fillImageMask(GString *imageTag, //--- horizontal/vertical flips only if (flipsOnly && !veryLarge) { - if (clipRes != splashClipAllOutside) { - int scaledWidth = xMax - xMin; - int scaledHeight = yMax - yMin; - ImageMaskScaler scaler(src, srcData, w, h, - scaledWidth, scaledHeight, interpolate, antialias); - Guchar *tmpLine = NULL; - if (horizFlip) { - tmpLine = (Guchar *)gmalloc(scaledWidth); + int scaledWidth = xMax - xMin; + int scaledHeight = yMax - yMin; + ImageMaskScaler scaler(src, srcData, w, h, + scaledWidth, scaledHeight, interpolate, antialias); + Guchar *tmpLine = NULL; + if (horizFlip) { + tmpLine = (Guchar *)gmalloc(scaledWidth); + } + if (vertFlip) { + if (horizFlip) { // bottom-up, mirrored + for (int y = 0; y < scaledHeight; ++y) { + scaler.nextLine(); + mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth); + (this->*drawRowFunc)(&dd, tmpLine, + xMin, yMax - 1 - y, scaledWidth); + } + } else { // bottom-up + for (int y = 0; y < scaledHeight; ++y) { + scaler.nextLine(); + (this->*drawRowFunc)(&dd, scaler.data(), + xMin, yMax - 1 - y, scaledWidth); + } } - if (vertFlip) { - if (horizFlip) { // bottom-up, mirrored - for (int y = 0; y < scaledHeight; ++y) { - scaler.nextLine(); - mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth); - (this->*drawRowFunc)(&dd, tmpLine, - xMin, yMax - 1 - y, scaledWidth); - } - } else { // bottom-up - for (int y = 0; y < scaledHeight; ++y) { - scaler.nextLine(); - (this->*drawRowFunc)(&dd, scaler.data(), - xMin, yMax - 1 - y, scaledWidth); - } + } else { + if (horizFlip) { // top-down, mirrored + for (int y = 0; y < scaledHeight; ++y) { + scaler.nextLine(); + mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth); + (this->*drawRowFunc)(&dd, tmpLine, + xMin, yMin + y, scaledWidth); } - } else { - if (horizFlip) { // top-down, mirrored - for (int y = 0; y < scaledHeight; ++y) { - scaler.nextLine(); - mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth); - (this->*drawRowFunc)(&dd, tmpLine, - xMin, yMin + y, scaledWidth); - } - } else { // top-down - for (int y = 0; y < scaledHeight; ++y) { - scaler.nextLine(); - (this->*drawRowFunc)(&dd, scaler.data(), - xMin, yMin + y, scaledWidth); - } + } else { // top-down + for (int y = 0; y < scaledHeight; ++y) { + scaler.nextLine(); + (this->*drawRowFunc)(&dd, scaler.data(), + xMin, yMin + y, scaledWidth); } } - gfree(tmpLine); } + gfree(tmpLine); //--- 90/270 rotation } else if (rot90Only && !veryLarge) { - if (clipRes != splashClipAllOutside) { - // scale the mask - int scaledWidth = yMax - yMin; - int scaledHeight = xMax - xMin; - ImageMaskScaler scaler(src, srcData, w, h, - scaledWidth, scaledHeight, interpolate, antialias); - Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); - Guchar *ptr = scaledMask; - for (int y = 0; y < scaledHeight; ++y) { - scaler.nextLine(); - memcpy(ptr, scaler.data(), scaledWidth); - ptr += scaledWidth; - } + // scale the mask + int scaledWidth = yMax - yMin; + int scaledHeight = xMax - xMin; + ImageMaskScaler scaler(src, srcData, w, h, + scaledWidth, scaledHeight, interpolate, antialias); + Guchar *scaledMask = (Guchar *)gmallocn64(scaledHeight, scaledWidth); + Guchar *ptr = scaledMask; + for (int y = 0; y < scaledHeight; ++y) { + scaler.nextLine(); + memcpy(ptr, scaler.data(), scaledWidth); + ptr += scaledWidth; + } - // draw it - Guchar *tmpLine = (Guchar *)gmalloc(scaledHeight); - for (int y = 0; y < scaledWidth; ++y) { - if (vertFlip) { - ptr = scaledMask + (scaledWidth - 1 - y); - } else { - ptr = scaledMask + y; + // draw it + Guchar *tmpLine = (Guchar *)gmalloc(scaledHeight); + for (int y = 0; y < scaledWidth; ++y) { + if (vertFlip) { + ptr = scaledMask + (scaledWidth - 1 - y); + } else { + ptr = scaledMask + y; + } + if (horizFlip) { + ptr += (scaledHeight - 1) * (SplashBitmapRowSize)scaledWidth; + for (int x = 0; x < scaledHeight; ++x) { + tmpLine[x] = *ptr; + ptr -= scaledWidth; } - if (horizFlip) { - ptr += (scaledHeight - 1) * scaledWidth; - for (int x = 0; x < scaledHeight; ++x) { - tmpLine[x] = *ptr; - ptr -= scaledWidth; - } - } else { - for (int x = 0; x < scaledHeight; ++x) { - tmpLine[x] = *ptr; - ptr += scaledWidth; - } + } else { + for (int x = 0; x < scaledHeight; ++x) { + tmpLine[x] = *ptr; + ptr += scaledWidth; } - (this->*drawRowFunc)(&dd, tmpLine, xMin, yMin + y, scaledHeight); } - - gfree(tmpLine); - gfree(scaledMask); + (this->*drawRowFunc)(&dd, tmpLine, xMin, yMin + y, scaledHeight); } + gfree(tmpLine); + gfree(scaledMask); + //--- arbitrary transform } else { // estimate of size of scaled image @@ -6155,7 +6394,7 @@ SplashError Splash::fillImageMask(GString *imageTag, scaledHeight = 1; } GBool downscaling = gTrue; - if (veryLarge || (scaledWidth >= w && scaledHeight >= h)) { + if (scaledWidth >= w && scaledHeight >= h) { downscaling = gFalse; scaledWidth = w; scaledHeight = h; @@ -6189,7 +6428,7 @@ SplashError Splash::fillImageMask(GString *imageTag, // if downscaling: store the downscaled image mask // if upscaling: store the unscaled image mask - Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); + Guchar *scaledMask = (Guchar *)gmallocn64(scaledHeight, scaledWidth); if (downscaling) { ImageMaskScaler scaler(src, srcData, w, h, scaledWidth, scaledHeight, interpolate, antialias); @@ -6271,7 +6510,7 @@ void Splash::drawImageMaskArbitraryNoInterp( + (SplashCoord)y * invMat[3] + invMat[5]); if (xx >= 0 && xx < scaledWidth && yy >= 0 && yy < scaledHeight) { - Guchar *p = scaledMask + (yy * scaledWidth + xx); + Guchar *p = scaledMask + (yy * (SplashBitmapRowSize)scaledWidth + xx); Guchar *q = buf + (x - xMin); *q = *p; if (x < rowMin) { @@ -6349,10 +6588,10 @@ void Splash::drawImageMaskArbitraryInterp( if (y1 >= scaledHeight) { y1 = scaledHeight - 1; } - Guchar *p00 = scaledMask + (y0 * scaledWidth + x0); - Guchar *p10 = scaledMask + (y0 * scaledWidth + x1); - Guchar *p01 = scaledMask + (y1 * scaledWidth + x0); - Guchar *p11 = scaledMask + (y1 * scaledWidth + x1); + Guchar *p00 = scaledMask + (y0 * (SplashBitmapRowSize)scaledWidth + x0); + Guchar *p10 = scaledMask + (y0 * (SplashBitmapRowSize)scaledWidth + x1); + Guchar *p01 = scaledMask + (y1 * (SplashBitmapRowSize)scaledWidth + x0); + Guchar *p11 = scaledMask + (y1 * (SplashBitmapRowSize)scaledWidth + x1); Guchar *q = buf + (x - xMin); *q = (Guchar)(int)(sx0 * (sy0 * (int)*p00 + sy1 * (int)*p01) + sx1 * (sy0 * (int)*p10 + sy1 * (int)*p11)); @@ -6386,7 +6625,8 @@ void Splash::mirrorImageMaskRow(Guchar *maskIn, Guchar *maskOut, int width) { void Splash::drawImageMaskRowNoClip(SplashDrawImageMaskRowData *data, Guchar *maskData, int x, int y, int width) { - (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, maskData, NULL); + (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, + NULL, maskData, NULL); } void Splash::drawImageMaskRowClipNoAA(SplashDrawImageMaskRowData *data, @@ -6410,7 +6650,7 @@ void Splash::drawImageMaskRowClipNoAA(SplashDrawImageMaskRowData *data, state->clip->clipSpanBinary(scanBuf, y, x, x + width - 1, state->strokeAdjust); (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - scanBuf + x, NULL); + NULL, scanBuf + x, NULL); } void Splash::drawImageMaskRowClipAA(SplashDrawImageMaskRowData *data, @@ -6433,7 +6673,7 @@ void Splash::drawImageMaskRowClipAA(SplashDrawImageMaskRowData *data, memcpy(scanBuf + x, maskData, width); state->clip->clipSpan(scanBuf, y, x, x + width - 1, state->strokeAdjust); (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - scanBuf + x, NULL); + NULL, scanBuf + x, NULL); } struct SplashDrawImageRowData { @@ -6569,6 +6809,9 @@ SplashError Splash::drawImage(GString *imageTag, SplashClipResult clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1, state->strokeAdjust); + if (clipRes == splashClipAllOutside) { + return splashOk; + } // If the scaled image is much wider and/or taller than the clip // region, we use the arbitrary transform path, to avoid a // potentially very slow loop in the flips-only path (which scans @@ -6587,8 +6830,8 @@ SplashError Splash::drawImage(GString *imageTag, dd.srcAlpha = srcAlpha; pipeInit(&dd.pipe, NULL, (Guchar)splashRound(state->fillAlpha * 255), - clipRes != splashClipAllInside || srcAlpha, - gFalse); + gFalse, clipRes != splashClipAllInside || srcAlpha, + gFalse, gFalse, state->alphaIsShape); //--- choose the drawRow function SplashDrawImageRowFunc drawRowFunc; @@ -6616,136 +6859,133 @@ SplashError Splash::drawImage(GString *imageTag, //--- horizontal/vertical flips only if (flipsOnly && !veryLarge) { - if (clipRes != splashClipAllOutside) { - int scaledWidth = xMax - xMin; - int scaledHeight = yMax - yMin; - ImageScaler *scaler = getImageScaler(imageTag, src, srcData, - w, h, nComps, - scaledWidth, scaledHeight, - srcMode, srcAlpha, interpolate); - Guchar *tmpLine = NULL; - Guchar *tmpAlphaLine = NULL; - if (horizFlip) { - tmpLine = (Guchar *)gmallocn(scaledWidth, nComps); - if (srcAlpha) { - tmpAlphaLine = (Guchar *)gmalloc(scaledWidth); + int scaledWidth = xMax - xMin; + int scaledHeight = yMax - yMin; + ImageScaler *scaler = getImageScaler(imageTag, src, srcData, + w, h, nComps, + scaledWidth, scaledHeight, + srcMode, srcAlpha, interpolate); + Guchar *tmpLine = NULL; + Guchar *tmpAlphaLine = NULL; + if (horizFlip) { + tmpLine = (Guchar *)gmallocn(scaledWidth, nComps); + if (srcAlpha) { + tmpAlphaLine = (Guchar *)gmalloc(scaledWidth); + } + } + if (vertFlip) { + if (horizFlip) { // bottom-up, mirrored + for (int y = 0; y < scaledHeight; ++y) { + scaler->nextLine(); + mirrorImageRow(scaler->colorData(), scaler->alphaData(), + tmpLine, tmpAlphaLine, + scaledWidth, nComps, srcAlpha); + (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, + xMin, yMax - 1 - y, scaledWidth); + } + } else { // bottom-up + for (int y = 0; y < scaledHeight; ++y) { + scaler->nextLine(); + (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(), + xMin, yMax - 1 - y, scaledWidth); } } - if (vertFlip) { - if (horizFlip) { // bottom-up, mirrored - for (int y = 0; y < scaledHeight; ++y) { - scaler->nextLine(); - mirrorImageRow(scaler->colorData(), scaler->alphaData(), - tmpLine, tmpAlphaLine, - scaledWidth, nComps, srcAlpha); - (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, - xMin, yMax - 1 - y, scaledWidth); - } - } else { // bottom-up - for (int y = 0; y < scaledHeight; ++y) { - scaler->nextLine(); - (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(), - xMin, yMax - 1 - y, scaledWidth); - } + } else { + if (horizFlip) { // top-down, mirrored + for (int y = 0; y < scaledHeight; ++y) { + scaler->nextLine(); + mirrorImageRow(scaler->colorData(), scaler->alphaData(), + tmpLine, tmpAlphaLine, + scaledWidth, nComps, srcAlpha); + (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, + xMin, yMin + y, scaledWidth); } - } else { - if (horizFlip) { // top-down, mirrored - for (int y = 0; y < scaledHeight; ++y) { - scaler->nextLine(); - mirrorImageRow(scaler->colorData(), scaler->alphaData(), - tmpLine, tmpAlphaLine, - scaledWidth, nComps, srcAlpha); - (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, - xMin, yMin + y, scaledWidth); - } - } else { // top-down - for (int y = 0; y < scaledHeight; ++y) { - scaler->nextLine(); - (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(), - xMin, yMin + y, scaledWidth); - } + } else { // top-down + for (int y = 0; y < scaledHeight; ++y) { + scaler->nextLine(); + (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(), + xMin, yMin + y, scaledWidth); } } - gfree(tmpLine); - gfree(tmpAlphaLine); - delete scaler; } + gfree(tmpLine); + gfree(tmpAlphaLine); + delete scaler; //--- 90/270 rotation } else if (rot90Only && !veryLarge) { - if (clipRes != splashClipAllOutside) { - - // scale the image - int scaledWidth = yMax - yMin; - int scaledHeight = xMax - xMin; - Guchar *scaledColor, *scaledAlpha; - GBool freeScaledImage; - getScaledImage(imageTag, src, srcData, w, h, nComps, - scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate, - &scaledColor, &scaledAlpha, &freeScaledImage); - - // draw it - Guchar *tmpLine = (Guchar *)gmallocn(scaledHeight, nComps); - Guchar *tmpAlphaLine = NULL; - if (srcAlpha) { - tmpAlphaLine = (Guchar *)gmalloc(scaledHeight); + + // scale the image + int scaledWidth = yMax - yMin; + int scaledHeight = xMax - xMin; + Guchar *scaledColor, *scaledAlpha; + GBool freeScaledImage; + getScaledImage(imageTag, src, srcData, w, h, nComps, + scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate, + &scaledColor, &scaledAlpha, &freeScaledImage); + + // draw it + Guchar *tmpLine = (Guchar *)gmallocn(scaledHeight, nComps); + Guchar *tmpAlphaLine = NULL; + if (srcAlpha) { + tmpAlphaLine = (Guchar *)gmalloc(scaledHeight); + } + for (int y = 0; y < scaledWidth; ++y) { + Guchar *ptr = NULL; + Guchar *alphaPtr = NULL; + if (vertFlip) { + ptr = scaledColor + ((SplashBitmapRowSize)scaledWidth - 1 - y) * nComps; + if (srcAlpha) { + alphaPtr = scaledAlpha + (scaledWidth - 1 - y); + } + } else { + ptr = scaledColor + y * nComps; + if (srcAlpha) { + alphaPtr = scaledAlpha + y; + } } - for (int y = 0; y < scaledWidth; ++y) { - Guchar *ptr, *alphaPtr; - if (vertFlip) { - ptr = scaledColor + (scaledWidth - 1 - y) * nComps; - if (srcAlpha) { - alphaPtr = scaledAlpha + (scaledWidth - 1 - y); - } - } else { - ptr = scaledColor + y * nComps; - if (srcAlpha) { - alphaPtr = scaledAlpha + y; + if (horizFlip) { + ptr += (scaledHeight - 1) * (SplashBitmapRowSize)scaledWidth * nComps; + Guchar *q = tmpLine; + for (int x = 0; x < scaledHeight; ++x) { + for (int i = 0; i < nComps; ++i) { + *q++ = ptr[i]; } + ptr -= scaledWidth * nComps; } - if (horizFlip) { - ptr += (scaledHeight - 1) * scaledWidth * nComps; - Guchar *q = tmpLine; + if (srcAlpha) { + alphaPtr += (scaledHeight - 1) * (SplashBitmapRowSize)scaledWidth; + q = tmpAlphaLine; for (int x = 0; x < scaledHeight; ++x) { - for (int i = 0; i < nComps; ++i) { - *q++ = ptr[i]; - } - ptr -= scaledWidth * nComps; + *q++ = *alphaPtr; + alphaPtr -= scaledWidth; } - if (srcAlpha) { - alphaPtr += (scaledHeight - 1) * scaledWidth; - q = tmpAlphaLine; - for (int x = 0; x < scaledHeight; ++x) { - *q++ = *alphaPtr; - alphaPtr -= scaledWidth; - } + } + } else { + Guchar *q = tmpLine; + for (int x = 0; x < scaledHeight; ++x) { + for (int i = 0; i < nComps; ++i) { + *q++ = ptr[i]; } - } else { - Guchar *q = tmpLine; + ptr += scaledWidth * nComps; + } + if (srcAlpha) { + q = tmpAlphaLine; for (int x = 0; x < scaledHeight; ++x) { - for (int i = 0; i < nComps; ++i) { - *q++ = ptr[i]; - } - ptr += scaledWidth * nComps; - } - if (srcAlpha) { - q = tmpAlphaLine; - for (int x = 0; x < scaledHeight; ++x) { - *q++ = *alphaPtr; - alphaPtr += scaledWidth; - } + *q++ = *alphaPtr; + alphaPtr += scaledWidth; } } - (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, - xMin, yMin + y, scaledHeight); } + (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, + xMin, yMin + y, scaledHeight); + } - gfree(tmpLine); - gfree(tmpAlphaLine); - if (freeScaledImage) { - gfree(scaledColor); - gfree(scaledAlpha); - } + gfree(tmpLine); + gfree(tmpAlphaLine); + if (freeScaledImage) { + gfree(scaledColor); + gfree(scaledAlpha); } //--- arbitrary transform @@ -6761,7 +7001,7 @@ SplashError Splash::drawImage(GString *imageTag, if (scaledHeight < 1) { scaledHeight = 1; } - if (veryLarge || (scaledWidth >= w && scaledHeight >= h)) { + if (scaledWidth >= w && scaledHeight >= h) { scaledWidth = w; scaledHeight = h; } @@ -6851,9 +7091,9 @@ ImageScaler *Splash::getImageScaler(GString *imageTag, } else { lineSize = -1; } - imageCache->colorData = (Guchar *)gmallocn(scaledHeight, lineSize); + imageCache->colorData = (Guchar *)gmallocn64(scaledHeight, lineSize); if (srcAlpha) { - imageCache->alphaData = (Guchar *)gmallocn(scaledHeight, scaledWidth); + imageCache->alphaData = (Guchar *)gmallocn64(scaledHeight, scaledWidth); } return new SavingImageScaler(src, srcData, w, h, nComps, srcAlpha, @@ -6894,9 +7134,9 @@ void Splash::getScaledImage(GString *imageTag, } else { lineSize = -1; } - *scaledColor = (Guchar *)gmallocn(scaledHeight, lineSize); + *scaledColor = (Guchar *)gmallocn64(scaledHeight, lineSize); if (srcAlpha) { - *scaledAlpha = (Guchar *)gmallocn(scaledHeight, scaledWidth); + *scaledAlpha = (Guchar *)gmallocn64(scaledHeight, scaledWidth); } else { *scaledAlpha = NULL; } @@ -6938,9 +7178,9 @@ void Splash::getScaledImage(GString *imageTag, } else { lineSize = -1; } - imageCache->colorData = (Guchar *)gmallocn(scaledHeight, lineSize); + imageCache->colorData = (Guchar *)gmallocn64(scaledHeight, lineSize); if (srcAlpha) { - imageCache->alphaData = (Guchar *)gmallocn(scaledHeight, scaledWidth); + imageCache->alphaData = (Guchar *)gmallocn64(scaledHeight, scaledWidth); } if (scaledWidth == w && scaledHeight == h) { Guchar *colorPtr = imageCache->colorData; @@ -7021,13 +7261,15 @@ void Splash::drawImageArbitraryNoInterp(Guchar *scaledColor, + (SplashCoord)y * invMat[3] + invMat[5]); if (xx >= 0 && xx < scaledWidth && yy >= 0 && yy < scaledHeight) { - Guchar *p = scaledColor + (yy * scaledWidth + xx) * nComps; + Guchar *p = scaledColor + + (yy * (SplashBitmapRowSize)scaledWidth + xx) * nComps; Guchar *q = colorBuf + (x - xMin) * nComps; for (int i = 0; i < nComps; ++i) { *q++ = *p++; } if (srcAlpha) { - alphaBuf[x - xMin] = scaledAlpha[yy * scaledWidth + xx]; + alphaBuf[x - xMin] = + scaledAlpha[yy * (SplashBitmapRowSize)scaledWidth + xx]; } if (x < rowMin) { rowMin = x; @@ -7111,20 +7353,24 @@ void Splash::drawImageArbitraryInterp(Guchar *scaledColor, Guchar *scaledAlpha, if (y1 >= scaledHeight) { y1 = scaledHeight - 1; } - Guchar *p00 = scaledColor + (y0 * scaledWidth + x0) * nComps; - Guchar *p10 = scaledColor + (y0 * scaledWidth + x1) * nComps; - Guchar *p01 = scaledColor + (y1 * scaledWidth + x0) * nComps; - Guchar *p11 = scaledColor + (y1 * scaledWidth + x1) * nComps; + Guchar *p00 = scaledColor + + (y0 * (SplashBitmapRowSize)scaledWidth + x0) * nComps; + Guchar *p10 = scaledColor + + (y0 * (SplashBitmapRowSize)scaledWidth + x1) * nComps; + Guchar *p01 = scaledColor + + (y1 * (SplashBitmapRowSize)scaledWidth + x0) * nComps; + Guchar *p11 = scaledColor + + (y1 * (SplashBitmapRowSize)scaledWidth + x1) * nComps; Guchar *q = colorBuf + (x - xMin) * nComps; for (int i = 0; i < nComps; ++i) { *q++ = (Guchar)(int)(sx0 * (sy0 * (int)*p00++ + sy1 * (int)*p01++) + sx1 * (sy0 * (int)*p10++ + sy1 * (int)*p11++)); } if (srcAlpha) { - p00 = scaledAlpha + (y0 * scaledWidth + x0); - p10 = scaledAlpha + (y0 * scaledWidth + x1); - p01 = scaledAlpha + (y1 * scaledWidth + x0); - p11 = scaledAlpha + (y1 * scaledWidth + x1); + p00 = scaledAlpha + (y0 * (SplashBitmapRowSize)scaledWidth + x0); + p10 = scaledAlpha + (y0 * (SplashBitmapRowSize)scaledWidth + x1); + p01 = scaledAlpha + (y1 * (SplashBitmapRowSize)scaledWidth + x0); + p11 = scaledAlpha + (y1 * (SplashBitmapRowSize)scaledWidth + x1); q = alphaBuf + (x - xMin); *q = (Guchar)(int)(sx0 * (sy0 * (int)*p00 + sy1 * (int)*p01) + sx1 * (sy0 * (int)*p10 + sy1 * (int)*p11)); @@ -7176,14 +7422,15 @@ void Splash::mirrorImageRow(Guchar *colorIn, Guchar *alphaIn, void Splash::drawImageRowNoClipNoAlpha(SplashDrawImageRowData *data, Guchar *colorData, Guchar *alphaData, int x, int y, int width) { - (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, NULL, colorData); + (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, + NULL, NULL, colorData); } void Splash::drawImageRowNoClipAlpha(SplashDrawImageRowData *data, Guchar *colorData, Guchar *alphaData, int x, int y, int width) { (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - alphaData, colorData); + NULL, alphaData, colorData); } void Splash::drawImageRowClipNoAlphaNoAA(SplashDrawImageRowData *data, @@ -7208,7 +7455,7 @@ void Splash::drawImageRowClipNoAlphaNoAA(SplashDrawImageRowData *data, state->clip->clipSpanBinary(scanBuf, y, x, x + width - 1, state->strokeAdjust); (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - scanBuf + x, colorData); + NULL, scanBuf + x, colorData); } void Splash::drawImageRowClipNoAlphaAA(SplashDrawImageRowData *data, @@ -7232,7 +7479,7 @@ void Splash::drawImageRowClipNoAlphaAA(SplashDrawImageRowData *data, memset(scanBuf + x, 0xff, width); state->clip->clipSpan(scanBuf, y, x, x + width - 1, state->strokeAdjust); (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - scanBuf + x, colorData); + NULL, scanBuf + x, colorData); } void Splash::drawImageRowClipAlphaNoAA(SplashDrawImageRowData *data, @@ -7258,7 +7505,7 @@ void Splash::drawImageRowClipAlphaNoAA(SplashDrawImageRowData *data, state->clip->clipSpanBinary(scanBuf, y, x, x + width - 1, state->strokeAdjust); (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - scanBuf + x, colorData); + NULL, scanBuf + x, colorData); } void Splash::drawImageRowClipAlphaAA(SplashDrawImageRowData *data, @@ -7283,12 +7530,12 @@ void Splash::drawImageRowClipAlphaAA(SplashDrawImageRowData *data, memcpy(scanBuf + x, alphaData, width); state->clip->clipSpan(scanBuf, y, x, x + width - 1, state->strokeAdjust); (this->*data->pipe.run)(&data->pipe, x, x + width - 1, y, - scanBuf + x, colorData); + NULL, scanBuf + x, colorData); } -SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h, - GBool noClip, GBool nonIsolated) { +SplashError Splash::composite(SplashBitmap *src, SplashAlphaBitmap *srcShape, + int xSrc, int ySrc, int xDest, int yDest, + int w, int h, GBool noClip, GBool nonIsolated) { SplashPipe pipe; Guchar *mono1Ptr, *lineBuf, *linePtr; Guchar mono1Mask, b; @@ -7300,15 +7547,33 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, return splashErrModeMismatch; } + GBool usesShape = srcShape && shapeBitmap && src->alpha; + GBool usesAlpha = !noClip || src->alpha; pipeInit(&pipe, NULL, (Guchar)splashRound(state->fillAlpha * 255), - !noClip || src->alpha != NULL, nonIsolated); + usesShape, usesAlpha, nonIsolated); if (src->mode == splashModeMono1) { // in mono1 mode, pipeRun expects the source to be in mono8 // format, so we need to extract the source color values into // scanBuf, expanding them from mono1 to mono8 if (noClip) { - if (src->alpha) { + if (usesShape) { + for (y = 0; y < h; ++y) { + mono1Ptr = src->data + (ySrc + y) * src->rowSize + (xSrc >> 3); + mono1Mask = (Guchar)(0x80 >> (xSrc & 7)); + for (x = 0; x < w; ++x) { + scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00; + mono1Ptr += mono1Mask & 1; + mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1)); + } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + srcShape->alpha + + (ySrc + y) * srcShape->alphaRowSize + xSrc, + src->alpha + + (ySrc + y) * src->alphaRowSize + xSrc, + scanBuf); + } + } else if (usesAlpha) { for (y = 0; y < h; ++y) { mono1Ptr = src->data + (ySrc + y) * src->rowSize + (xSrc >> 3); mono1Mask = (Guchar)(0x80 >> (xSrc & 7)); @@ -7320,6 +7585,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, // this uses shape instead of alpha, which isn't technically // correct, but works out the same (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + NULL, src->alpha + (ySrc + y) * src->alphaRowSize + xSrc, scanBuf); @@ -7334,8 +7600,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1)); } (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, - NULL, - scanBuf); + NULL, NULL, scanBuf); } } } else { @@ -7356,7 +7621,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, y1 = t; } if (x0 < x1 && y0 < y1) { - if (src->alpha) { + if (usesShape) { for (y = y0; y < y1; ++y) { mono1Ptr = src->data + (ySrc + y - yDest) * src->rowSize @@ -7368,19 +7633,43 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1)); } memcpy(scanBuf2 + x0, - src->alpha + (ySrc + y - yDest) * src->alphaRowSize + + srcShape->alpha + + (ySrc + y - yDest) * srcShape->alphaRowSize + (xSrc + x0 - xDest), x1 - x0); if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1, state->strokeAdjust)) { continue; } - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same (this->*pipe.run)(&pipe, x0, x1 - 1, y, scanBuf2 + x0, + srcShape->alpha + + (ySrc + y - yDest) * srcShape->alphaRowSize + + (xSrc + x0 - xDest), scanBuf + x0); } + } else if (usesAlpha) { + for (y = y0; y < y1; ++y) { + mono1Ptr = src->data + + (ySrc + y - yDest) * src->rowSize + + ((xSrc + x0 - xDest) >> 3); + mono1Mask = (Guchar)(0x80 >> ((xSrc + x0 - xDest) & 7)); + for (x = x0; x < x1; ++x) { + scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00; + mono1Ptr += mono1Mask & 1; + mono1Mask = (Guchar)((mono1Mask << 7) | (mono1Mask >> 1)); + } + memcpy(scanBuf2 + x0, + src->alpha + (ySrc + y - yDest) * src->alphaRowSize + + (xSrc + x0 - xDest), + x1 - x0); + if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1, + state->strokeAdjust)) { + continue; + } + (this->*pipe.run)(&pipe, x0, x1 - 1, y, + NULL, scanBuf2 + x0, scanBuf + x0); + } } else { for (y = y0; y < y1; ++y) { mono1Ptr = src->data @@ -7398,8 +7687,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, continue; } (this->*pipe.run)(&pipe, x0, x1 - 1, y, - scanBuf2 + x0, - scanBuf + x0); + NULL, scanBuf2 + x0, scanBuf + x0); } } } @@ -7410,7 +7698,24 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, // so we need to swap bytes lineBuf = (Guchar *)gmallocn(w, 3); if (noClip) { - if (src->alpha) { + if (usesShape) { + for (y = 0; y < h; ++y) { + memcpy(lineBuf, + src->data + (ySrc + y) * src->rowSize + xSrc * 3, + w * 3); + for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) { + b = linePtr[0]; + linePtr[0] = linePtr[2]; + linePtr[2] = b; + } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + srcShape->alpha + + (ySrc + y) * srcShape->alphaRowSize + xSrc, + src->alpha + + (ySrc + y) * src->alphaRowSize + xSrc, + lineBuf); + } + } else if (usesAlpha) { for (y = 0; y < h; ++y) { memcpy(lineBuf, src->data + (ySrc + y) * src->rowSize + xSrc * 3, @@ -7420,9 +7725,8 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, linePtr[0] = linePtr[2]; linePtr[2] = b; } - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + NULL, src->alpha + (ySrc + y) * src->alphaRowSize + xSrc, lineBuf); @@ -7438,7 +7742,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, linePtr[2] = b; } (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, - NULL, lineBuf); + NULL, NULL, lineBuf); } } } else { @@ -7459,7 +7763,34 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, y1 = t; } if (x0 < x1 && y0 < y1) { - if (src->alpha) { + if (usesShape) { + for (y = y0; y < y1; ++y) { + memcpy(scanBuf + x0, + srcShape->alpha + + (ySrc + y - yDest) * srcShape->alphaRowSize + + (xSrc + x0 - xDest), + x1 - x0); + state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust); + memcpy(lineBuf, + src->data + + (ySrc + y - yDest) * src->rowSize + + (xSrc + x0 - xDest) * 3, + (x1 - x0) * 3); + for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) { + b = linePtr[0]; + linePtr[0] = linePtr[2]; + linePtr[2] = b; + } + // this uses shape instead of alpha, which isn't technically + // correct, but works out the same + (this->*pipe.run)(&pipe, x0, x1 - 1, y, + scanBuf + x0, + src->alpha + + (ySrc + y - yDest) * src->alphaRowSize + + (xSrc + x0 - xDest), + lineBuf); + } + } else if (usesAlpha) { for (y = y0; y < y1; ++y) { memcpy(scanBuf + x0, src->alpha + (ySrc + y - yDest) * src->alphaRowSize + @@ -7479,7 +7810,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, // this uses shape instead of alpha, which isn't technically // correct, but works out the same (this->*pipe.run)(&pipe, x0, x1 - 1, y, - scanBuf + x0, lineBuf); + NULL, scanBuf + x0, lineBuf); } } else { for (y = y0; y < y1; ++y) { @@ -7496,6 +7827,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, linePtr[2] = b; } (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y, + NULL, scanBuf + x0, src->data + (ySrc + y - yDest) * src->rowSize + @@ -7508,20 +7840,29 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, } else { // src->mode not mono1 or BGR8 if (noClip) { - if (src->alpha) { + if (usesShape) { for (y = 0; y < h; ++y) { - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + srcShape->alpha + + (ySrc + y) * srcShape->alphaRowSize + xSrc, src->alpha + (ySrc + y) * src->alphaRowSize + xSrc, src->data + (ySrc + y) * src->rowSize + - xSrc * bitmapComps); + xSrc * bitmapComps); } - } else { + } else if (usesAlpha) { for (y = 0; y < h; ++y) { (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, NULL, + src->alpha + + (ySrc + y) * src->alphaRowSize + xSrc, + src->data + (ySrc + y) * src->rowSize + + xSrc * bitmapComps); + } + } else { + for (y = 0; y < h; ++y) { + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + NULL, NULL, src->data + (ySrc + y) * src->rowSize + xSrc * bitmapComps); } @@ -7544,16 +7885,32 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, y1 = t; } if (x0 < x1 && y0 < y1) { - if (src->alpha) { + if (usesShape) { + for (y = y0; y < y1; ++y) { + memcpy(scanBuf + x0, + srcShape->alpha + + (ySrc + y - yDest) * srcShape->alphaRowSize + + (xSrc + x0 - xDest), + x1 - x0); + state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust); + (this->*pipe.run)(&pipe, x0, x1 - 1, y, + scanBuf + x0, + src->alpha + + (ySrc + y - yDest) * src->alphaRowSize + + (xSrc + x0 - xDest), + src->data + + (ySrc + y - yDest) * src->rowSize + + (xSrc + x0 - xDest) * bitmapComps); + } + } else if (usesAlpha) { for (y = y0; y < y1; ++y) { memcpy(scanBuf + x0, src->alpha + (ySrc + y - yDest) * src->alphaRowSize + (xSrc + x0 - xDest), x1 - x0); state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust); - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same (this->*pipe.run)(&pipe, x0, x1 - 1, y, + NULL, scanBuf + x0, src->data + (ySrc + y - yDest) * src->rowSize + @@ -7564,6 +7921,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, memset(scanBuf + x0, 0xff, x1 - x0); state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust); (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y, + NULL, scanBuf + x0, src->data + (ySrc + y - yDest) * src->rowSize + @@ -7578,6 +7936,7 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, } SplashError Splash::compositeWithOverprint(SplashBitmap *src, + SplashAlphaBitmap *srcShape, Guint *srcOverprintMaskBitmap, int xSrc, int ySrc, int xDest, int yDest, int w, int h, @@ -7591,27 +7950,39 @@ SplashError Splash::compositeWithOverprint(SplashBitmap *src, return splashErrModeMismatch; } + GBool usesShape = srcShape && shapeBitmap && src->alpha; + GBool usesAlpha = !noClip || src->alpha; pipeInit(&pipe, NULL, (Guchar)splashRound(state->fillAlpha * 255), - !noClip || src->alpha != NULL, nonIsolated, gTrue); + usesShape, usesAlpha, nonIsolated, gTrue); if (noClip) { - if (src->alpha) { + if (usesShape) { for (y = 0; y < h; ++y) { pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + y * w + xSrc; - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + srcShape->alpha + + (ySrc + y) * srcShape->alphaRowSize + xSrc, src->alpha + (ySrc + y) * src->alphaRowSize + xSrc, src->data + (ySrc + y) * src->rowSize + xSrc * bitmapComps); } - } else { + } else if (usesAlpha) { for (y = 0; y < h; ++y) { pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + y * w + xSrc; (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, NULL, + src->alpha + + (ySrc + y) * src->alphaRowSize + xSrc, + src->data + (ySrc + y) * src->rowSize + + xSrc * bitmapComps); + } + } else { + for (y = 0; y < h; ++y) { + pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + y * w + xSrc; + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + NULL, NULL, src->data + (ySrc + y) * src->rowSize + xSrc * bitmapComps); } @@ -7634,7 +8005,27 @@ SplashError Splash::compositeWithOverprint(SplashBitmap *src, y1 = t; } if (x0 < x1 && y0 < y1) { - if (src->alpha) { + if (usesShape) { + for (y = y0; y < y1; ++y) { + memcpy(scanBuf + x0, + srcShape->alpha + + (ySrc + y - yDest) * srcShape->alphaRowSize + + (xSrc + x0 - xDest), + x1 - x0); + state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust); + pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + + (ySrc + y - yDest) * w + + (xSrc + x0 - xDest); + (this->*pipe.run)(&pipe, x0, x1 - 1, y, + scanBuf + x0, + src->alpha + + (ySrc + y - yDest) * src->alphaRowSize + + (xSrc + x0 - xDest), + src->data + + (ySrc + y - yDest) * src->rowSize + + (xSrc + x0 - xDest) * bitmapComps); + } + } else if (usesAlpha) { for (y = y0; y < y1; ++y) { memcpy(scanBuf + x0, src->alpha + (ySrc + y - yDest) * src->alphaRowSize + @@ -7644,9 +8035,8 @@ SplashError Splash::compositeWithOverprint(SplashBitmap *src, pipe.srcOverprintMaskPtr = srcOverprintMaskBitmap + (ySrc + y - yDest) * w + (xSrc + x0 - xDest); - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same (this->*pipe.run)(&pipe, x0, x1 - 1, y, + NULL, scanBuf + x0, src->data + (ySrc + y - yDest) * src->rowSize + @@ -7660,6 +8050,7 @@ SplashError Splash::compositeWithOverprint(SplashBitmap *src, + (ySrc + y - yDest) * w + (xSrc + x0 - xDest); (this->*pipe.run)(&pipe, x0, x1 - 1, y, + NULL, scanBuf + x0, src->data + (ySrc + y - yDest) * src->rowSize + @@ -7786,156 +8177,6 @@ void Splash::compositeBackground(SplashColorPtr color) { memset(bitmap->alpha, 255, bitmap->alphaRowSize * bitmap->height); } -SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h) { - SplashColorPtr p, q; - Guchar mask, srcMask; - int x, y; - - if (src->mode != bitmap->mode) { - return splashErrModeMismatch; - } - - switch (bitmap->mode) { - case splashModeMono1: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + (xDest >> 3)]; - mask = (Guchar)(0x80 >> (xDest & 7)); - q = &src->data[(ySrc + y) * src->rowSize + (xSrc >> 3)]; - srcMask = (Guchar)(0x80 >> (xSrc & 7)); - for (x = 0; x < w; ++x) { - if (*q & srcMask) { - *p |= mask; - } else { - *p &= (Guchar)~mask; - } - if (!(mask = (Guchar)(mask >> 1))) { - mask = 0x80; - ++p; - } - if (!(srcMask = (Guchar)(srcMask >> 1))) { - srcMask = 0x80; - ++q; - } - } - } - break; - case splashModeMono8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + xDest]; - q = &src->data[(ySrc + y) * src->rowSize + xSrc]; - memcpy(p, q, w); - } - break; - case splashModeRGB8: - case splashModeBGR8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + 3 * xDest]; - q = &src->data[(ySrc + y) * src->rowSize + 3 * xSrc]; - memcpy(p, q, 3 * w); - } - break; -#if SPLASH_CMYK - case splashModeCMYK8: - for (y = 0; y < h; ++y) { - p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest]; - q = &src->data[(ySrc + y) * src->rowSize + 4 * xSrc]; - memcpy(p, q, 4 * w); - } - break; -#endif - } - - if (bitmap->alpha) { - for (y = 0; y < h; ++y) { - q = &bitmap->alpha[(yDest + y) * bitmap->alphaRowSize + xDest]; - memset(q, 0, w); - } - } - - return splashOk; -} - -SplashError Splash::blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc, - int xDest, int yDest, int w, int h) { - SplashColorPtr p, q; - Guchar *alpha0Ptr; - Guchar alpha0, aSrc, mask, srcMask; - int x, y; - - if (bitmap->mode != dest->mode || - !bitmap->alpha || - !dest->alpha || - !groupBackBitmap) { - return splashErrModeMismatch; - } - - switch (bitmap->mode) { - case splashModeMono1: - for (y = 0; y < h; ++y) { - p = &dest->data[(yDest + y) * dest->rowSize + (xDest >> 3)]; - mask = (Guchar)(0x80 >> (xDest & 7)); - q = &bitmap->data[(ySrc + y) * bitmap->rowSize + (xSrc >> 3)]; - srcMask = (Guchar)(0x80 >> (xSrc & 7)); - for (x = 0; x < w; ++x) { - if (*q & srcMask) { - *p |= mask; - } else { - *p &= (Guchar)~mask; - } - if (!(mask = (Guchar)(mask >> 1))) { - mask = 0x80; - ++p; - } - if (!(srcMask = (Guchar)(srcMask >> 1))) { - srcMask = 0x80; - ++q; - } - } - } - break; - case splashModeMono8: - for (y = 0; y < h; ++y) { - p = &dest->data[(yDest + y) * dest->rowSize + xDest]; - q = &bitmap->data[(ySrc + y) * bitmap->rowSize + xSrc]; - memcpy(p, q, w); - } - break; - case splashModeRGB8: - case splashModeBGR8: - for (y = 0; y < h; ++y) { - p = &dest->data[(yDest + y) * dest->rowSize + 3 * xDest]; - q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 3 * xSrc]; - memcpy(p, q, 3 * w); - } - break; -#if SPLASH_CMYK - case splashModeCMYK8: - for (y = 0; y < h; ++y) { - p = &dest->data[(yDest + y) * dest->rowSize + 4 * xDest]; - q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 4 * xSrc]; - memcpy(p, q, 4 * w); - } - break; -#endif - } - - for (y = 0; y < h; ++y) { - p = &dest->alpha[(yDest + y) * dest->alphaRowSize + xDest]; - q = &bitmap->alpha[(ySrc + y) * bitmap->alphaRowSize + xSrc]; - alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + ySrc + y) - * groupBackBitmap->alphaRowSize + - (groupBackX + xSrc)]; - for (x = 0; x < w; ++x) { - alpha0 = *alpha0Ptr++; - aSrc = *q++; - *p++ = (Guchar)(alpha0 + aSrc - div255(alpha0 * aSrc)); - } - } - - return splashOk; -} - SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w, int lineCap, int lineJoin, GBool flatten) { diff --git a/src/xpdf-4.04/splash/Splash.h b/src/xpdf-4.04/splash/Splash.h index 9622b07..dcca49d 100644 --- a/src/xpdf-4.04/splash/Splash.h +++ b/src/xpdf-4.04/splash/Splash.h @@ -11,16 +11,13 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" #include "SplashClip.h" class GString; class Splash; class SplashBitmap; +class SplashAlphaBitmap; struct SplashGlyphBitmap; class SplashState; class SplashPattern; @@ -174,6 +171,7 @@ class Splash { void setLineDash(SplashCoord *lineDash, int lineDashLength, SplashCoord lineDashPhase); void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust); + void setAlphaIsShape(GBool alphaIsShape); // NB: uses transformed coordinates. void clipResetToRect(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1); @@ -183,9 +181,10 @@ class Splash { // NB: uses untransformed coordinates. SplashError clipToPath(SplashPath *path, GBool eo); void setSoftMask(SplashBitmap *softMask, GBool deleteBitmap = gTrue); - void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, - int groupBackXA, int groupBackYA, - SplashGroupDestInitMode groupDestInitModeA, + void setInTransparencyGroup(Splash *parentA, + int parentOffsetXA, int parentOffsetYA, + SplashAlphaBitmap *alpha0BitmapA, + SplashAlphaBitmap *shapeBitmapA, GBool nonIsolated, GBool knockout); void forceDeferredInit(int y, int h); GBool checkTransparentRect(int x, int y, int w, int h); @@ -210,7 +209,8 @@ class Splash { SplashError fill(SplashPath *path, GBool eo); // Draw a character, using the current fill pattern. - SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font); + SplashError fillChar(SplashCoord x, SplashCoord y, + Guint c, SplashFont *font); // Draw a glyph, using the current fill pattern. This function does // not free any data, i.e., it ignores glyph->freeData. @@ -261,14 +261,15 @@ class Splash { // Composite a rectangular region from onto this Splash // object. - SplashError composite(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h, - GBool noClip, GBool nonIsolated); + SplashError composite(SplashBitmap *src, SplashAlphaBitmap *srcShape, + int xSrc, int ySrc, int xDest, int yDest, + int w, int h, GBool noClip, GBool nonIsolated); // Composite a rectangular region from onto this Splash // object, using as the overprint mask per // pixel. This is only supported for CMYK and DeviceN bitmaps. SplashError compositeWithOverprint(SplashBitmap *src, + SplashAlphaBitmap *srcShape, Guint *srcOverprintMaskBitmap, int xSrc, int ySrc, int xDest, int yDest, int w, int h, @@ -278,18 +279,6 @@ class Splash { // background alpha is assumed to be 1. void compositeBackground(SplashColorPtr color); - // Copy a rectangular region from onto the bitmap belonging to - // this Splash object. The destination alpha values are all set to - // zero. - SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); - - // Copy a rectangular region from the bitmap belonging to this - // Splash object to . The alpha values are corrected for a - // non-isolated group. - SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); - //----- misc // Construct a path for a stroke, given the path to be stroked and @@ -333,78 +322,103 @@ class Splash { SplashImageCache *getImageCache() { return imageCache; } -#if 1 //~tmp: turn off anti-aliasing temporarily - void setInShading(GBool sh) { inShading = sh; } -#endif - private: void pipeInit(SplashPipe *pipe, SplashPattern *pattern, - Guchar aInput, GBool usesShape, - GBool nonIsolatedGroup, GBool usesSrcOverprint = gFalse); + Guchar aInput, GBool usesShape, GBool usesAlpha, + GBool nonIsolatedGroup, GBool usesSrcOverprint = gFalse, + GBool alphaIsShape = gFalse); void pipeRun(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #if SPLASH_CMYK void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #endif void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #if SPLASH_CMYK void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #endif void pipeRunShapeNoAlphaMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #if SPLASH_CMYK void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #endif void pipeRunSoftMaskMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunSoftMaskRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunSoftMaskBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #if SPLASH_CMYK void pipeRunSoftMaskCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #endif void pipeRunNonIsoMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunNonIsoRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); void pipeRunNonIsoBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #if SPLASH_CMYK void pipeRunNonIsoCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + Guchar *shapePtr, Guchar *alphaPtr, + SplashColorPtr cSrcPtr); #endif - void useDestRow(int y); - void copyGroupBackdropRow(int y); + void useBitmapRow(int y); + void copyParentRowColor(int y); + void zeroRowColor(int y); + void zeroRowAlpha(int y); + void computeAlpha0Row(int y); void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, SplashCoord *xo, SplashCoord *yo); void updateModX(int x); @@ -425,7 +439,7 @@ class Splash { SplashError fillWithPattern(SplashPath *path, GBool eo, SplashPattern *pattern, SplashCoord alpha); SplashPath *tweakFillPath(SplashPath *path); - GBool pathAllOutside(SplashPath *path); + GBool pathAllOutside(SplashPath *path, GBool stroke); SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); void getImageBounds(SplashCoord xyMin, SplashCoord xyMax, int *xyMinI, int *xyMaxI); @@ -518,17 +532,19 @@ class Splash { SplashState *state; Guchar *scanBuf; Guchar *scanBuf2; - SplashBitmap // for transparency groups, this is the bitmap - *groupBackBitmap; // containing the alpha0/color0 values - int groupBackX, groupBackY; // offset within groupBackBitmap - SplashGroupDestInitMode groupDestInitMode; - int groupDestInitYMin, groupDestInitYMax; + Splash *parent; // transparency group parent + int parentOffsetX, // offset within parent + parentOffsetY; + GBool deferredInit; // true if bitmap initialization is deferred + int deferredInitYMin, // range of rows that have been initialized + deferredInitYMax; + SplashAlphaBitmap *alpha0Bitmap; + SplashAlphaBitmap *shapeBitmap; Guint *overprintMaskBitmap; SplashCoord minLineWidth; int modXMin, modYMin, modXMax, modYMax; SplashClipResult opClipRes; GBool vectorAntialias; - GBool inShading; GBool debugMode; SplashImageCache *imageCache; diff --git a/src/xpdf-4.04/splash/SplashBitmap.cc b/src/xpdf-4.04/splash/SplashBitmap.cc index db341d7..9ddce06 100644 --- a/src/xpdf-4.04/splash/SplashBitmap.cc +++ b/src/xpdf-4.04/splash/SplashBitmap.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -21,19 +17,96 @@ #include "SplashErrorCodes.h" #include "SplashBitmap.h" +//------------------------------------------------------------------------ +// SplashBitmapMemCache +//------------------------------------------------------------------------ + +#define splashBitmapMemCacheThreshold 4000000 + +SplashBitmapMemCache::SplashBitmapMemCache() { + for (int i = 0; i < splashBitmapMemCacheSize; ++i) { + cache[i].data = NULL; + cache[i].height = 0; + cache[i].rowSize = 0; + } +} + +SplashBitmapMemCache::~SplashBitmapMemCache() { + for (int i = 0; i < splashBitmapMemCacheSize; ++i) { + if (cache[i].data) { + gfree(cache[i].data); + cache[i].data = NULL; + cache[i].height = 0; + cache[i].rowSize = 0; + } + } +} + +void *SplashBitmapMemCache::alloc(int height, SplashBitmapRowSize rowSize) { + // if the block is small, just allocate it + if (rowSize < splashBitmapMemCacheThreshold / height) { + return gmallocn64(height, rowSize); + } + + // if a match is found in the cache, return it + for (int i = splashBitmapMemCacheSize - 1; i >= 0; --i) { + if (cache[i].data && + cache[i].height == height && + cache[i].rowSize == rowSize) { + void *data = cache[i].data; + for (int j = i; j < splashBitmapMemCacheSize - 1; ++j) { + cache[j] = cache[j + 1]; + } + cache[splashBitmapMemCacheSize - 1].data = NULL; + cache[splashBitmapMemCacheSize - 1].height = 0; + cache[splashBitmapMemCacheSize - 1].rowSize = 0; + return data; + } + } + + // if no match was found, clear the cache and allcoate the block + for (int i = 0; i < splashBitmapMemCacheSize; ++i) { + if (cache[i].data) { + gfree(cache[i].data); + cache[i].data = NULL; + cache[i].height = 0; + cache[i].rowSize = 0; + } + } + return gmallocn64(height, rowSize); +} + +void SplashBitmapMemCache::free(void *data, int height, + SplashBitmapRowSize rowSize) { + if (rowSize < splashBitmapMemCacheThreshold / height) { + gfree(data); + return; + } + if (cache[0].data) { + gfree(cache[0].data); + } + for (int i = 0; i < splashBitmapMemCacheSize - 1; ++i) { + cache[i] = cache[i + 1]; + } + cache[splashBitmapMemCacheSize - 1].data = data; + cache[splashBitmapMemCacheSize - 1].height = height; + cache[splashBitmapMemCacheSize - 1].rowSize = rowSize; +} + //------------------------------------------------------------------------ // SplashBitmap //------------------------------------------------------------------------ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad, SplashColorMode modeA, GBool alphaA, - GBool topDown, SplashBitmap *parentA) { + GBool topDown, SplashBitmapMemCache *cacheA) { // NB: this code checks that rowSize fits in a signed 32-bit // integer, because some code (outside this class) makes that // assumption width = widthA; height = heightA; mode = modeA; + rowSize = 0; // make gcc happy switch (mode) { case splashModeMono1: if (width <= 0) { @@ -71,25 +144,11 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad, alphaA ? "with alpha" : "without alpha", height * rowSize + (alphaA ? height * width : 0)); - parent = parentA; - oldData = NULL; - oldAlpha = NULL; - oldRowSize = 0; - oldAlphaRowSize = 0; - oldHeight = 0; - if (parent && parent->oldData && - parent->oldRowSize == rowSize && - parent->oldHeight == height) { - data = parent->oldData; - parent->oldData = NULL; - traceMessage("reusing bitmap memory"); + cache = cacheA; + if (cache) { + data = (SplashColorPtr)cache->alloc(height, rowSize); } else { data = (SplashColorPtr)gmallocn64(height, rowSize); - traceMessage("not reusing bitmap memory" - " (parent=%p parent->oldData=%p same-size=%d)", - parent, parent ? parent->oldData : NULL, - parent ? (parent->oldRowSize == rowSize && - parent->oldHeight == height) : 0); } if (!topDown) { data += (height - 1) * rowSize; @@ -97,11 +156,8 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad, } if (alphaA) { alphaRowSize = width; - if (parent && parent->oldAlpha && - parent->oldAlphaRowSize == alphaRowSize && - parent->oldHeight == height) { - alpha = parent->oldAlpha; - parent->oldAlpha = NULL; + if (cache) { + alpha = (Guchar *)cache->alloc(height, alphaRowSize); } else { alpha = (Guchar *)gmallocn64(height, alphaRowSize); } @@ -117,20 +173,15 @@ SplashBitmap::~SplashBitmap() { rowSize = -rowSize; data -= (height - 1) * rowSize; } - if (parent && rowSize > 4000000 / height) { - gfree(parent->oldData); - gfree(parent->oldAlpha); - parent->oldData = data; - parent->oldAlpha = alpha; - parent->oldRowSize = rowSize; - parent->oldAlphaRowSize = alphaRowSize; - parent->oldHeight = height; + if (cache) { + cache->free(data, height, rowSize); + if (alpha) { + cache->free(alpha, height, alphaRowSize); + } } else { gfree(data); gfree(alpha); } - gfree(oldData); - gfree(oldAlpha); } SplashError SplashBitmap::writePNMFile(char *fileName) { @@ -286,3 +337,37 @@ SplashColorPtr SplashBitmap::takeData() { return data2; } +void SplashBitmap::doNotCache() { + cache = NULL; +} + + +//------------------------------------------------------------------------ +// SplashAlphaBitmap +//------------------------------------------------------------------------ + +SplashAlphaBitmap::SplashAlphaBitmap(int widthA, int heightA, + SplashBitmapMemCache *cacheA) { + width = widthA; + height = heightA; + alphaRowSize = width; + + traceAlloc(this, "alloc alpha bitmap: %d x %d -> %lld bytes", + width, height, height * alphaRowSize); + + cache = cacheA; + if (cache) { + alpha = (Guchar *)cache->alloc(height, alphaRowSize); + } else { + alpha = (Guchar *)gmallocn64(height, alphaRowSize); + } +} + +SplashAlphaBitmap::~SplashAlphaBitmap() { + traceFree(this, "free alpha bitmap"); + if (cache) { + cache->free(alpha, height, alphaRowSize); + } else { + gfree(alpha); + } +} diff --git a/src/xpdf-4.04/splash/SplashBitmap.h b/src/xpdf-4.04/splash/SplashBitmap.h index 54975a3..22c4ed2 100644 --- a/src/xpdf-4.04/splash/SplashBitmap.h +++ b/src/xpdf-4.04/splash/SplashBitmap.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include // older compilers won't define SIZE_MAX in stdint.h without this @@ -35,6 +31,39 @@ # define SplashBitmapRowSizeMax LLONG_MAX #endif +//------------------------------------------------------------------------ +// SplashBitmapMemCache +//------------------------------------------------------------------------ + +#define splashBitmapMemCacheSize 4 + +struct SplashBitmapMemCacheEntry { + void *data; + int height; + SplashBitmapRowSize rowSize; +}; + +// This holds onto a small number of freed bitmaps so they can be +// reused, avoiding system overhead for (re)allocating large chunks of +// memory. It's not thread-safe, so it needs to be owned by a single +// thread. +class SplashBitmapMemCache { +public: + + SplashBitmapMemCache(); + ~SplashBitmapMemCache(); + +private: + + void *alloc(int height, SplashBitmapRowSize rowSize); + void free(void *data, int height, SplashBitmapRowSize rowSize); + + SplashBitmapMemCacheEntry cache[splashBitmapMemCacheSize]; + + friend class SplashBitmap; + friend class SplashAlphaBitmap; +}; + //------------------------------------------------------------------------ // SplashBitmap //------------------------------------------------------------------------ @@ -48,7 +77,7 @@ class SplashBitmap { // upside-down, i.e., with the last row first in memory. SplashBitmap(int widthA, int heightA, int rowPad, SplashColorMode modeA, GBool alphaA, - GBool topDown, SplashBitmap *parentA); + GBool topDown, SplashBitmapMemCache *cacheA); ~SplashBitmap(); @@ -72,6 +101,8 @@ class SplashBitmap { // destructor. SplashColorPtr takeData(); + void doNotCache(); + private: int width, height; // size of bitmap @@ -83,16 +114,38 @@ class SplashBitmap { Guchar *alpha; // pointer to row zero of the alpha data // (always top-down) - // save the last-allocated (large) bitmap data and reuse if possible - SplashBitmap *parent; - SplashColorPtr oldData; - Guchar *oldAlpha; - SplashBitmapRowSize oldRowSize; - size_t oldAlphaRowSize; - int oldHeight; + SplashBitmapMemCache *cache; friend class Splash; }; +//------------------------------------------------------------------------ +// SplashAlphaBitmap +//------------------------------------------------------------------------ + +class SplashAlphaBitmap { +public: + + // Create a new alpha bitmap with x pixels. + SplashAlphaBitmap(int widthA, int heightA, SplashBitmapMemCache *cacheA); + + ~SplashAlphaBitmap(); + + int getWidth() { return width; } + int getHeight() { return height; } + size_t getAlphaRowSize() { return alphaRowSize; } + Guchar *getAlphaPtr() { return alpha; } + +private: + + int width, height; // size of bitmap + size_t alphaRowSize; // size of one row, in bytes + Guchar *alpha; // pointer to the alpha data + + SplashBitmapMemCache *cache; + + friend class Splash; +}; + #endif diff --git a/src/xpdf-4.04/splash/SplashClip.cc b/src/xpdf-4.04/splash/SplashClip.cc index bf7b802..4b491aa 100644 --- a/src/xpdf-4.04/splash/SplashClip.cc +++ b/src/xpdf-4.04/splash/SplashClip.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -210,7 +206,7 @@ SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix, xPath = new SplashXPath(path, matrix, flatness, gTrue, enablePathSimplification, - strokeAdjust); + strokeAdjust, NULL); // check for an empty path if (xPath->length == 0) { diff --git a/src/xpdf-4.04/splash/SplashClip.h b/src/xpdf-4.04/splash/SplashClip.h index fb86ed8..093c65c 100644 --- a/src/xpdf-4.04/splash/SplashClip.h +++ b/src/xpdf-4.04/splash/SplashClip.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" #include "SplashMath.h" @@ -100,6 +96,9 @@ class SplashClip { // Get the number of arbitrary paths used by the clip region. int getNumPaths(); + // Return true if the clip path is a simple rectangle. + GBool getIsSimple() { return isSimple; } + private: SplashClip(SplashClip *clip); @@ -110,10 +109,11 @@ class SplashClip { hardXMax, hardYMax; // [hardXMin, hardXMax), [hardYMin, hardYMax) SplashCoord xMin, yMin, // current clip bounding rectangle - xMax, yMax; // (these coordinates may be adjusted if - // stroke adjustment is enabled) + xMax, yMax; - int xMinI, yMinI, xMaxI, yMaxI; + int xMinI, yMinI, // integer clip bounding rectangle + xMaxI, yMaxI; // (these coordinates are adjusted if + // stroke adjustment is enabled) GBool intBoundsValid; // true if xMinI, etc. are valid GBool intBoundsStrokeAdjust; // value of strokeAdjust used to compute // xMinI, etc. diff --git a/src/xpdf-4.04/splash/SplashFTFont.cc b/src/xpdf-4.04/splash/SplashFTFont.cc index 9148144..e40f057 100644 --- a/src/xpdf-4.04/splash/SplashFTFont.cc +++ b/src/xpdf-4.04/splash/SplashFTFont.cc @@ -10,10 +10,6 @@ #if HAVE_FREETYPE_H -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include FT_OUTLINE_H #include FT_SIZES_H @@ -223,12 +219,12 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA, SplashFTFont::~SplashFTFont() { } -GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac, +GBool SplashFTFont::getGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap) { return SplashFont::getGlyph(c, xFrac, 0, bitmap); } -GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac, +GBool SplashFTFont::makeGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap) { SplashFTFontFile *ff; FT_Vector offset; @@ -247,7 +243,7 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac, FT_Set_Transform(ff->face, &matrix, &offset); slot = ff->face->glyph; - if (ff->codeToGID && c < ff->codeToGIDLen) { + if (ff->codeToGID && c < (Guint)ff->codeToGIDLen) { gid = ff->codeToGID[c]; } else { gid = c; @@ -325,7 +321,7 @@ struct SplashFTFontPath { GBool needClose; }; -SplashPath *SplashFTFont::getGlyphPath(int c) { +SplashPath *SplashFTFont::getGlyphPath(Guint c) { static FT_Outline_Funcs outlineFuncs = { #if FREETYPE_MINOR <= 1 (int (*)(FT_Vector *, void *))&glyphPathMoveTo, @@ -350,7 +346,7 @@ SplashPath *SplashFTFont::getGlyphPath(int c) { ff->face->size = sizeObj; FT_Set_Transform(ff->face, &textMatrix, NULL); slot = ff->face->glyph; - if (ff->codeToGID && c < ff->codeToGIDLen) { + if (ff->codeToGID && c < (Guint)ff->codeToGIDLen) { gid = ff->codeToGID[c]; } else { gid = c; diff --git a/src/xpdf-4.04/splash/SplashFTFont.h b/src/xpdf-4.04/splash/SplashFTFont.h index ac08b00..d7ad39a 100644 --- a/src/xpdf-4.04/splash/SplashFTFont.h +++ b/src/xpdf-4.04/splash/SplashFTFont.h @@ -13,10 +13,6 @@ #if HAVE_FREETYPE_H -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include FT_FREETYPE_H #include "SplashFont.h" @@ -36,16 +32,16 @@ class SplashFTFont: public SplashFont { virtual ~SplashFTFont(); // Munge xFrac and yFrac before calling SplashFont::getGlyph. - virtual GBool getGlyph(int c, int xFrac, int yFrac, + virtual GBool getGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap); // Rasterize a glyph. The and values are the same // as described for getGlyph. - virtual GBool makeGlyph(int c, int xFrac, int yFrac, + virtual GBool makeGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap); // Return the path for a glyph. - virtual SplashPath *getGlyphPath(int c); + virtual SplashPath *getGlyphPath(Guint c); private: diff --git a/src/xpdf-4.04/splash/SplashFTFontEngine.cc b/src/xpdf-4.04/splash/SplashFTFontEngine.cc index 3393954..4b99586 100644 --- a/src/xpdf-4.04/splash/SplashFTFontEngine.cc +++ b/src/xpdf-4.04/splash/SplashFTFontEngine.cc @@ -10,10 +10,6 @@ #if HAVE_FREETYPE_H -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #ifndef _WIN32 # include diff --git a/src/xpdf-4.04/splash/SplashFTFontEngine.h b/src/xpdf-4.04/splash/SplashFTFontEngine.h index 24db3c6..e6612e1 100644 --- a/src/xpdf-4.04/splash/SplashFTFontEngine.h +++ b/src/xpdf-4.04/splash/SplashFTFontEngine.h @@ -13,10 +13,6 @@ #if HAVE_FREETYPE_H -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include FT_FREETYPE_H #include "gtypes.h" diff --git a/src/xpdf-4.04/splash/SplashFTFontFile.cc b/src/xpdf-4.04/splash/SplashFTFontFile.cc index b5fd02a..b76e543 100644 --- a/src/xpdf-4.04/splash/SplashFTFontFile.cc +++ b/src/xpdf-4.04/splash/SplashFTFontFile.cc @@ -10,10 +10,6 @@ #if HAVE_FREETYPE_H -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmem.h" #include "gmempp.h" #include "GString.h" diff --git a/src/xpdf-4.04/splash/SplashFTFontFile.h b/src/xpdf-4.04/splash/SplashFTFontFile.h index 3a6b9b7..3720d05 100644 --- a/src/xpdf-4.04/splash/SplashFTFontFile.h +++ b/src/xpdf-4.04/splash/SplashFTFontFile.h @@ -13,10 +13,6 @@ #if HAVE_FREETYPE_H -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include FT_FREETYPE_H #include "SplashFontFile.h" diff --git a/src/xpdf-4.04/splash/SplashFont.cc b/src/xpdf-4.04/splash/SplashFont.cc index 2fcd83d..0e147ab 100644 --- a/src/xpdf-4.04/splash/SplashFont.cc +++ b/src/xpdf-4.04/splash/SplashFont.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include "gmem.h" #include "gmempp.h" @@ -30,7 +26,7 @@ //------------------------------------------------------------------------ struct SplashFontCacheTag { - int c; + Guint c; short xFrac, yFrac; // x and y fractions int mru; // valid bit (0x80000000) and MRU index int x, y, w, h; // offset and size of glyph @@ -107,7 +103,7 @@ SplashFont::~SplashFont() { } } -GBool SplashFont::getGlyph(int c, int xFrac, int yFrac, +GBool SplashFont::getGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap) { SplashGlyphBitmap bitmap2; int size; diff --git a/src/xpdf-4.04/splash/SplashFont.h b/src/xpdf-4.04/splash/SplashFont.h index 2bb9654..9ca0371 100644 --- a/src/xpdf-4.04/splash/SplashFont.h +++ b/src/xpdf-4.04/splash/SplashFont.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "SplashTypes.h" #include "SplashMath.h" @@ -72,16 +68,16 @@ class SplashFont { // splashFontFraction = 1 << splashFontFractionBits. Subclasses // should override this to zero out xFrac and/or yFrac if they don't // support fractional coordinates. - virtual GBool getGlyph(int c, int xFrac, int yFrac, + virtual GBool getGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap); // Rasterize a glyph. The and values are the same // as described for getGlyph. - virtual GBool makeGlyph(int c, int xFrac, int yFrac, + virtual GBool makeGlyph(Guint c, int xFrac, int yFrac, SplashGlyphBitmap *bitmap) = 0; // Return the path for a glyph. - virtual SplashPath *getGlyphPath(int c) = 0; + virtual SplashPath *getGlyphPath(Guint c) = 0; // Return the font transform matrix. SplashCoord *getMatrix() { return mat; } diff --git a/src/xpdf-4.04/splash/SplashFontEngine.cc b/src/xpdf-4.04/splash/SplashFontEngine.cc index 81afe0c..70338a8 100644 --- a/src/xpdf-4.04/splash/SplashFontEngine.cc +++ b/src/xpdf-4.04/splash/SplashFontEngine.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #ifndef _WIN32 diff --git a/src/xpdf-4.04/splash/SplashFontEngine.h b/src/xpdf-4.04/splash/SplashFontEngine.h index 59adb95..99d7b1b 100644 --- a/src/xpdf-4.04/splash/SplashFontEngine.h +++ b/src/xpdf-4.04/splash/SplashFontEngine.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" class GString; class GList; diff --git a/src/xpdf-4.04/splash/SplashFontFile.cc b/src/xpdf-4.04/splash/SplashFontFile.cc index 2d260e3..8d846a9 100644 --- a/src/xpdf-4.04/splash/SplashFontFile.cc +++ b/src/xpdf-4.04/splash/SplashFontFile.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #ifndef _WIN32 # include diff --git a/src/xpdf-4.04/splash/SplashFontFile.h b/src/xpdf-4.04/splash/SplashFontFile.h index 133e6ab..72c51b8 100644 --- a/src/xpdf-4.04/splash/SplashFontFile.h +++ b/src/xpdf-4.04/splash/SplashFontFile.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "SplashTypes.h" diff --git a/src/xpdf-4.04/splash/SplashFontFileID.cc b/src/xpdf-4.04/splash/SplashFontFileID.cc index 27f5203..2c03cf1 100644 --- a/src/xpdf-4.04/splash/SplashFontFileID.cc +++ b/src/xpdf-4.04/splash/SplashFontFileID.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmempp.h" #include "SplashFontFileID.h" diff --git a/src/xpdf-4.04/splash/SplashFontFileID.h b/src/xpdf-4.04/splash/SplashFontFileID.h index 384018a..c4a0d7e 100644 --- a/src/xpdf-4.04/splash/SplashFontFileID.h +++ b/src/xpdf-4.04/splash/SplashFontFileID.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/splash/SplashPath.cc b/src/xpdf-4.04/splash/SplashPath.cc index 7921667..ff993d5 100644 --- a/src/xpdf-4.04/splash/SplashPath.cc +++ b/src/xpdf-4.04/splash/SplashPath.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include "gmem.h" #include "gmempp.h" diff --git a/src/xpdf-4.04/splash/SplashPath.h b/src/xpdf-4.04/splash/SplashPath.h index b5732b8..648b320 100644 --- a/src/xpdf-4.04/splash/SplashPath.h +++ b/src/xpdf-4.04/splash/SplashPath.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/splash/SplashPattern.cc b/src/xpdf-4.04/splash/SplashPattern.cc index 0c5b509..344a449 100644 --- a/src/xpdf-4.04/splash/SplashPattern.cc +++ b/src/xpdf-4.04/splash/SplashPattern.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmempp.h" #include "SplashMath.h" #include "SplashScreen.h" diff --git a/src/xpdf-4.04/splash/SplashPattern.h b/src/xpdf-4.04/splash/SplashPattern.h index fcbe21d..45a9dcd 100644 --- a/src/xpdf-4.04/splash/SplashPattern.h +++ b/src/xpdf-4.04/splash/SplashPattern.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" class SplashScreen; diff --git a/src/xpdf-4.04/splash/SplashScreen.cc b/src/xpdf-4.04/splash/SplashScreen.cc index 9993edc..0428683 100644 --- a/src/xpdf-4.04/splash/SplashScreen.cc +++ b/src/xpdf-4.04/splash/SplashScreen.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #if HAVE_STD_SORT diff --git a/src/xpdf-4.04/splash/SplashScreen.h b/src/xpdf-4.04/splash/SplashScreen.h index 560e275..9edf8e8 100644 --- a/src/xpdf-4.04/splash/SplashScreen.h +++ b/src/xpdf-4.04/splash/SplashScreen.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/splash/SplashState.cc b/src/xpdf-4.04/splash/SplashState.cc index 7fc5104..1bfc22a 100644 --- a/src/xpdf-4.04/splash/SplashState.cc +++ b/src/xpdf-4.04/splash/SplashState.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include "gmem.h" #include "gmempp.h" @@ -57,6 +53,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, lineDashLength = 0; lineDashPhase = 0; strokeAdjust = splashStrokeAdjustOff; + alphaIsShape = gFalse; clip = new SplashClip(0, 0, width, height); clipIsShared = gFalse; softMask = NULL; @@ -120,6 +117,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, lineDashLength = 0; lineDashPhase = 0; strokeAdjust = splashStrokeAdjustOff; + alphaIsShape = gFalse; clip = new SplashClip(0, 0, width, height); clipIsShared = gFalse; softMask = NULL; @@ -182,6 +180,7 @@ SplashState::SplashState(SplashState *state) { } lineDashPhase = state->lineDashPhase; strokeAdjust = state->strokeAdjust; + alphaIsShape = state->alphaIsShape; clip = state->clip; clipIsShared = gTrue; softMask = state->softMask; diff --git a/src/xpdf-4.04/splash/SplashState.h b/src/xpdf-4.04/splash/SplashState.h index be64b47..36c40bb 100644 --- a/src/xpdf-4.04/splash/SplashState.h +++ b/src/xpdf-4.04/splash/SplashState.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" class SplashPattern; @@ -107,6 +103,7 @@ class SplashState { int lineDashLength; SplashCoord lineDashPhase; SplashStrokeAdjustMode strokeAdjust; + GBool alphaIsShape; SplashClip *clip; GBool clipIsShared; SplashBitmap *softMask; diff --git a/src/xpdf-4.04/splash/SplashXPath.cc b/src/xpdf-4.04/splash/SplashXPath.cc index 4c77765..e48c29a 100644 --- a/src/xpdf-4.04/splash/SplashXPath.cc +++ b/src/xpdf-4.04/splash/SplashXPath.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #if HAVE_STD_SORT @@ -21,6 +17,7 @@ #include "gmempp.h" #include "SplashMath.h" #include "SplashPath.h" +#include "SplashClip.h" #include "SplashXPath.h" //------------------------------------------------------------------------ @@ -83,10 +80,11 @@ void SplashXPath::clampCoords(SplashCoord *x, SplashCoord *y) { SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, SplashCoord flatness, GBool closeSubpaths, GBool simplify, - SplashStrokeAdjustMode strokeAdjMode) { + SplashStrokeAdjustMode strokeAdjMode, + SplashClip *clip) { SplashXPathPoint *pts; SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp, t; - int curSubpath, firstSegInSubpath, i; + int nSubpaths, curSubpath, firstSegInSubpath, i; GBool adjusted; //--- transform the points @@ -99,7 +97,7 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, //--- do stroke adjustment if (path->hints) { adjusted = strokeAdjust(pts, path->hints, path->hintsLength, - strokeAdjMode); + strokeAdjMode, clip); } else { adjusted = gFalse; } @@ -110,6 +108,7 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, length = size = 0; x0 = y0 = xsp = ysp = 0; // make gcc happy + nSubpaths = 0; curSubpath = 0; firstSegInSubpath = 0; i = 0; @@ -160,6 +159,7 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, // end a subpath if (path->flags[i-1] & splashPathLast) { + ++nSubpaths; if (closeSubpaths && (pts[i-1].x != pts[curSubpath].x || pts[i-1].y != pts[curSubpath].y)) { @@ -180,7 +180,7 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, //--- check for a rectangle isRect = gFalse; rectX0 = rectY0 = rectX1 = rectY1 = 0; - if (length == 4) { + if (nSubpaths == 1 && length == 4) { #if HAVE_STD_SORT std::sort(segs, segs + length, SplashXPathSeg::cmpY); #else @@ -227,7 +227,8 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, GBool SplashXPath::strokeAdjust(SplashXPathPoint *pts, SplashPathHint *hints, int nHints, - SplashStrokeAdjustMode strokeAdjMode) { + SplashStrokeAdjustMode strokeAdjMode, + SplashClip *clip) { SplashXPathAdjust *adjusts, *adjust; SplashPathHint *hint; SplashCoord x0, y0, x1, y1, x2, y2, x3, y3; @@ -238,6 +239,26 @@ GBool SplashXPath::strokeAdjust(SplashXPathPoint *pts, adjusted = gFalse; + // If there is a simple rectangular clip region, stroke-adjusted + // edges that fall slightly outside the clip region are adjusted + // back inside the clip region. This avoids problems with narrow + // lines in slightly mismatched clip rectangles, which appear to be + // generated somewhat commonly by buggy CAD software. (Note: [clip] + // is NULL when called to build a clip path.) + GBool clipTweak = clip && clip->getIsSimple(); + SplashCoord cx0 = 0, cx1 = 0, cy0 = 0, cy1 = 0; + int cxi0 = 0, cxi1 = 0, cyi0 = 0, cyi1 = 0; + if (clipTweak) { + cx0 = clip->getXMin(); + cx1 = clip->getXMax(); + cy0 = clip->getYMin(); + cy1 = clip->getYMax(); + cxi0 = clip->getXMinI(strokeAdjMode); + cxi1 = clip->getXMaxI(strokeAdjMode); + cyi0 = clip->getYMinI(strokeAdjMode); + cyi1 = clip->getYMaxI(strokeAdjMode); + } + // set up the stroke adjustment hints adjusts = (SplashXPathAdjust *)gmallocn(nHints, sizeof(SplashXPathAdjust)); for (i = 0; i < nHints; ++i) { @@ -282,6 +303,32 @@ GBool SplashXPath::strokeAdjust(SplashXPathPoint *pts, adjusts[i].x1a = adj1 - d; adjusts[i].x1b = adj1 + d; splashStrokeAdjust(adj0, adj1, &xi0, &xi1, strokeAdjMode, w); + if (clipTweak) { + SplashCoord c0, c1; + int ci0, ci1; + if (adjusts[i].vert) { + c0 = cx0; + c1 = cx1; + ci0 = cxi0; + ci1 = cxi1; + } else { + c0 = cy0; + c1 = cy1; + ci0 = cyi0; + ci1 = cyi1; + } + if (adj0 < c0 && c0 < adj1 && adj1 < c1 && + adj1 - c0 > (adj1 - adj0) * 0.2 && + xi1 <= ci0) { + xi0 = ci0; + xi1 = xi0 + 1; + } else if (c0 < adj0 && adj0 < c1 && c1 < adj1 && + c1 - adj0 > (adj1 - adj0) * 0.2 && + ci1 < xi0) { + xi0 = ci1; + xi1 = ci1 + 1; + } + } adjusts[i].x0 = (SplashCoord)xi0; // the "minus epsilon" thing here is needed when vector // antialiasing is turned off -- otherwise stroke adjusted lines diff --git a/src/xpdf-4.04/splash/SplashXPath.h b/src/xpdf-4.04/splash/SplashXPath.h index 82d7889..3318866 100644 --- a/src/xpdf-4.04/splash/SplashXPath.h +++ b/src/xpdf-4.04/splash/SplashXPath.h @@ -11,13 +11,10 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" class SplashPath; +class SplashClip; struct SplashXPathPoint; struct SplashPathHint; @@ -94,7 +91,8 @@ class SplashXPath { // subpaths. SplashXPath(SplashPath *path, SplashCoord *matrix, SplashCoord flatness, GBool closeSubpaths, - GBool simplify, SplashStrokeAdjustMode strokeAdjMode); + GBool simplify, SplashStrokeAdjustMode strokeAdjMode, + SplashClip *clip); // Copy an expanded path. SplashXPath *copy() { return new SplashXPath(this); } @@ -114,7 +112,8 @@ class SplashXPath { SplashCoord *xo, SplashCoord *yo); GBool strokeAdjust(SplashXPathPoint *pts, SplashPathHint *hints, int nHints, - SplashStrokeAdjustMode strokeAdjMode); + SplashStrokeAdjustMode strokeAdjMode, + SplashClip *clip); void grow(int nSegs); void addCurve(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1, diff --git a/src/xpdf-4.04/splash/SplashXPathScanner.cc b/src/xpdf-4.04/splash/SplashXPathScanner.cc index 3f167b8..b642866 100644 --- a/src/xpdf-4.04/splash/SplashXPathScanner.cc +++ b/src/xpdf-4.04/splash/SplashXPathScanner.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #if HAVE_STD_SORT @@ -36,23 +32,25 @@ #define aaVert 4 #define aaHoriz 4 +// 4x4 oversampling tends to generate alpha (coverage) values that are +// too high, so we reduce them here. (Yes, this is a kludge.) static Guchar map16to255[17] = { 0, - 16, - 32, - 48, - 64, - 80, - 96, - 112, - 128, - 143, - 159, - 175, - 191, - 207, - 223, - 239, + 16 / 2, + 32 / 2, + 48 / 2, + 64 - 32, + 80 - 32, + 96 - 32, + 112 - 32, + 128 - 32, + 143 - 32, + 159 - 32, + 175 - 32, + 191 - 32, + 207 - 32, + 223 - 32, + 239 - 32, 255 }; diff --git a/src/xpdf-4.04/splash/SplashXPathScanner.h b/src/xpdf-4.04/splash/SplashXPathScanner.h index 39cc0eb..decfc50 100644 --- a/src/xpdf-4.04/splash/SplashXPathScanner.h +++ b/src/xpdf-4.04/splash/SplashXPathScanner.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" #include "SplashXPath.h" From 6f894c854ed2438a475b870a5f4f09309c2d3982 Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:47:33 +0200 Subject: [PATCH 05/10] Update xpdf-qt --- src/xpdf-4.04/xpdf-qt/CMakeLists.txt | 2 +- src/xpdf-4.04/xpdf-qt/QtPDFCore.cc | 35 +-- src/xpdf-4.04/xpdf-qt/QtPDFCore.h | 7 +- src/xpdf-4.04/xpdf-qt/XpdfApp.cc | 217 ++++++++++++-- src/xpdf-4.04/xpdf-qt/XpdfApp.h | 28 +- src/xpdf-4.04/xpdf-qt/XpdfViewer.cc | 357 +++++++++++++++++++---- src/xpdf-4.04/xpdf-qt/XpdfViewer.h | 30 ++ src/xpdf-4.04/xpdf-qt/XpdfWidget.cc | 96 +++--- src/xpdf-4.04/xpdf-qt/XpdfWidget.h | 55 ++-- src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc | 24 +- src/xpdf-4.04/xpdf-qt/xpdf.cc | 1 + 11 files changed, 677 insertions(+), 175 deletions(-) diff --git a/src/xpdf-4.04/xpdf-qt/CMakeLists.txt b/src/xpdf-4.04/xpdf-qt/CMakeLists.txt index 026174a..cecb926 100644 --- a/src/xpdf-4.04/xpdf-qt/CMakeLists.txt +++ b/src/xpdf-4.04/xpdf-qt/CMakeLists.txt @@ -19,7 +19,7 @@ if ((QT4_FOUND OR Qt5Widgets_FOUND OR Qt6Widgets_FOUND) if (QT4_FOUND) include(${QT_USE_FILE}) else () - include_directories(SYSTEM "${QT_INCLUDES}") + include_directories(SYSTEM ${QT_INCLUDES}) add_definitions(${QT_DEFINITIONS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QT_CFLAGS}") endif () diff --git a/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc b/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc index 9a082ed..f98c565 100644 --- a/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc +++ b/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -23,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -55,8 +52,6 @@ QtPDFCore::QtPDFCore(QWidget *viewportA, GBool reverseVideo): PDFCore(splashModeRGB8, 4, reverseVideo, paperColor) { - int dpiX, dpiY; - viewport = viewportA; hScrollBar = hScrollBarA; vScrollBar = vScrollBarA; @@ -76,6 +71,7 @@ QtPDFCore::QtPDFCore(QWidget *viewportA, dragging = gFalse; + panning = gFalse; inUpdateScrollbars = gFalse; @@ -95,23 +91,28 @@ QtPDFCore::QtPDFCore(QWidget *viewportA, panEnabled = gTrue; showPasswordDialog = gTrue; + scaleFactor = computeScaleFactor(); + displayDpi = computeDisplayDpi(); +} + +QtPDFCore::~QtPDFCore() { +} + +double QtPDFCore::computeScaleFactor() { // get Qt's HiDPI scale factor + QGuiApplication *app = (QGuiApplication *)QGuiApplication::instance(); + QScreen *screen = app->primaryScreen(); #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - scaleFactor = viewport->devicePixelRatioF(); -#elif QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - scaleFactor = viewport->devicePixelRatio(); + return screen->devicePixelRatio(); #else - scaleFactor = 1; + return 1; #endif - - // get the display resolution (used for HiDPI scaling) - dpiX = viewport->logicalDpiX(); - dpiY = viewport->logicalDpiY(); - displayDpi = dpiX < dpiY ? dpiX : dpiY; - displayDpi = (int)(displayDpi * scaleFactor); } -QtPDFCore::~QtPDFCore() { +int QtPDFCore::computeDisplayDpi() { + QGuiApplication *app = (QGuiApplication *)QGuiApplication::instance(); + QScreen *screen = app->primaryScreen(); + return (int)(screen->logicalDotsPerInch() * computeScaleFactor()); } //------------------------------------------------------------------------ diff --git a/src/xpdf-4.04/xpdf-qt/QtPDFCore.h b/src/xpdf-4.04/xpdf-qt/QtPDFCore.h index cbd1e3b..dfd5afa 100644 --- a/src/xpdf-4.04/xpdf-qt/QtPDFCore.h +++ b/src/xpdf-4.04/xpdf-qt/QtPDFCore.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include "gtypes.h" #include "SplashTypes.h" @@ -163,6 +159,9 @@ class QtPDFCore: public PDFCore { void scrollEvent(); virtual void tick(); + static double computeScaleFactor(); + static int computeDisplayDpi(); + private: //----- hyperlinks diff --git a/src/xpdf-4.04/xpdf-qt/XpdfApp.cc b/src/xpdf-4.04/xpdf-qt/XpdfApp.cc index fdcaea5..3b1d31d 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfApp.cc +++ b/src/xpdf-4.04/xpdf-qt/XpdfApp.cc @@ -12,15 +12,14 @@ #include #include #include -#ifdef _WIN32 -# include -#endif +#include #include "config.h" #include "parseargs.h" #include "GString.h" #include "GList.h" #include "gfile.h" #include "GlobalParams.h" +#include "QtPDFCore.h" #include "XpdfViewer.h" #include "XpdfApp.h" #include "gmempp.h" @@ -94,12 +93,15 @@ XpdfApp::XpdfApp(int &argc, char **argv): setApplicationVersion(xpdfVersion); ok = parseArgs(argDesc, &argc, argv); - if (!ok || printVersionArg || printHelpArg) { + if (printVersionArg) { + printf("xpdf version %s [www.xpdfreader.com]\n", xpdfVersion); + printf("%s\n", xpdfCopyright); + ::exit(99); + } + if (!ok || printHelpArg) { fprintf(stderr, "xpdf version %s [www.xpdfreader.com]\n", xpdfVersion); fprintf(stderr, "%s\n", xpdfCopyright); - if (!printVersionArg) { - printUsage("xpdf", "[ [: | +]] ...", argDesc); - } + printUsage("xpdf", "[ [: | +]] ...", argDesc); ::exit(99); } @@ -166,11 +168,47 @@ XpdfApp::XpdfApp(int &argc, char **argv): if (printCommandsArg) { globalParams->setPrintCommands(gTrue); } + zoomScaleFactor = globalParams->getZoomScaleFactor(); + if (zoomScaleFactor != 1) { + if (zoomScaleFactor <= 0) { + zoomScaleFactor = QtPDFCore::computeDisplayDpi() / 72.0; + } + GString *initialZoomStr = globalParams->getInitialZoom(); + double initialZoom = atoi(initialZoomStr->getCString()); + delete initialZoomStr; + if (initialZoom > 0) { + initialZoomStr = GString::format("{0:d}", + (int)(initialZoom * zoomScaleFactor)); + globalParams->setInitialZoom(initialZoomStr->getCString()); + delete initialZoomStr; + } + int defaultFitZoom = globalParams->getDefaultFitZoom(); + if (defaultFitZoom > 0) { + globalParams->setDefaultFitZoom((int)(defaultFitZoom * zoomScaleFactor)); + } + } + GList *zoomValueList = globalParams->getZoomValues(); + nZoomValues = 0; + for (i = 0; i < zoomValueList->getLength() && i < maxZoomValues; ++i) { + GString *val = (GString *)zoomValueList->get(i); + zoomValues[nZoomValues++] = atoi(val->getCString()); + } errorEventType = QEvent::registerEventType(); viewers = new GList(); +#ifndef DISABLE_SESSION_MANAGEMENT + //--- session management + connect(this, SIGNAL(saveStateRequest(QSessionManager&)), + this, SLOT(saveSessionSlot(QSessionManager&)), + Qt::DirectConnection); + if (isSessionRestored()) { + loadSession(sessionId().toLocal8Bit().constData(), gFalse); + return; + } +#endif + //--- remote server mode if (remoteServerArg[0]) { sock = new QLocalSocket(this); @@ -299,13 +337,19 @@ int XpdfApp::getNumViewers() { } XpdfViewer *XpdfApp::newWindow(GBool fullScreen, - const char *remoteServerName) { + const char *remoteServerName, + int x, int y, int width, int height) { XpdfViewer *viewer = new XpdfViewer(this, fullScreen); viewers->append(viewer); if (remoteServerName) { viewer->startRemoteServer(remoteServerName); } - viewer->tweakSize(); + if (width > 0 && height > 0) { + viewer->resize(width, height); + viewer->move(x, y); + } else { + viewer->tweakSize(); + } viewer->show(); return viewer; } @@ -315,7 +359,7 @@ GBool XpdfApp::openInNewWindow(QString fileName, int page, QString dest, const char *remoteServerName) { XpdfViewer *viewer; - viewer = XpdfViewer::create(this, fileName, page, dest, rotate, + viewer = XpdfViewer::create(this, fileName, 1, "", rotate, password, fullScreen); if (!viewer) { return gFalse; @@ -326,6 +370,18 @@ GBool XpdfApp::openInNewWindow(QString fileName, int page, QString dest, } viewer->tweakSize(); viewer->show(); + + // NB: do this after calling show() to avoid weird glitches if show + // resizes the new window + if (!dest.isEmpty()) { + viewer->gotoNamedDestination(dest); + } else { + if (page < 0) { + page = getSavedPageNumber(fileName); + } + viewer->gotoPage(page); + } + return gTrue; } @@ -344,6 +400,9 @@ void XpdfApp::closeWindowOrQuit(XpdfViewer *viewer) { void XpdfApp::quit() { XpdfViewer *viewer; + if (globalParams->getSaveSessionOnQuit()) { + saveSession(NULL, gFalse); + } while (viewers->getLength()) { viewer = (XpdfViewer *)viewers->del(0); viewer->close(); @@ -351,6 +410,127 @@ void XpdfApp::quit() { QApplication::quit(); } +void XpdfApp::saveSession(const char *id, GBool interactive) { + GString *path = globalParams->getSessionFile(); + if (id) { +#if 1 + // We use a single session save file for session manager sessions + // -- this prevents using multiple sessions, but it also avoids + // dealing with stale session save files. + // + // We can't use the same save file for both session manager + // sessions and save-on-quit sessions, because the session manager + // sends a 'save' request immediately on starting, which will + // overwrite the last save-on-quit session. + path->append(".managed"); +#else + path->append('.'); + path->append(id); +#endif + } + FILE *out = openFile(path->getCString(), "wb"); + if (!out) { + if (interactive) { + GString *msg = GString::format("Couldn't write the session file '{0:t}'", + path); + QMessageBox::warning(NULL, "Xpdf Error", msg->getCString()); + delete msg; + } + delete path; + return; + } + delete path; + + fprintf(out, "xpdf-session-1\n"); + for (int i = 0; i < viewers->getLength(); ++i) { + XpdfViewer *viewer = (XpdfViewer *)viewers->get(i); + fprintf(out, "window %d %d %d %d\n", + viewer->x(), viewer->y(), viewer->width(), viewer->height()); + viewer->saveSession(out, 1); + } + + fclose(out); +} + +void XpdfApp::loadSession(const char *id, GBool interactive) { + GString *path = globalParams->getSessionFile(); + if (id) { +#if 1 + // see comment in XpdfApp::saveSession + path->append(".managed"); +#else + path->append('.'); + path->append(id); +#endif + } + FILE *in = openFile(path->getCString(), "rb"); + if (!in) { + if (interactive) { + GString *msg = GString::format("Couldn't read the session file '{0:t}'", + path); + QMessageBox::warning(NULL, "Xpdf Error", msg->getCString()); + delete msg; + } + delete path; + return; + } + delete path; + + char line[1024]; + if (!fgets(line, sizeof(line), in)) { + fclose(in); + return; + } + size_t n = strlen(line); + if (n > 0 && line[n-1] == '\n') { + line[--n] = '\0'; + } + if (n > 0 && line[n-1] == '\r') { + line[--n] = '\0'; + } + if (strcmp(line, "xpdf-session-1")) { + fclose(in); + return; + } + + // if this function is called explicitly (e.g., bound to a key), and + // there is a single empty viewer (because the user has just started + // xpdf), we want to close that viewer + XpdfViewer *viewerToClose = nullptr; + if (viewers->getLength() == 1 && + ((XpdfViewer *)viewers->get(0))->isEmpty()) { + viewerToClose = (XpdfViewer *)viewers->get(0); + } + + while (fgets(line, sizeof(line), in)) { + int x, y, width, height; + if (sscanf(line, "window %d %d %d %d\n", &x, &y, &width, &height) != 4) { + fclose(in); + return; + } + + XpdfViewer *viewer = newWindow(gFalse, NULL, x, y, width, height); + viewer->loadSession(in, 1); + + if (viewerToClose) { + closeWindowOrQuit(viewerToClose); + viewerToClose = nullptr; + } + } + + fclose(in); +} + +void XpdfApp::saveSessionSlot(QSessionManager &sessionMgr) { + // Removing the saveSessionSlot function/slot would be better, but + // that causes problems with moc/cmake -- so just comment out the + // guts. In any case, this function should never even be called if + // DISABLE_SESSION_MANAGEMENT is defined. +#ifndef DISABLE_SESSION_MANAGEMENT + saveSession(sessionMgr.sessionId().toLocal8Bit().constData(), gFalse); +#endif +} + //------------------------------------------------------------------------ void XpdfApp::startUpdatePagesFile() { @@ -413,22 +593,13 @@ int XpdfApp::getSavedPageNumber(const QString &fileName) { void XpdfApp::readPagesFile() { // construct the file name (first time only) if (savedPagesFileName.isEmpty()) { + GString *s = globalParams->getPagesFile(); #ifdef _WIN32 - char path[MAX_PATH]; - if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, - SHGFP_TYPE_CURRENT, path) != S_OK) { - return; - } - savedPagesFileName = QString::fromLocal8Bit(path); - savedPagesFileName.append("/xpdf"); - CreateDirectory(savedPagesFileName.toLocal8Bit().constData(), NULL); - savedPagesFileName.append("/xpdf.pages"); + savedPagesFileName = QString::fromLocal8Bit(s->getCString()); #else - GString *path = getHomeDir(); - savedPagesFileName = QString::fromUtf8(path->getCString()); - delete path; - savedPagesFileName.append("/.xpdf.pages"); + savedPagesFileName = QString::fromUtf8(s->getCString()); #endif + delete s; } // no change since last read, so no need to re-read diff --git a/src/xpdf-4.04/xpdf-qt/XpdfApp.h b/src/xpdf-4.04/xpdf-qt/XpdfApp.h index 3ac2d2f..348100c 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfApp.h +++ b/src/xpdf-4.04/xpdf-qt/XpdfApp.h @@ -14,8 +14,10 @@ #include #include #include +#include #include "gtypes.h" +class GString; class GList; class XpdfViewer; @@ -31,6 +33,10 @@ struct XpdfSavedPageNumber { #define maxSavedPageNumbers 100 +//------------------------------------------------------------------------ + +#define maxZoomValues 100 + //------------------------------------------------------------------------ // XpdfApp //------------------------------------------------------------------------ @@ -46,7 +52,9 @@ class XpdfApp: public QApplication { int getNumViewers(); XpdfViewer *newWindow(GBool fullScreen = gFalse, - const char *remoteServerName = NULL); + const char *remoteServerName = NULL, + int x = -1, int y = -1, + int width = -1, int height = -1); GBool openInNewWindow(QString fileName, int page = 1, QString dest = QString(), @@ -67,6 +75,14 @@ class XpdfApp: public QApplication { void quit(); + // Save the current session state. For managed sessions, {id} is the + // session ID. + void saveSession(const char *id, GBool interactive); + + // Load the last saved session. For managed sessions, {id} is the + // session ID to load. + void loadSession(const char *id, GBool interactive); + //--- for use by XpdfViewer int getErrorEventType() { return errorEventType; } @@ -75,6 +91,13 @@ class XpdfApp: public QApplication { const QColor &getFullScreenMatteColor() { return fsMatteColor; } const QColor &getSelectionColor() { return selectionColor; } GBool getReverseVideo() { return reverseVideo; } + double getZoomScaleFactor() { return zoomScaleFactor; } + int getNZoomValues() { return nZoomValues; } + int getZoomValue(int idx) { return zoomValues[idx]; } + +private slots: + + void saveSessionSlot(QSessionManager &sessionMgr); private: @@ -87,6 +110,9 @@ class XpdfApp: public QApplication { QColor fsMatteColor; QColor selectionColor; GBool reverseVideo; + double zoomScaleFactor; + int zoomValues[maxZoomValues]; + int nZoomValues; GList *viewers; // [XpdfViewer] diff --git a/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc b/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc index 5ed5661..c91ce14 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc +++ b/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc @@ -83,19 +83,14 @@ static const char *aboutHTML = "
" "XpdfReader uses the following open source libraries:" "
    " - "FreeType is copyright 2006-2020 David Turner, Robert Wilhelm, and Werner Lemberg. FreeType is used here under the terms of the FreeType Project License." - "
  • The Qt Toolkit is Copyright 2015 The Qt Company Ltd. Qt is used here under the terms of the LGPL v2.1." + "
  • FreeType is copyright 2006-2025 David Turner, Robert Wilhelm, and Werner Lemberg. FreeType is used here under the terms of the FreeType Project License." + "
  • The Qt Toolkit is Copyright 2025 The Qt Company Ltd. Qt is used here under the terms of the LGPL v2.1." "
"; const char *helpURL = "http://www.xpdfreader.com/help"; //------------------------------------------------------------------------ -#define nZoomComboBoxVals 13 -static int zoomComboBoxVals[nZoomComboBoxVals] = { - 25, 50, 75, 100, 110, 125, 150, 175, 200, 300, 400, 600, 800 -}; - #define maxZoom 2000 // Maximum number of errors to show in the error window. Beyond this @@ -155,12 +150,14 @@ XpdfViewerCmd XpdfViewer::cmdTab[] = { { "hideToolbar", 0, gFalse, gFalse, &XpdfViewer::cmdHideToolbar }, { "horizontalContinuousMode",0, gFalse, gFalse, &XpdfViewer::cmdHorizontalContinuousMode }, { "linearSelectMode", 0, gFalse, gFalse, &XpdfViewer::cmdLinearSelectMode }, + { "loadSession", 0, gFalse, gFalse, &XpdfViewer::cmdLoadSession }, { "loadTabState", 0, gFalse, gFalse, &XpdfViewer::cmdLoadTabState }, { "newTab", 0, gFalse, gFalse, &XpdfViewer::cmdNewTab }, { "newWindow", 0, gFalse, gFalse, &XpdfViewer::cmdNewWindow }, { "nextPage", 0, gTrue, gFalse, &XpdfViewer::cmdNextPage }, { "nextPageNoScroll", 0, gTrue, gFalse, &XpdfViewer::cmdNextPageNoScroll }, { "nextTab", 0, gFalse, gFalse, &XpdfViewer::cmdNextTab }, + { "normalVideoMode", 0, gFalse, gFalse, &XpdfViewer::cmdNormalVideoMode }, { "open", 0, gFalse, gFalse, &XpdfViewer::cmdOpen }, { "openErrorWindow", 0, gFalse, gFalse, &XpdfViewer::cmdOpenErrorWindow }, { "openFile", 1, gFalse, gFalse, &XpdfViewer::cmdOpenFile }, @@ -187,11 +184,13 @@ XpdfViewerCmd XpdfViewer::cmdTab[] = { { "raise", 0, gFalse, gFalse, &XpdfViewer::cmdRaise }, //~ { "redraw", 0, gTrue, gFalse, &XpdfViewer::cmdRedraw }, { "reload", 0, gTrue, gFalse, &XpdfViewer::cmdReload }, + { "reverseVideoMode", 0, gFalse, gFalse, &XpdfViewer::cmdReverseVideoMode }, { "rotateCCW", 0, gTrue, gFalse, &XpdfViewer::cmdRotateCCW }, { "rotateCW", 0, gTrue, gFalse, &XpdfViewer::cmdRotateCW }, { "run", 1, gFalse, gFalse, &XpdfViewer::cmdRun }, { "saveAs", 0, gTrue, gFalse, &XpdfViewer::cmdSaveAs }, { "saveImage", 0, gTrue, gFalse, &XpdfViewer::cmdSaveImage }, + { "saveSession", 0, gFalse, gFalse, &XpdfViewer::cmdSaveSession }, { "saveTabState", 0, gFalse, gFalse, &XpdfViewer::cmdSaveTabState }, { "scrollDown", 1, gTrue, gFalse, &XpdfViewer::cmdScrollDown }, { "scrollDownNextPage", 1, gTrue, gFalse, &XpdfViewer::cmdScrollDownNextPage }, @@ -227,6 +226,7 @@ XpdfViewerCmd XpdfViewer::cmdTab[] = { { "toggleContinuousMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleContinuousMode }, { "toggleFullScreenMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleFullScreenMode }, { "toggleMenuBar", 0, gFalse, gFalse, &XpdfViewer::cmdToggleMenuBar }, + { "toggleReverseVideoMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleReverseVideoMode }, { "toggleSelectMode", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSelectMode }, { "toggleSidebar", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSidebar }, { "toggleSidebarMoveResizeWin", 0, gFalse, gFalse, &XpdfViewer::cmdToggleSidebarMoveResizeWin }, @@ -391,7 +391,7 @@ QValidator::State ZoomValidator::validate(QString &input, int &pos) const { QChar c; int n, i; - n = input.length(); + n = (int)input.length(); if (n == 0) { return QValidator::Intermediate; } @@ -447,11 +447,11 @@ QVariant PropertyListAnimation::interpolated(const QVariant &from, qreal progress) const { int i; - i = (int)(progress * valueList.size()); + i = (int)(progress * (int)valueList.size()); if (i < 0) { i = 0; } else if (i >= valueList.size()) { - i = valueList.size() - 1; + i = (int)valueList.size() - 1; } return valueList[i]; } @@ -822,6 +822,7 @@ class XpdfTabInfo { XpdfViewer::XpdfViewer(XpdfApp *appA, GBool fullScreen) { setAttribute(Qt::WA_DeleteOnClose, true); app = appA; + reverseVideo = (bool)app->getReverseVideo(); createWindow(); if (fullScreen) { move(0, 0); @@ -1008,6 +1009,118 @@ QMenu *XpdfViewer::createPopupMenu() { return NULL; } +void XpdfViewer::saveSession(FILE *out, int format) { + fprintf(out, "%d\n", tabInfo->getLength()); + for (int i = 0; i < tabInfo->getLength(); ++i) { + XpdfWidget *pdf = ((XpdfTabInfo *)tabInfo->get(i))->pdf; + QString fileName = pdf->getFileName(); + if (!fileName.isEmpty()) { + fprintf(out, "%s\n", fileName.toUtf8().constData()); + char displayModeChar; + switch (pdf->getDisplayMode()) { + case XpdfWidget::pdfDisplaySingle: + displayModeChar = 's'; + break; + case XpdfWidget::pdfDisplayContinuous: + displayModeChar = 'c'; + break; + case XpdfWidget::pdfDisplaySideBySideSingle: + displayModeChar = 'b'; + break; + case XpdfWidget::pdfDisplaySideBySideContinuous: + displayModeChar = 'B'; + break; + case XpdfWidget::pdfDisplayHorizontalContinuous: + displayModeChar = 'h'; + break; + default: + displayModeChar = 'c'; + break; + } + fprintf(out, "%c %d %g %d %d %d\n", + displayModeChar, pdf->getMidPage(), pdf->getZoom(), + pdf->getRotate(), pdf->getScrollX(), pdf->getScrollY()); + } + } +} + +void XpdfViewer::loadSession(FILE *in, int format) { + char line1[1024], line2[1024]; + if (!fgets(line1, sizeof(line1), in)) { + return; + } + int nTabs; + if (sscanf(line1, "%d", &nTabs) != 1) { + return; + } + + GBool first = gTrue; + for (int i = 0; i < nTabs; ++i) { + if (!fgets(line1, sizeof(line1), in) || !fgets(line2, sizeof(line2), in)) { + return; + } + size_t n = strlen(line1); + if (n > 0 && line1[n-1] == '\n') { + line1[--n] = '\0'; + } + if (n > 0 && line1[n-1] == '\r') { + line1[--n] = '\0'; + } + char displayModeChar; + int page, rotate, scrollX, scrollY; + double zoom; + if (sscanf(line2, "%c %d %lf %d %d %d", + &displayModeChar, &page, &zoom, &rotate, + &scrollX, &scrollY) != 6) { + return; + } + GBool ok; + if (first && !currentTab->pdf->hasOpenDocument()) { + ok = open(line1, page, "", rotate, ""); + } else { + ok = openInNewTab(line1, page, "", rotate, "", gFalse); + } + if (ok) { + XpdfWidget *pdf = lastOpenedTab->pdf; + switch (displayModeChar) { + case 's': + pdf->setDisplayMode(XpdfWidget::pdfDisplaySingle); + break; + case 'c': + pdf->setDisplayMode(XpdfWidget::pdfDisplayContinuous); + break; + case 'b': + pdf->setDisplayMode(XpdfWidget::pdfDisplaySideBySideSingle); + break; + case 'B': + pdf->setDisplayMode(XpdfWidget::pdfDisplaySideBySideContinuous); + break; + case 'h': + pdf->setDisplayMode(XpdfWidget::pdfDisplayHorizontalContinuous); + break; + default: break; + } + pdf->setRotate(rotate); + pdf->setZoom(zoom); + pdf->scrollTo(scrollX, scrollY); + } + first = gFalse; + } +} + +GBool XpdfViewer::isEmpty() { + return tabInfo->getLength() == 1 && + ((XpdfTabInfo *)tabInfo->get(0))->pdf->getFileName().isEmpty(); +} + +void XpdfViewer::gotoPage(int page) { + currentTab->pdf->gotoPage(page); +} + +void XpdfViewer::gotoNamedDestination(QString destName) { + currentTab->pdf->gotoNamedDestination(destName); +} + //------------------------------------------------------------------------ // remote server //------------------------------------------------------------------------ @@ -1095,6 +1208,7 @@ void XpdfViewer::execCmd(const char *cmd, QInputEvent *event) { //----- find the command a = -1; b = nCmds; + cmp = 0; // invariant: cmdTab[a].name < name < cmdTab[b].name while (b - a > 1) { m = (a + b) / 2; @@ -1336,10 +1450,7 @@ void XpdfViewer::cmdFindFirst(GString *args[], int nArgs, QInputEvent *event) { int flags; clearFindError(); - flags = 0; - if (findCaseSensitiveAction->isChecked()) { - flags |= XpdfWidget::findCaseSensitive; - } + flags = getFindCaseFlag(); if (findWholeWordsAction->isChecked()) { flags |= XpdfWidget::findWholeWord; } @@ -1352,10 +1463,7 @@ void XpdfViewer::cmdFindNext(GString *args[], int nArgs, QInputEvent *event) { int flags; clearFindError(); - flags = XpdfWidget::findNext; - if (findCaseSensitiveAction->isChecked()) { - flags |= XpdfWidget::findCaseSensitive; - } + flags = XpdfWidget::findNext | getFindCaseFlag(); if (findWholeWordsAction->isChecked()) { flags |= XpdfWidget::findWholeWord; } @@ -1369,10 +1477,7 @@ void XpdfViewer::cmdFindPrevious(GString *args[], int nArgs, int flags; clearFindError(); - flags = XpdfWidget::findBackward | XpdfWidget::findNext; - if (findCaseSensitiveAction->isChecked()) { - flags |= XpdfWidget::findCaseSensitive; - } + flags = XpdfWidget::findBackward | XpdfWidget::findNext | getFindCaseFlag(); if (findWholeWordsAction->isChecked()) { flags |= XpdfWidget::findWholeWord; } @@ -1483,6 +1588,11 @@ void XpdfViewer::cmdLinearSelectMode(GString *args[], int nArgs, updateSelectModeInfo(); } +void XpdfViewer::cmdLoadSession(GString *args[], int nArgs, + QInputEvent *event) { + app->loadSession(NULL, gTrue); +} + void XpdfViewer::cmdLoadTabState(GString *args[], int nArgs, QInputEvent *event) { GString *path = globalParams->getTabStateFile(); @@ -1617,6 +1727,17 @@ void XpdfViewer::cmdNextTab(GString *args[], int nArgs, QInputEvent *event) { } } +void XpdfViewer::cmdNormalVideoMode(GString *args[], int nArgs, + QInputEvent *event) { + if (reverseVideo) { + reverseVideo = false; + for (int i = 0; i < tabInfo->getLength(); ++i) { + ((XpdfTabInfo *)tabInfo->get(i))->pdf->setReverseVideo(reverseVideo); + } + reverseVideoMenuItem->setChecked(reverseVideo); + } +} + void XpdfViewer::cmdOpen(GString *args[], int nArgs, QInputEvent *event) { QString startFile, fileName; @@ -1854,6 +1975,17 @@ void XpdfViewer::cmdReload(GString *args[], int nArgs, QInputEvent *event) { } } +void XpdfViewer::cmdReverseVideoMode(GString *args[], int nArgs, + QInputEvent *event) { + if (!reverseVideo) { + reverseVideo = true; + for (int i = 0; i < tabInfo->getLength(); ++i) { + ((XpdfTabInfo *)tabInfo->get(i))->pdf->setReverseVideo(reverseVideo); + } + reverseVideoMenuItem->setChecked(reverseVideo); + } +} + void XpdfViewer::cmdRotateCW(GString *args[], int nArgs, QInputEvent *event) { currentTab->pdf->setRotate((currentTab->pdf->getRotate() + 90) % 360); } @@ -1899,6 +2031,8 @@ void XpdfViewer::cmdRun(GString *args[], int nArgs, QInputEvent *event) { fmt = args[0]; i = 0; gotSel = gotMouse = gFalse; + selPage = mPage = 0; + selURX = selURY = selLRX = selLRY = mX = mY = 0; while (i < fmt->getLength()) { c0 = fmt->getChar(i); if (c0 == '%' && i+1 < fmt->getLength()) { @@ -1939,6 +2073,11 @@ void XpdfViewer::cmdRun(GString *args[], int nArgs, QInputEvent *event) { (c1 == 'y') ? selURY : (c1 == 'X') ? selLRX : selLRY); break; + case 't': + s = currentTab->pdf->getSelectedText().left(500); + s.replace('\n', ' ').replace('\r', ' '); + cmd->append(s.toLocal8Bit().constData()); + break; case 'i': case 'j': case 'k': @@ -2011,6 +2150,11 @@ void XpdfViewer::cmdSaveImage(GString *args[], int nArgs, QInputEvent *event) { execSaveImageDialog(); } +void XpdfViewer::cmdSaveSession(GString *args[], int nArgs, + QInputEvent *event) { + app->saveSession(NULL, gTrue); +} + void XpdfViewer::cmdSaveTabState(GString *args[], int nArgs, QInputEvent *event) { GString *path = globalParams->getTabStateFile(); @@ -2280,6 +2424,15 @@ void XpdfViewer::cmdToggleMenuBar(GString *args[], int nArgs, } } +void XpdfViewer::cmdToggleReverseVideoMode(GString *args[], int nArgs, + QInputEvent *event) { + reverseVideo = !reverseVideo; + for (int i = 0; i < tabInfo->getLength(); ++i) { + ((XpdfTabInfo *)tabInfo->get(i))->pdf->setReverseVideo(reverseVideo); + } + reverseVideoMenuItem->setChecked(reverseVideo); +} + void XpdfViewer::cmdToggleSelectMode(GString *args[], int nArgs, QInputEvent *event) { if (currentTab->pdf->isBlockSelectMode()) { @@ -2361,13 +2514,16 @@ void XpdfViewer::cmdZoomFitWidth(GString *args[], int nArgs, } void XpdfViewer::cmdZoomIn(GString *args[], int nArgs, QInputEvent *event) { - double z; + double zsf, z; int i; - z = currentTab->pdf->getZoomPercent(currentTab->pdf->getMidPage()); - for (i = 0; i < zoomComboBox->count(); ++i) { - if (zoomComboBoxVals[i] > z) { - currentTab->pdf->zoomCentered(zoomComboBoxVals[i]); + zsf = app->getZoomScaleFactor(); + z = currentTab->pdf->getZoomPercent(currentTab->pdf->getMidPage()) / zsf; + for (i = 0; i < app->getNZoomValues(); ++i) { + // the 1.0001 factor is to allow for floating point jitter when + // multiplying and dividing by zoomScaleFactor + if (app->getZoomValue(i) > 1.0001 * z) { + currentTab->pdf->zoomCentered(app->getZoomValue(i) * zsf); zoomComboBox->setCurrentIndex(i); updateZoomInfo(); break; @@ -2376,13 +2532,16 @@ void XpdfViewer::cmdZoomIn(GString *args[], int nArgs, QInputEvent *event) { } void XpdfViewer::cmdZoomOut(GString *args[], int nArgs, QInputEvent *event) { - double z; + double zsf, z; int i; - z = currentTab->pdf->getZoomPercent(currentTab->pdf->getMidPage()); - for (i = zoomComboBox->count() - 1; i >= 0; --i) { - if (zoomComboBoxVals[i] < z) { - currentTab->pdf->zoomCentered(zoomComboBoxVals[i]); + zsf = app->getZoomScaleFactor(); + z = currentTab->pdf->getZoomPercent(currentTab->pdf->getMidPage()) / zsf; + for (i = app->getNZoomValues() - 1; i >= 0; --i) { + // the 0.9999 factor is to allow for floating point jitter when + // multiplying and dividing by zoomScaleFactor + if (app->getZoomValue(i) < 0.9999 * z) { + currentTab->pdf->zoomCentered(app->getZoomValue(i) * zsf); zoomComboBox->setCurrentIndex(i); updateZoomInfo(); break; @@ -2399,7 +2558,7 @@ void XpdfViewer::cmdZoomPercent(GString *args[], int nArgs, if (z > maxZoom) { z = maxZoom; } - currentTab->pdf->zoomCentered(z); + currentTab->pdf->zoomCentered(z * app->getZoomScaleFactor()); updateZoomInfo(); } @@ -2409,7 +2568,7 @@ void XpdfViewer::cmdZoomToSelection(GString *args[], int nArgs, int pg, xx0, yy0, xx1, yy1; if (currentTab->pdf->getCurrentSelection(&pg, &x0, &y0, &x1, &y1)) { - z = currentTab->pdf->getZoomPercent(pg); + z = currentTab->pdf->getZoomPercent(pg) / app->getZoomScaleFactor(); currentTab->pdf->getCore()->cvtUserToDev(pg, x0, y0, &xx0, &yy0); currentTab->pdf->getCore()->cvtUserToDev(pg, x1, y1, &xx1, &yy1); rx = (double)currentTab->pdf->getCore()->getWindowWidth() @@ -2432,6 +2591,26 @@ void XpdfViewer::cmdZoomToSelection(GString *args[], int nArgs, } } +// Check the find settings menu items and the find text to determine +// the effective case sensitivity setting. +int XpdfViewer::getFindCaseFlag() { + // could use QString::isLower(), but it's only available in Qt 5.12+ + if (findCaseSensitiveAction->isChecked()) { + return XpdfWidget::findCaseSensitive; + } else if (findSmartCaseAction->isChecked()) { + QString s = findEdit->text(); + for (int i = 0; i < s.length(); ++i) { + QChar c = s[i]; + if (c != c.toLower()) { + return XpdfWidget::findCaseSensitive; + } + } + return 0; + } else { + return 0; + } +} + int XpdfViewer::scaleScroll(int delta) { int scaledDelta; @@ -2672,6 +2851,8 @@ void XpdfViewer::mouseWheel(QWheelEvent *e) { keyCode = xpdfKeyCodeMousePress6; } else if (delta.x() < 0) { keyCode = xpdfKeyCodeMousePress7; + } else { + return; } if ((cmds = globalParams->getKeyBinding(keyCode, getModifiers(e->modifiers()), @@ -2848,6 +3029,10 @@ void XpdfViewer::openInNewWinMenuAction() { execCmd("openIn(win)", NULL); } +void XpdfViewer::closeMenuAction() { + execCmd("closeTabOrQuit", NULL); +} + void XpdfViewer::reloadMenuAction() { execCmd("reload", NULL); } @@ -2856,6 +3041,10 @@ void XpdfViewer::saveAsMenuAction() { execCmd("saveAs", NULL); } +void XpdfViewer::loadSessionMenuAction() { + execCmd("loadSession", NULL); +} + void XpdfViewer::saveImageMenuAction() { execCmd("saveImage", NULL); } @@ -2898,6 +3087,10 @@ void XpdfViewer::fullScreenMenuAction(bool checked) { execCmd(checked ? "fullScreenMode" : "windowMode", NULL); } +void XpdfViewer::reverseVideoMenuAction(bool checked) { + execCmd(checked ? "reverseVideoMode" : "normalVideoMode", NULL); +} + void XpdfViewer::rotateClockwiseMenuAction() { execCmd("rotateCW", NULL); } @@ -3191,6 +3384,10 @@ void XpdfViewer::createWindow() { // it will be updated by open/close/toggleSidebar sidebarWidth = 200; + if (globalParams->getInitialMaximized()) { + setWindowState(windowState() | Qt::WindowMaximized); + } + linkTargetBar = new QLabel(this); linkTargetBar->setStyleSheet("padding:2px; background:#00ffff;"); linkTargetBar->setAttribute(Qt::WA_TransparentForMouseEvents, true); @@ -3305,8 +3502,8 @@ void XpdfViewer::createToolBar() { addToolBarSpacing(4); zoomComboBox = new QComboBox(); zoomComboBox->setToolTip("change zoom level"); - for (i = 0; i < nZoomComboBoxVals; ++i) { - zoomVal.setNum(zoomComboBoxVals[i]); + for (i = 0; i < app->getNZoomValues(); ++i) { + zoomVal.setNum(app->getZoomValue(i)); zoomVal.append('%'); zoomComboBox->addItem(zoomVal); } @@ -3353,8 +3550,18 @@ void XpdfViewer::createToolBar() { addToolBarButton(QIcon(":/findPrevious-button"), SLOT(findPrevButtonPressed()), "find previous occurrence"); QMenu *findSettingsMenu = new QMenu(this); + QActionGroup *findCaseGroup = new QActionGroup(findSettingsMenu); + findCaseInsensitiveAction = findSettingsMenu->addAction("case insensitive"); + findCaseInsensitiveAction->setCheckable(true); + findCaseGroup->addAction(findCaseInsensitiveAction); findCaseSensitiveAction = findSettingsMenu->addAction("case sensitive"); findCaseSensitiveAction->setCheckable(true); + findCaseGroup->addAction(findCaseSensitiveAction); + findSmartCaseAction = findSettingsMenu->addAction("smart case"); + findSmartCaseAction->setCheckable(true); + findSmartCaseAction->setChecked(true); + findCaseGroup->addAction(findSmartCaseAction); + findSettingsMenu->addSeparator(); findWholeWordsAction = findSettingsMenu->addAction("whole words"); findWholeWordsAction->setCheckable(true); addToolBarMenuButton(QIcon(":/findSettings-button"), @@ -3411,8 +3618,11 @@ void XpdfViewer::createMainMenu() { fileSubmenu->addAction("&Open...", this, SLOT(openMenuAction())); fileSubmenu->addAction("Open in new window...", this, SLOT(openInNewWinMenuAction())); + fileSubmenu->addAction("Close tab", this, SLOT(closeMenuAction())); fileSubmenu->addAction("Reload", this, SLOT(reloadMenuAction())); fileSubmenu->addAction("&Save as...", this, SLOT(saveAsMenuAction())); + fileSubmenu->addAction("Load last session", + this, SLOT(loadSessionMenuAction())); fileSubmenu->addSeparator(); fileSubmenu->addAction("Save image...", this, SLOT(saveImageMenuAction())); #if XPDFWIDGET_PRINTING @@ -3475,6 +3685,11 @@ void XpdfViewer::createMainMenu() { fullScreenMenuItem = viewSubmenu->addAction("Full screen", this, SLOT(fullScreenMenuAction(bool))); fullScreenMenuItem->setCheckable(true); + reverseVideoMenuItem = + viewSubmenu->addAction("Reverse video", this, + SLOT(reverseVideoMenuAction(bool))); + reverseVideoMenuItem->setCheckable(true); + reverseVideoMenuItem->setChecked(reverseVideo); viewSubmenu->addSeparator(); viewSubmenu->addAction("Rotate clockwise", this, SLOT(rotateClockwiseMenuAction())); @@ -3546,6 +3761,8 @@ QWidget *XpdfViewer::createTabPane() { tabList = new QListWidget(); tabList->setSelectionMode(QAbstractItemView::SingleSelection); + tabList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + tabList->setTextElideMode(Qt::ElideNone); tabList->setDragEnabled(true); tabList->setDragDropMode(QAbstractItemView::InternalMove); tabList->viewport()->setAcceptDrops(true); @@ -3559,7 +3776,7 @@ QWidget *XpdfViewer::createTabPane() { const QModelIndex&, int))); tabPaneLayout->addWidget(tabList); - QPushButton *newTabBtn = new QPushButton("+ tab"); + QPushButton *newTabBtn = new QPushButton("+ new tab"); connect(newTabBtn, SIGNAL(clicked()), this, SLOT(newTabButtonPressed())); tabPaneLayout->addWidget(newTabBtn); @@ -3670,7 +3887,7 @@ void XpdfViewer::addTab() { GString *initialSelectMode; pdf = new XpdfWidget(NULL, app->getPaperColor(), app->getMatteColor(), - app->getReverseVideo()); + reverseVideo); pdf->setSelectionColor(app->getSelectionColor()); pdf->enableHyperlinks(false); pdf->setKeyPassthrough(true); @@ -3847,7 +4064,8 @@ void XpdfViewer::updateZoomInfo() { } else { pg = 1; } - z = (int)floor(currentTab->pdf->getZoomPercent(pg) + 0.5); + z = (int)floor(currentTab->pdf->getZoomPercent(pg) / + app->getZoomScaleFactor() + 0.5); zoomStr.setNum(z); zoomStr.append('%'); zoomComboBox->setEditText(zoomStr); @@ -3879,23 +4097,13 @@ void XpdfViewer::updateSelectModeInfo() { // - a tab switch happens // It updates all visible info related to the document. void XpdfViewer::updateDocInfo() { - //--- window title - QString windowTitle; - if (currentTab->pdf->hasOpenDocument()) { - windowTitle = currentTab->pdf->getFileName(); - windowTitle += " - XpdfReader"; - } else { - windowTitle = "XpdfReader"; - } - setWindowTitle(windowTitle); - - //--- tab title - QString tabTitle; + //--- window and tab titles + QString windowTitle, tabTitle; if (currentTab->pdf->hasOpenDocument()) { tabTitle = currentTab->pdf->getFileName(); - int i = tabTitle.lastIndexOf('/'); + int i = (int)tabTitle.lastIndexOf('/'); #ifdef _WIN32 - int j = tabTitle.lastIndexOf('\\'); + int j = (int)tabTitle.lastIndexOf('\\'); if (j > i) { i = j; } @@ -3903,9 +4111,12 @@ void XpdfViewer::updateDocInfo() { if (i >= 0) { tabTitle = tabTitle.mid(i + 1) + " [" + tabTitle.left(i + 1) + "]"; } + windowTitle = tabTitle + " - XpdfReader"; } else { tabTitle = "(empty)"; + windowTitle = "XpdfReader"; } + setWindowTitle(windowTitle); currentTab->listItem->setText(tabTitle); currentTab->listItem->setToolTip(tabTitle); @@ -4584,6 +4795,7 @@ QString XpdfViewer::createDocumentInfoFontsHTML(XpdfWidget *view) { char *seenObjs = (char *)gmalloc(numObjects); memset(seenObjs, 0, numObjects); + Annots *annots = doc->getAnnots(); for (int pg = 1; pg <= doc->getNumPages(); ++pg) { Page *page = doc->getCatalog()->getPage(pg); Dict *resDict = page->getResourceDict(); @@ -4591,17 +4803,15 @@ QString XpdfViewer::createDocumentInfoFontsHTML(XpdfWidget *view) { html += scanFonts(resDict, doc, seenObjs); } Object obj1, obj2; - Annots *annots = new Annots(doc, page->getAnnots(&obj1)); - obj1.free(); - for (int i = 0; i < annots->getNumAnnots(); ++i) { - if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + int nAnnots = annots->getNumAnnots(pg); + for (int i = 0; i < nAnnots; ++i) { + if (annots->getAnnot(pg, i)->getAppearance(&obj1)->isStream()) { obj1.streamGetDict()->lookupNF("Resources", &obj2); html += scanFonts(&obj2, doc, seenObjs); obj2.free(); } obj1.free(); } - delete annots; } AcroForm *form = doc->getCatalog()->getForm(); if (form) { @@ -4862,6 +5072,21 @@ void XpdfViewer::execSaveImageDialog() { regionBox->addWidget(selectionBtn); selectionBtn->setEnabled(currentTab->pdf->hasSelection()); + grid->addWidget(new QLabel("Color:"), 1, 0); + + QHBoxLayout *colorBox = new QHBoxLayout(); + grid->addLayout(colorBox, 1, 1); + + QComboBox *colorCombo = new QComboBox(); + colorBox->addWidget(colorCombo); + colorCombo->setEditable(false); + colorCombo->addItem("RGB"); + colorCombo->addItem("Gray"); + colorCombo->addItem("Monochrome"); + colorCombo->setCurrentIndex(0); + + colorBox->addStretch(); + grid->addWidget(new QLabel("Resolution:"), 2, 0); QHBoxLayout *resolutionBox = new QHBoxLayout(); @@ -4926,6 +5151,17 @@ void XpdfViewer::execSaveImageDialog() { currentTab->pdf->getCurrentSelection(&page, &x0, &y0, &x1, &y1); } int fmt = formatCombo->currentIndex(); + XpdfWidget::ImageColorMode color; + if (colorCombo->currentIndex() == 1) { + color = XpdfWidget::pdfImageColorGray; + } else if (colorCombo->currentIndex() == 2) { + color = XpdfWidget::pdfImageColorMono; + if (strcmp(saveImageFormats[fmt].qImageFormat, "TIFF")) { + color = XpdfWidget::pdfImageColorGray; + } + } else { + color = XpdfWidget::pdfImageColorRGB; + } QString fileName = QFileDialog::getSaveFileName(this, "Save Image", QString(), @@ -4933,9 +5169,10 @@ void XpdfViewer::execSaveImageDialog() { if (!fileName.isEmpty()) { QImage img; if (wholePage) { - img = currentTab->pdf->convertPageToImage(page, res); + img = currentTab->pdf->convertPageToImage(page, res, false, color); } else { - img = currentTab->pdf->convertRegionToImage(page, x0, y0, x1, y1, res); + img = currentTab->pdf->convertRegionToImage(page, x0, y0, x1, y1, res, + false, color); } img.save(fileName, saveImageFormats[fmt].qImageFormat); } diff --git a/src/xpdf-4.04/xpdf-qt/XpdfViewer.h b/src/xpdf-4.04/xpdf-qt/XpdfViewer.h index f957626..66c3998 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfViewer.h +++ b/src/xpdf-4.04/xpdf-qt/XpdfViewer.h @@ -154,6 +154,22 @@ class XpdfViewer: public QMainWindow { // Execute a command [cmd], with [event] for context. void execCmd(const char *cmd, QInputEvent *event); + // Used by XpdfApp::saveSession() to save session info for one + // window. + void saveSession(FILE *out, int format); + + // Used by XpdfApp::loadSession() to load a session for one window. + void loadSession(FILE *in, int format); + + // Returns true if this viewer contains a single empty tab. + GBool isEmpty(); + + // Goto [page] in the current tab. + void gotoPage(int page); + + // Goto [destName] in the current tab. + void gotoNamedDestination(QString destName); + public slots: bool close(); @@ -184,8 +200,10 @@ private slots: void openMenuAction(); void openInNewWinMenuAction(); + void closeMenuAction(); void reloadMenuAction(); void saveAsMenuAction(); + void loadSessionMenuAction(); void saveImageMenuAction(); #if XPDFWIDGET_PRINTING void printMenuAction(); @@ -198,6 +216,7 @@ private slots: void sideBySideContinuousModeMenuAction(); void horizontalContinuousModeMenuAction(); void fullScreenMenuAction(bool checked); + void reverseVideoMenuAction(bool checked); void rotateClockwiseMenuAction(); void rotateCounterclockwiseMenuAction(); void zoomToSelectionMenuAction(); @@ -292,12 +311,14 @@ private slots: void cmdHideToolbar(GString *args[], int nArgs, QInputEvent *event); void cmdHorizontalContinuousMode(GString *args[], int nArgs, QInputEvent *event); void cmdLinearSelectMode(GString *args[], int nArgs, QInputEvent *event); + void cmdLoadSession(GString *args[], int nArgs, QInputEvent *event); void cmdLoadTabState(GString *args[], int nArgs, QInputEvent *event); void cmdNewTab(GString *args[], int nArgs, QInputEvent *event); void cmdNewWindow(GString *args[], int nArgs, QInputEvent *event); void cmdNextPage(GString *args[], int nArgs, QInputEvent *event); void cmdNextPageNoScroll(GString *args[], int nArgs, QInputEvent *event); void cmdNextTab(GString *args[], int nArgs, QInputEvent *event); + void cmdNormalVideoMode(GString *args[], int nArgs, QInputEvent *event); void cmdOpen(GString *args[], int nArgs, QInputEvent *event); void cmdOpenErrorWindow(GString *args[], int nArgs, QInputEvent *event); void cmdOpenFile(GString *args[], int nArgs, QInputEvent *event); @@ -323,11 +344,13 @@ private slots: void cmdQuit(GString *args[], int nArgs, QInputEvent *event); void cmdRaise(GString *args[], int nArgs, QInputEvent *event); void cmdReload(GString *args[], int nArgs, QInputEvent *event); + void cmdReverseVideoMode(GString *args[], int nArgs, QInputEvent *event); void cmdRotateCW(GString *args[], int nArgs, QInputEvent *event); void cmdRotateCCW(GString *args[], int nArgs, QInputEvent *event); void cmdRun(GString *args[], int nArgs, QInputEvent *event); void cmdSaveAs(GString *args[], int nArgs, QInputEvent *event); void cmdSaveImage(GString *args[], int nArgs, QInputEvent *event); + void cmdSaveSession(GString *args[], int nArgs, QInputEvent *event); void cmdSaveTabState(GString *args[], int nArgs, QInputEvent *event); void cmdScrollDown(GString *args[], int nArgs, QInputEvent *event); void cmdScrollDownNextPage(GString *args[], int nArgs, QInputEvent *event); @@ -363,6 +386,7 @@ private slots: void cmdToggleContinuousMode(GString *args[], int nArgs, QInputEvent *event); void cmdToggleFullScreenMode(GString *args[], int nArgs, QInputEvent *event); void cmdToggleMenuBar(GString *args[], int nArgs, QInputEvent *event); + void cmdToggleReverseVideoMode(GString *args[], int nArgs, QInputEvent *event); void cmdToggleSelectMode(GString *args[], int nArgs, QInputEvent *event); void cmdToggleSidebar(GString *args[], int nArgs, QInputEvent *event); void cmdToggleSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event); @@ -377,6 +401,7 @@ private slots: void cmdZoomOut(GString *args[], int nArgs, QInputEvent *event); void cmdZoomPercent(GString *args[], int nArgs, QInputEvent *event); void cmdZoomToSelection(GString *args[], int nArgs, QInputEvent *event); + int getFindCaseFlag(); int scaleScroll(int delta); void followLink(QInputEvent *event, GBool onlyIfNoSel, GBool newTab, GBool newWindow); @@ -441,6 +466,7 @@ private slots: QMenuBar *mainMenu; QMenu *displayModeSubmenu; QAction *fullScreenMenuItem; + QAction *reverseVideoMenuItem; QAction *toggleToolbarMenuItem; QAction *toggleSidebarMenuItem; QAction *viewPageLabelsMenuItem; @@ -462,7 +488,9 @@ private slots: QList indicatorIcons; QList indicatorErrIcons; QLineEdit *findEdit; + QAction *findCaseInsensitiveAction; QAction *findCaseSensitiveAction; + QAction *findSmartCaseAction; QAction *findWholeWordsAction; // sidebar pane @@ -483,6 +511,8 @@ private slots: XpdfTabInfo *currentTab; XpdfTabInfo *lastOpenedTab; + bool reverseVideo; + double scaleFactor; XpdfWidget::DisplayMode fullScreenPreviousDisplayMode; diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc b/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc index f5ad763..3be50d2 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc +++ b/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #ifdef _WIN32 #include #endif @@ -1266,7 +1262,8 @@ void XpdfWidget::setPrintDPI(int hDPI, int vDPI) { #endif // XPDFWIDGET_PRINTING -QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) { +QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent, + ImageColorMode color) { try { PDFDoc *doc = core->getDoc(); if (!doc) { @@ -1275,18 +1272,34 @@ QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) { if (page < 1 || page > doc->getNumPages()) { return QImage(); } - if (transparent) { - SplashColor paperColor; - paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused - SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse, - paperColor); + SplashColorMode mode; + SplashColor paperColor; + QImage::Format format; + if (color == pdfImageColorMono) { + mode = splashModeMono1; + paperColor[0] = 0xff; + format = QImage::Format_Mono; + } else if (color == pdfImageColorGray) { + mode = splashModeMono8; + paperColor[0] = 0xff; + format = QImage::Format_Grayscale8; + } else { + mode = splashModeRGB8; + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + if (transparent) { + format = QImage::Format_ARGB32; + } else { + format = QImage::Format_RGB888; + } + } + if (format == QImage::Format_ARGB32) { + SplashOutputDev *out = new SplashOutputDev(mode, 1, gFalse, paperColor); out->setNoComposite(gTrue); out->startDoc(doc->getXRef()); - doc->displayPage(out, page, dpi, dpi, core->getRotate(), + doc->displayPage(out, NULL, page, dpi, dpi, core->getRotate(), gFalse, gTrue, gFalse); SplashBitmap *bitmap = out->getBitmap(); - QImage img(bitmap->getWidth(), bitmap->getHeight(), - QImage::Format_ARGB32); + QImage img(bitmap->getWidth(), bitmap->getHeight(), format); Guchar *pix = bitmap->getDataPtr(); Guchar *alpha = bitmap->getAlphaPtr(); Guint *argb = (Guint *)img.bits(); @@ -1301,17 +1314,14 @@ QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) { delete out; return img; } else { - SplashColor paperColor; - paperColor[0] = paperColor[1] = paperColor[2] = 0xff; - SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse, - paperColor); + SplashOutputDev *out = new SplashOutputDev(mode, 4, gFalse, paperColor); out->startDoc(doc->getXRef()); - doc->displayPage(out, page, dpi, dpi, core->getRotate(), + doc->displayPage(out, NULL, page, dpi, dpi, core->getRotate(), gFalse, gTrue, gFalse); SplashBitmap *bitmap = out->getBitmap(); QImage *img = new QImage((const uchar *)bitmap->getDataPtr(), bitmap->getWidth(), bitmap->getHeight(), - QImage::Format_RGB888); + format); // force a copy QImage img2(img->copy()); delete img; @@ -1325,7 +1335,8 @@ QImage XpdfWidget::convertPageToImage(int page, double dpi, bool transparent) { QImage XpdfWidget::convertRegionToImage(int page, double x0, double y0, double x1, double y1, double dpi, - bool transparent) { + bool transparent, + ImageColorMode color) { try { PDFDoc *doc = core->getDoc(); if (!doc) { @@ -1367,19 +1378,35 @@ QImage XpdfWidget::convertRegionToImage(int page, double x0, double y0, sliceH = (int)(k * (y1 - y0)); } - if (transparent) { - SplashColor paperColor; - paperColor[0] = paperColor[1] = paperColor[2] = 0xff; // unused - SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 1, gFalse, - paperColor); + SplashColorMode mode; + SplashColor paperColor; + QImage::Format format; + if (color == pdfImageColorMono) { + mode = splashModeMono1; + paperColor[0] = 0xff; + format = QImage::Format_Mono; + } else if (color == pdfImageColorGray) { + mode = splashModeMono8; + paperColor[0] = 0xff; + format = QImage::Format_Grayscale8; + } else { + mode = splashModeRGB8; + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + if (transparent) { + format = QImage::Format_ARGB32; + } else { + format = QImage::Format_RGB888; + } + } + if (format == QImage::Format_ARGB32) { + SplashOutputDev *out = new SplashOutputDev(mode, 1, gFalse, paperColor); out->setNoComposite(gTrue); out->startDoc(doc->getXRef()); - doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(), + doc->displayPageSlice(out, NULL, page, dpi, dpi, core->getRotate(), gFalse, gTrue, gFalse, sliceX, sliceY, sliceW, sliceH); SplashBitmap *bitmap = out->getBitmap(); - QImage img(bitmap->getWidth(), bitmap->getHeight(), - QImage::Format_ARGB32); + QImage img(bitmap->getWidth(), bitmap->getHeight(), format); Guchar *pix = bitmap->getDataPtr(); Guchar *alpha = bitmap->getAlphaPtr(); Guint *argb = (Guint *)img.bits(); @@ -1394,18 +1421,15 @@ QImage XpdfWidget::convertRegionToImage(int page, double x0, double y0, delete out; return img; } else { - SplashColor paperColor; - paperColor[0] = paperColor[1] = paperColor[2] = 0xff; - SplashOutputDev *out = new SplashOutputDev(splashModeRGB8, 4, gFalse, - paperColor); + SplashOutputDev *out = new SplashOutputDev(mode, 4, gFalse, paperColor); out->startDoc(doc->getXRef()); - doc->displayPageSlice(out, page, dpi, dpi, core->getRotate(), + doc->displayPageSlice(out, NULL, page, dpi, dpi, core->getRotate(), gFalse, gTrue, gFalse, sliceX, sliceY, sliceW, sliceH); SplashBitmap *bitmap = out->getBitmap(); QImage *img = new QImage((const uchar *)bitmap->getDataPtr(), bitmap->getWidth(), bitmap->getHeight(), - QImage::Format_RGB888); + format); // force a copy QImage img2(img->copy()); delete img; @@ -1572,7 +1596,7 @@ bool XpdfWidget::find(const QString &text, int flags) { if (!core->getDoc()) { return false; } - len = text.length(); + len = (int)text.length(); u = (Unicode *)gmallocn(len, sizeof(Unicode)); for (i = 0; i < len; ++i) { u[i] = (Unicode)text[i].unicode(); @@ -1597,7 +1621,7 @@ QVector XpdfWidget::findAll(const QString &text, int firstPage, if (!core->getDoc()) { return v; } - int len = text.length(); + int len = (int)text.length(); Unicode *u = (Unicode *)gmallocn(len, sizeof(Unicode)); for (int i = 0; i < len; ++i) { u[i] = (Unicode)text[i].unicode(); diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidget.h b/src/xpdf-4.04/xpdf-qt/XpdfWidget.h index 0e33d0d..25a8474 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfWidget.h +++ b/src/xpdf-4.04/xpdf-qt/XpdfWidget.h @@ -2,7 +2,7 @@ // // XpdfWidget.h // -// Copyright 2009-2021 Glyph & Cog, LLC +// Copyright 2009-2025 Glyph & Cog, LLC // //======================================================================== @@ -12,7 +12,7 @@ //!

//! Change history //!

-//! Copyright 2009-2022 Glyph & Cog, LLC +//! Copyright 2009-2025 Glyph & Cog, LLC //! \file @@ -21,10 +21,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include class QMutex; @@ -74,10 +70,10 @@ struct XpdfFindResult { /*! Page number. */ int page; - /*! \name Bounding box. */ - ///@{ - double xMin, yMin, xMax, yMax; - ///@} + double xMin, /*!< Bounding box - minimum x coordinate. */ + yMin, /*!< Bounding box - minimum y coordinate. */ + xMax, /*!< Bounding box - maximum x coordinate. */ + yMax; /*!< Bounding box - maximum y coordinate. */ }; //------------------------------------------------------------------------ @@ -141,6 +137,15 @@ class XpdfWidget: public QAbstractScrollArea { static const int findWholeWord = 0x00000010; //@} + //! Color modes, to be passed to the image conversion functions. + //! These can be used with XpdfWidget::convertPageToImage() and + //! XpdfWidget::convertRegionToImage(). + enum ImageColorMode { + pdfImageColorRGB, + pdfImageColorGray, + pdfImageColorMono + }; + //! Initialize the XpdfWidget class, reading a configuration file. //! If \a configFileName is non-empty, the specified file is //! tried first. If \a configFileName is empty, or the file @@ -238,7 +243,7 @@ class XpdfWidget: public QAbstractScrollArea { //! Control the password dialog. //! If enabled, the viewer will show a password dialog for encrypted //! files; if disabled, it will simply return \c pdfErrEncrypted unless - //! the correct password is passed to \c pdfLoadFileWithPassword. The + //! the correct password is passed to \c loadFile or \c loadMem. The //! default is enabled. void showPasswordDialog(bool showDlg); @@ -638,22 +643,30 @@ class XpdfWidget: public QAbstractScrollArea { void setPrintDPI(int hDPI, int vDPI); #endif // XPDFWIDGET_PRINTING - //! Convert a page to a color image. - //! This function converts the page number \a page to a 24-bit RGB - //! bitmap, at a resolution of \a dpi dots per inch. If \a - //! transparent is true, the returned image will be 32-bit ARGB + //! Convert a page to an image. + //! This function converts page number \a page to a bitmap, at a + //! resolution of \a dpi dots per inch. The image is 24-bit RGB if + //! \a color is \c pdfImageColorRGB, 8-bit grayscale if \a color is + //! \c pdfImageColorGray, or 1-bit monochrome if \a color is \c + //! pdfImageColorMono. If \a transparent is true and \a color is \c + //! pdfImageColorRGB, the returned image will be 32-bit ARGB //! instead, and will include an alpha channel. - QImage convertPageToImage(int page, double dpi, bool transparent = false); + QImage convertPageToImage(int page, double dpi, bool transparent = false, + ImageColorMode color = pdfImageColorRGB); - //! Convert a rectangular region of a page to a color image. + //! Convert a rectangular region of a page to an image. //! This function converts a rectangular region, defined by corners //! (\a x0,\a y0) and (\a x1,\a y1), of page number \a page to a - //! 24-bit RGB bitmap, at a resolution of \a dpi dots per inch. If - //! \a transparent is true, the returned image will be 32-bit ARGB - //! instead, and will include an alpha channel. + //! bitmap, at a resolution of \a dpi dots per inch. The image is + //! 24-bit RGB if \a color is \c pdfImageColorRGB, 8-bit grayscale + //! if \a color is \c pdfImageColorGray, or 1-bit monochrome if \a + //! color is \c pdfImageColorMono. If \a transparent is true and \a + //! color is \c pdfImageColorRGB, the returned image will be 32-bit + //! ARGB instead, and will include an alpha channel. QImage convertRegionToImage(int page, double x0, double y0, double x1, double y1, double dpi, - bool transparent = false); + bool transparent = false, + ImageColorMode color = pdfImageColorRGB); //! Retrieve an embedded thumbnail image. //! This function returns the embedded thumbnail image for the diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc b/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc index e57ae10..f9aff45 100644 --- a/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc +++ b/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc @@ -60,7 +60,7 @@ XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt, CGContextRef ctx; CGAffineTransform pageTransform; QPrinter::ColorMode colorMode; - QSizeF paperSize; + QSize paperSize; QPrinter::PaperSource paperSource; QPageLayout::Orientation pageOrientation; FILE *f; @@ -117,7 +117,7 @@ XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt, //--- get other parameters colorMode = prt->colorMode(); - paperSize = prt->paperSize(QPrinter::Point); + paperSize = prt->pageLayout().pageSize().sizePoints(); paperSource = prt->paperSource(); pageOrientation = prt->pageLayout().orientation(); @@ -325,8 +325,8 @@ XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt, int hDPI, int vDPI, XpdfWidget *widget) { int startPage, endPage; - QPrinter::PaperSize paperSize; - QSizeF paperSizePts; + QPageSize::PageSizeId paperSize; + QSize paperSizePts; QPrinter::PaperSource paperSource; QPrinter::DuplexMode duplex; GString *psFileName; @@ -356,8 +356,8 @@ XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt, //--- get other parameters - paperSize = prt->paperSize(); - paperSizePts = prt->paperSize(QPrinter::Point); + paperSize = prt->pageLayout().pageSize().id(); + paperSizePts = prt->pageLayout().pageSize().sizePoints(); paperSource = prt->paperSource(); duplex = prt->duplex(); @@ -395,7 +395,7 @@ XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt, fclose(psFile); goto err1; } - doc->displayPage(psOut, pg, 72, 72, 0, + doc->displayPage(psOut, NULL, pg, 72, 72, 0, !globalParams->getPSUseCropBoxAsPage(), gTrue, gTrue); widget->updatePrintStatus(pg + 1, startPage, endPage); @@ -425,11 +425,11 @@ XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt, nOptions = 0; switch (paperSize) { - case QPrinter::A4: paperSizeStr = "A4"; break; - case QPrinter::Comm10E: paperSizeStr = "COM10"; break; - case QPrinter::DLE: paperSizeStr = "DL"; break; - case QPrinter::Legal: paperSizeStr = "Legal"; break; - case QPrinter::Letter: paperSizeStr = "Letter"; break; + case QPageSize::A4: paperSizeStr = "A4"; break; + case QPageSize::Comm10E: paperSizeStr = "COM10"; break; + case QPageSize::DLE: paperSizeStr = "DL"; break; + case QPageSize::Legal: paperSizeStr = "Legal"; break; + case QPageSize::Letter: paperSizeStr = "Letter"; break; default: paperSizeStr = NULL; break; } switch (paperSource) { diff --git a/src/xpdf-4.04/xpdf-qt/xpdf.cc b/src/xpdf-4.04/xpdf-qt/xpdf.cc index 63e52d8..550738f 100644 --- a/src/xpdf-4.04/xpdf-qt/xpdf.cc +++ b/src/xpdf-4.04/xpdf-qt/xpdf.cc @@ -11,6 +11,7 @@ #include "gmem.h" #include "Object.h" #include "XpdfApp.h" +#include "gmempp.h" int main(int argc, char *argv[]) { int exitCode; From b661869843188d4cc7816c1431327ea68386e77d Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:52:34 +0200 Subject: [PATCH 06/10] Update xpdf --- src/xpdf-4.04/xpdf/AcroForm.cc | 80 +- src/xpdf-4.04/xpdf/AcroForm.h | 9 +- src/xpdf-4.04/xpdf/Annot.cc | 423 +++-- src/xpdf-4.04/xpdf/Annot.h | 56 +- src/xpdf-4.04/xpdf/Array.cc | 8 +- src/xpdf-4.04/xpdf/Array.h | 4 - src/xpdf-4.04/xpdf/BuiltinFont.cc | 4 - src/xpdf-4.04/xpdf/BuiltinFont.h | 4 - src/xpdf-4.04/xpdf/CMakeLists.txt | 1 + src/xpdf-4.04/xpdf/CMap.cc | 85 +- src/xpdf-4.04/xpdf/CMap.h | 23 +- src/xpdf-4.04/xpdf/Catalog.cc | 403 ++++- src/xpdf-4.04/xpdf/Catalog.h | 22 +- src/xpdf-4.04/xpdf/CharCodeToUnicode.cc | 18 +- src/xpdf-4.04/xpdf/CharCodeToUnicode.h | 4 - src/xpdf-4.04/xpdf/Decrypt.cc | 36 +- src/xpdf-4.04/xpdf/Decrypt.h | 4 - src/xpdf-4.04/xpdf/Dict.cc | 4 - src/xpdf-4.04/xpdf/Dict.h | 4 - src/xpdf-4.04/xpdf/DisplayState.cc | 4 - src/xpdf-4.04/xpdf/DisplayState.h | 4 - src/xpdf-4.04/xpdf/Error.cc | 4 - src/xpdf-4.04/xpdf/Error.h | 4 - src/xpdf-4.04/xpdf/Function.cc | 14 +- src/xpdf-4.04/xpdf/Function.h | 4 - src/xpdf-4.04/xpdf/Gfx.cc | 567 ++++--- src/xpdf-4.04/xpdf/Gfx.h | 20 +- src/xpdf-4.04/xpdf/GfxFont.cc | 515 ++++-- src/xpdf-4.04/xpdf/GfxFont.h | 27 +- src/xpdf-4.04/xpdf/GfxState.cc | 485 ++++-- src/xpdf-4.04/xpdf/GfxState.h | 30 +- src/xpdf-4.04/xpdf/GlobalParams.cc | 562 +++++- src/xpdf-4.04/xpdf/GlobalParams.h | 35 +- src/xpdf-4.04/xpdf/HTMLGen.cc | 117 +- src/xpdf-4.04/xpdf/HTMLGen.h | 24 +- src/xpdf-4.04/xpdf/ImageOutputDev.cc | 116 +- src/xpdf-4.04/xpdf/ImageOutputDev.h | 28 +- src/xpdf-4.04/xpdf/JArithmeticDecoder.cc | 37 +- src/xpdf-4.04/xpdf/JArithmeticDecoder.h | 8 +- src/xpdf-4.04/xpdf/JBIG2Stream.cc | 50 +- src/xpdf-4.04/xpdf/JBIG2Stream.h | 5 +- src/xpdf-4.04/xpdf/JPXStream.cc | 21 +- src/xpdf-4.04/xpdf/JPXStream.h | 6 +- src/xpdf-4.04/xpdf/Lexer.cc | 19 +- src/xpdf-4.04/xpdf/Lexer.h | 4 - src/xpdf-4.04/xpdf/Link.cc | 4 - src/xpdf-4.04/xpdf/Link.h | 4 - src/xpdf-4.04/xpdf/LocalParams.cc | 21 + src/xpdf-4.04/xpdf/LocalParams.h | 40 + src/xpdf-4.04/xpdf/NameToCharCode.cc | 4 - src/xpdf-4.04/xpdf/NameToCharCode.h | 4 - src/xpdf-4.04/xpdf/Object.cc | 14 +- src/xpdf-4.04/xpdf/Object.h | 8 +- src/xpdf-4.04/xpdf/OptionalContent.cc | 4 - src/xpdf-4.04/xpdf/OptionalContent.h | 4 - src/xpdf-4.04/xpdf/Outline.cc | 4 - src/xpdf-4.04/xpdf/Outline.h | 4 - src/xpdf-4.04/xpdf/OutputDev.cc | 13 +- src/xpdf-4.04/xpdf/OutputDev.h | 29 +- src/xpdf-4.04/xpdf/PDF417Barcode.cc | 4 - src/xpdf-4.04/xpdf/PDF417Barcode.h | 4 - src/xpdf-4.04/xpdf/PDFCore.cc | 138 +- src/xpdf-4.04/xpdf/PDFCore.h | 50 +- src/xpdf-4.04/xpdf/PDFDoc.cc | 29 +- src/xpdf-4.04/xpdf/PDFDoc.h | 21 +- src/xpdf-4.04/xpdf/PSOutputDev.cc | 426 +++-- src/xpdf-4.04/xpdf/PSOutputDev.h | 25 +- src/xpdf-4.04/xpdf/PSTokenizer.cc | 4 - src/xpdf-4.04/xpdf/PSTokenizer.h | 4 - src/xpdf-4.04/xpdf/Page.cc | 52 +- src/xpdf-4.04/xpdf/Page.h | 12 +- src/xpdf-4.04/xpdf/Parser.cc | 22 +- src/xpdf-4.04/xpdf/Parser.h | 10 +- src/xpdf-4.04/xpdf/PreScanOutputDev.cc | 4 - src/xpdf-4.04/xpdf/PreScanOutputDev.h | 4 - src/xpdf-4.04/xpdf/SecurityHandler.cc | 6 +- src/xpdf-4.04/xpdf/SecurityHandler.h | 4 - src/xpdf-4.04/xpdf/ShadingImage.cc | 102 +- src/xpdf-4.04/xpdf/ShadingImage.h | 69 +- src/xpdf-4.04/xpdf/SplashOutputDev.cc | 1983 +++++++++++++--------- src/xpdf-4.04/xpdf/SplashOutputDev.h | 64 +- src/xpdf-4.04/xpdf/Stream.cc | 48 +- src/xpdf-4.04/xpdf/Stream.h | 15 +- src/xpdf-4.04/xpdf/TextOutputDev.cc | 880 +++++++--- src/xpdf-4.04/xpdf/TextOutputDev.h | 49 +- src/xpdf-4.04/xpdf/TextString.cc | 4 - src/xpdf-4.04/xpdf/TextString.h | 4 - src/xpdf-4.04/xpdf/TileCache.cc | 10 +- src/xpdf-4.04/xpdf/TileCache.h | 4 - src/xpdf-4.04/xpdf/TileCompositor.cc | 4 - src/xpdf-4.04/xpdf/TileCompositor.h | 4 - src/xpdf-4.04/xpdf/TileMap.cc | 20 +- src/xpdf-4.04/xpdf/TileMap.h | 4 - src/xpdf-4.04/xpdf/UnicodeMap.cc | 4 - src/xpdf-4.04/xpdf/UnicodeMap.h | 4 - src/xpdf-4.04/xpdf/UnicodeRemapping.cc | 8 +- src/xpdf-4.04/xpdf/UnicodeRemapping.h | 4 - src/xpdf-4.04/xpdf/UnicodeTypeTable.cc | 132 +- src/xpdf-4.04/xpdf/UnicodeTypeTable.h | 2 + src/xpdf-4.04/xpdf/WebFont.cc | 6 +- src/xpdf-4.04/xpdf/WebFont.h | 4 - src/xpdf-4.04/xpdf/XFAScanner.cc | 21 +- src/xpdf-4.04/xpdf/XFAScanner.h | 12 +- src/xpdf-4.04/xpdf/XRef.cc | 122 +- src/xpdf-4.04/xpdf/XRef.h | 11 +- src/xpdf-4.04/xpdf/Zoox.cc | 12 +- src/xpdf-4.04/xpdf/Zoox.h | 5 +- src/xpdf-4.04/xpdf/config.h | 29 +- src/xpdf-4.04/xpdf/pdfdetach.cc | 22 +- src/xpdf-4.04/xpdf/pdffonts.cc | 31 +- src/xpdf-4.04/xpdf/pdfimages.cc | 41 +- src/xpdf-4.04/xpdf/pdfinfo.cc | 72 +- src/xpdf-4.04/xpdf/pdftohtml.cc | 147 +- src/xpdf-4.04/xpdf/pdftopng.cc | 24 +- src/xpdf-4.04/xpdf/pdftoppm.cc | 24 +- src/xpdf-4.04/xpdf/pdftops.cc | 28 +- src/xpdf-4.04/xpdf/pdftotext.cc | 24 +- 117 files changed, 6126 insertions(+), 2805 deletions(-) create mode 100644 src/xpdf-4.04/xpdf/LocalParams.cc create mode 100644 src/xpdf-4.04/xpdf/LocalParams.h diff --git a/src/xpdf-4.04/xpdf/AcroForm.cc b/src/xpdf-4.04/xpdf/AcroForm.cc index 695c286..5c417e5 100644 --- a/src/xpdf-4.04/xpdf/AcroForm.cc +++ b/src/xpdf-4.04/xpdf/AcroForm.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -343,8 +339,12 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { AcroForm *acroForm; AcroFormField *field; Object xfaObj, fieldsObj, annotsObj, annotRef, annotObj, obj1, obj2; + char *touchedObjs; int pageNum, i, j; + touchedObjs = (char *)gmalloc(docA->getXRef()->getNumObjects()); + memset(touchedObjs, 0, docA->getXRef()->getNumObjects()); + // this is the normal case: acroFormObj is a dictionary, as expected if (acroFormObjA->isDict()) { acroForm = new AcroForm(docA, acroFormObjA); @@ -372,11 +372,12 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { } obj1.free(); delete acroForm; + gfree(touchedObjs); return NULL; } for (i = 0; i < obj1.arrayGetLength(); ++i) { obj1.arrayGetNF(i, &obj2); - acroForm->scanField(&obj2); + acroForm->scanField(&obj2, touchedObjs); obj2.free(); } obj1.free(); @@ -400,7 +401,7 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { annotRef.fetch(acroForm->doc->getXRef(), &annotObj); if (annotObj.isDict()) { if (annotObj.dictLookup("Subtype", &obj1)->isName("Widget")) { - acroForm->scanField(&annotRef); + acroForm->scanField(&annotRef, touchedObjs); } obj1.free(); } @@ -431,7 +432,7 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { annotRef.fetch(acroForm->doc->getXRef(), &annotObj); if (annotObj.isDict()) { if (annotObj.dictLookup("Subtype", &obj1)->isName("Widget")) { - acroForm->scanField(&annotRef); + acroForm->scanField(&annotRef, touchedObjs); } obj1.free(); } @@ -449,6 +450,8 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { } } + gfree(touchedObjs); + return acroForm; } @@ -512,34 +515,51 @@ int AcroForm::lookupAnnotPage(Object *annotRef) { return 0; } -void AcroForm::scanField(Object *fieldRef) { - int startDepth = depth; - depth++; +void AcroForm::scanField(Object *fieldRef, char *touchedObjs) { AcroFormField *field; - Object fieldObj, kidsObj, kidRef, kidObj, subtypeObj; + Object fieldObj, kidsRef, kidsObj, kidRef, kidObj, subtypeObj; GBool isTerminal; int i; - if (depth > maxDepth) { - error(errInternal, -1, "Recursion depth exceeded"); - depth = startDepth; - return; + // check for an object loop + if (fieldRef->isRef()) { + if (fieldRef->getRefNum() < 0 || + fieldRef->getRefNum() >= doc->getXRef()->getNumObjects() || + touchedObjs[fieldRef->getRefNum()]) { + return; + } + touchedObjs[fieldRef->getRefNum()] = 1; } fieldRef->fetch(doc->getXRef(), &fieldObj); if (!fieldObj.isDict()) { error(errSyntaxError, -1, "AcroForm field object is wrong type"); fieldObj.free(); - depth = startDepth; return; } + // look for a Kids entry, and check for an object loop there + if (fieldObj.dictLookupNF("Kids", &kidsRef)->isRef()) { + if (kidsRef.getRefNum() < 0 || + kidsRef.getRefNum() >= doc->getXRef()->getNumObjects() || + touchedObjs[kidsRef.getRefNum()]) { + kidsRef.free(); + fieldObj.free(); + return; + } + touchedObjs[kidsRef.getRefNum()] = 1; + kidsRef.fetch(doc->getXRef(), &kidsObj); + } else { + kidsRef.copy(&kidsObj); + } + kidsRef.free(); + // if this field has a Kids array, and all of the kids have a Parent // reference (i.e., they're all form fields, not widget // annotations), then this is a non-terminal field, and we need to // scan the kids isTerminal = gTrue; - if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + if (kidsObj.isArray()) { isTerminal = gFalse; for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { kidsObj.arrayGet(i, &kidObj); @@ -554,7 +574,7 @@ void AcroForm::scanField(Object *fieldRef) { if (!isTerminal) { for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { kidsObj.arrayGetNF(i, &kidRef); - scanField(&kidRef); + scanField(&kidRef, touchedObjs); kidRef.free(); } } @@ -568,7 +588,6 @@ void AcroForm::scanField(Object *fieldRef) { } fieldObj.free(); - depth = startDepth; } void AcroForm::draw(int pageNum, Gfx *gfx, GBool printing) { @@ -870,7 +889,7 @@ Unicode *AcroFormField::getValue(int *length) { // if this field has a counterpart in the XFA form, take the value // from the XFA field (NB: an XFA field with no value overrides the // AcroForm value) - if (xfaField) { + if (globalParams->getPreferXFAFieldValues() && xfaField) { if (xfaField->getValue()) { u = utf8ToUnicode(xfaField->getValue(), length); } @@ -2043,21 +2062,18 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict, wMax = dx - 2 * border - 4; -#if 1 //~tmp // this is a kludge that appears to match Adobe's behavior if (height > 15) { topBorder = 5; } else { topBorder = 2; } -#else - topBorder = 5; -#endif // compute font autosize if (fontSize == 0) { for (fontSize = 10; fontSize > 1; --fontSize) { yy = dy - topBorder; + w = 0; i = 0; while (i < text2->getLength()) { getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k); @@ -2190,6 +2206,18 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict, // comb formatting if (comb > 0) { + // Acrobat apparently reduces the field width by the sum of the + // left and right margins (but doesn't shift the text to the + // right at all) -- I'm not really sure what's going on here + // (maybe a bug in Acrobat?), but rendering SSN fields in tax + // forms depends on this. + if (xfaField) { + XFAFieldLayoutInfo *layoutInfo = xfaField->getLayoutInfo(); + if (layoutInfo) { + dx -= layoutInfo->marginLeft + layoutInfo->marginRight; + } + } + // compute comb spacing w = dx / comb; @@ -3193,7 +3221,7 @@ GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, return gFalse; } for (int i = 0; i < unicodeLength; ++i) { - if ((s->getChar(i) & 0xff) != u[i]) { + if ((Unicode)(s->getChar(i) & 0xff) != u[i]) { return gFalse; } } @@ -3203,7 +3231,7 @@ GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, const char *s) { for (int i = 0; i < unicodeLength; ++i) { - if (!s[i] || (s[i] & 0xff) != u[i]) { + if (!s[i] || (Unicode)(s[i] & 0xff) != u[i]) { return gFalse; } } diff --git a/src/xpdf-4.04/xpdf/AcroForm.h b/src/xpdf-4.04/xpdf/AcroForm.h index b43e46d..0e922d1 100644 --- a/src/xpdf-4.04/xpdf/AcroForm.h +++ b/src/xpdf-4.04/xpdf/AcroForm.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class TextString; class Gfx; class GfxFont; @@ -47,10 +43,7 @@ class AcroForm { AcroForm(PDFDoc *docA, Object *acroFormObjA); void buildAnnotPageList(Catalog *catalog); int lookupAnnotPage(Object *annotRef); - void scanField(Object *fieldRef); - - int depth = 0; - int maxDepth = 100; + void scanField(Object *fieldRef, char *touchedObjs); PDFDoc *doc; Object acroFormObj; diff --git a/src/xpdf-4.04/xpdf/Annot.cc b/src/xpdf-4.04/xpdf/Annot.cc index 82ef600..1f39f46 100644 --- a/src/xpdf-4.04/xpdf/Annot.cc +++ b/src/xpdf-4.04/xpdf/Annot.cc @@ -2,18 +2,15 @@ // // Annot.cc // -// Copyright 2000-2003 Glyph & Cog, LLC +// Copyright 2000-2022 Glyph & Cog, LLC // //======================================================================== #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include +#include #include "gmem.h" #include "gmempp.h" #include "GList.h" @@ -278,6 +275,8 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { obj3.free(); } else if (obj2.isRef()) { obj2.copy(&appearance); + } else if (obj2.isStream()) { + obj2.copy(&appearance); } obj1.free(); obj2.free(); @@ -306,29 +305,48 @@ Annot::~Annot() { ocObj.free(); } -void Annot::generateAnnotAppearance() { +void Annot::generateAnnotAppearance(Object *annotObj) { Object obj; - appearance.fetch(doc->getXRef(), &obj); - if (!obj.isStream()) { - if (type) { - if (!type->cmp("Line")) { - generateLineAppearance(); - } else if (!type->cmp("PolyLine")) { - generatePolyLineAppearance(); - } else if (!type->cmp("Polygon")) { - generatePolygonAppearance(); - } else if (!type->cmp("FreeText")) { - generateFreeTextAppearance(); - } - } - } + GBool alreadyHaveAppearance = obj.isStream(); obj.free(); + if (alreadyHaveAppearance) { + return; + } + + if (!type || (type->cmp("Line") && + type->cmp("PolyLine") && + type->cmp("Polygon") && + type->cmp("FreeText"))) { + return; + } + + Object annotObj2; + if (!annotObj) { + getObject(&annotObj2); + annotObj = &annotObj2; + } + if (!annotObj->isDict()) { + annotObj2.free(); + return; + } + + if (!type->cmp("Line")) { + generateLineAppearance(annotObj); + } else if (!type->cmp("PolyLine")) { + generatePolyLineAppearance(annotObj); + } else if (!type->cmp("Polygon")) { + generatePolygonAppearance(annotObj); + } else if (!type->cmp("FreeText")) { + generateFreeTextAppearance(annotObj); + } + + annotObj2.free(); } //~ this doesn't draw the caption -void Annot::generateLineAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generateLineAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; MemStream *appearStream; double x1, y1, x2, y2, dx, dy, len, w; double lx1, ly1, lx2, ly2; @@ -339,15 +357,10 @@ void Annot::generateLineAppearance() { AnnotLineEndType lineEnd1, lineEnd2; GBool fill; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -358,7 +371,7 @@ void Annot::generateLineAppearance() { setLineStyle(borderStyle, &w); setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); fill = gFalse; - if (annotObj.dictLookup("IC", &obj1)->isArray()) { + if (annotObj->dictLookup("IC", &obj1)->isArray()) { if (setFillColor(&obj1)) { fill = gTrue; } @@ -366,14 +379,14 @@ void Annot::generateLineAppearance() { obj1.free(); //----- get line properties - if (annotObj.dictLookup("L", &obj1)->isArray() && + if (annotObj->dictLookup("L", &obj1)->isArray() && obj1.arrayGetLength() == 4) { if (obj1.arrayGet(0, &obj2)->isNum()) { x1 = obj2.getNum(); } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); if (obj1.arrayGet(1, &obj2)->isNum()) { @@ -381,7 +394,7 @@ void Annot::generateLineAppearance() { } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); if (obj1.arrayGet(2, &obj2)->isNum()) { @@ -389,7 +402,7 @@ void Annot::generateLineAppearance() { } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); if (obj1.arrayGet(3, &obj2)->isNum()) { @@ -397,16 +410,16 @@ void Annot::generateLineAppearance() { } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); } else { obj1.free(); - goto err1; + return; } obj1.free(); lineEnd1 = lineEnd2 = annotLineEndNone; - if (annotObj.dictLookup("LE", &obj1)->isArray() && + if (annotObj->dictLookup("LE", &obj1)->isArray() && obj1.arrayGetLength() == 2) { lineEnd1 = parseLineEndType(obj1.arrayGet(0, &obj2)); obj2.free(); @@ -414,19 +427,19 @@ void Annot::generateLineAppearance() { obj2.free(); } obj1.free(); - if (annotObj.dictLookup("LL", &obj1)->isNum()) { + if (annotObj->dictLookup("LL", &obj1)->isNum()) { leaderLen = obj1.getNum(); } else { leaderLen = 0; } obj1.free(); - if (annotObj.dictLookup("LLE", &obj1)->isNum()) { + if (annotObj->dictLookup("LLE", &obj1)->isNum()) { leaderExtLen = obj1.getNum(); } else { leaderExtLen = 0; } obj1.free(); - if (annotObj.dictLookup("LLO", &obj1)->isNum()) { + if (annotObj->dictLookup("LLO", &obj1)->isNum()) { leaderOffLen = obj1.getNum(); } else { leaderOffLen = 0; @@ -513,27 +526,19 @@ void Annot::generateLineAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - err1: - annotObj.free(); } //~ this doesn't handle line ends (arrows) -void Annot::generatePolyLineAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generatePolyLineAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; MemStream *appearStream; double x1, y1, w; int i; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -544,7 +549,7 @@ void Annot::generatePolyLineAppearance() { setLineStyle(borderStyle, &w); setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); // fill = gFalse; - // if (annotObj.dictLookup("IC", &obj1)->isArray()) { + // if (annotObj->dictLookup("IC", &obj1)->isArray()) { // if (setFillColor(&obj1)) { // fill = gTrue; // } @@ -552,22 +557,22 @@ void Annot::generatePolyLineAppearance() { // obj1.free(); //----- draw line - if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + if (!annotObj->dictLookup("Vertices", &obj1)->isArray()) { obj1.free(); - goto err1; + return; } for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { if (!obj1.arrayGet(i, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } x1 = obj2.getNum(); obj2.free(); if (!obj1.arrayGet(i+1, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } y1 = obj2.getNum(); obj2.free(); @@ -606,26 +611,18 @@ void Annot::generatePolyLineAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - err1: - annotObj.free(); } -void Annot::generatePolygonAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generatePolygonAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; MemStream *appearStream; double x1, y1; int i; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -633,30 +630,30 @@ void Annot::generatePolygonAppearance() { obj1.free(); //----- set fill color - if (!annotObj.dictLookup("IC", &obj1)->isArray() || + if (!annotObj->dictLookup("IC", &obj1)->isArray() || !setFillColor(&obj1)) { obj1.free(); - goto err1; + return; } obj1.free(); //----- fill polygon - if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + if (!annotObj->dictLookup("Vertices", &obj1)->isArray()) { obj1.free(); - goto err1; + return; } for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { if (!obj1.arrayGet(i, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } x1 = obj2.getNum(); obj2.free(); if (!obj1.arrayGet(i+1, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } y1 = obj2.getNum(); obj2.free(); @@ -695,31 +692,23 @@ void Annot::generatePolygonAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - err1: - annotObj.free(); } //~ this doesn't handle rich text //~ this doesn't handle the callout //~ this doesn't handle the RD field -void Annot::generateFreeTextAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generateFreeTextAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; Object resources, gsResources, fontResources, defaultFont; GString *text, *da; double lineWidth; int quadding, rot; MemStream *appearStream; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -727,19 +716,19 @@ void Annot::generateFreeTextAppearance() { obj1.free(); //----- draw the text - if (annotObj.dictLookup("Contents", &obj1)->isString()) { + if (annotObj->dictLookup("Contents", &obj1)->isString()) { text = obj1.getString()->copy(); } else { text = new GString(); } obj1.free(); - if (annotObj.dictLookup("Q", &obj1)->isInt()) { + if (annotObj->dictLookup("Q", &obj1)->isInt()) { quadding = obj1.getInt(); } else { quadding = 0; } obj1.free(); - if (annotObj.dictLookup("DA", &obj1)->isString()) { + if (annotObj->dictLookup("DA", &obj1)->isString()) { da = obj1.getString()->copy(); } else { da = new GString(); @@ -747,7 +736,7 @@ void Annot::generateFreeTextAppearance() { obj1.free(); // the "Rotate" field is not defined in the PDF spec, but Acrobat // looks at it - if (annotObj.dictLookup("Rotate", &obj1)->isInt()) { + if (annotObj->dictLookup("Rotate", &obj1)->isInt()) { rot = obj1.getInt(); } else { rot = 0; @@ -797,8 +786,6 @@ void Annot::generateFreeTextAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - annotObj.free(); } void Annot::setLineStyle(AnnotBorderStyle *bs, double *lineWidth) { @@ -1344,105 +1331,219 @@ Object *Annot::getObject(Object *obj) { } //------------------------------------------------------------------------ -// Annots +// PageAnnots //------------------------------------------------------------------------ -Annots::Annots(PDFDoc *docA, Object *annotsObj) { - Annot *annot; - Object obj1, obj2; - Ref ref; - GBool drawWidgetAnnots; - int size; - int i; +class PageAnnots { +public: + + PageAnnots(); + ~PageAnnots(); + GList *annots; // list of annots on the page [Annot] + GBool appearancesGenerated; // set after appearances have been generated +}; + +PageAnnots::PageAnnots() { + annots = new GList(); + appearancesGenerated = gFalse; +} + +PageAnnots::~PageAnnots() { + deleteGList(annots, Annot); +} + +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +Annots::Annots(PDFDoc *docA) { doc = docA; - annots = NULL; - size = 0; - nAnnots = 0; - - if (annotsObj->isArray()) { - // Kludge: some PDF files define an empty AcroForm, but still - // include Widget-type annotations -- in that case, we want to - // draw the widgets (since the form code won't). This really - // ought to look for Widget-type annotations that are not included - // in any form field. - drawWidgetAnnots = !doc->getCatalog()->getForm() || - doc->getCatalog()->getForm()->getNumFields() == 0; - for (i = 0; i < annotsObj->arrayGetLength(); ++i) { - if (annotsObj->arrayGetNF(i, &obj1)->isRef()) { - ref = obj1.getRef(); - obj1.free(); - annotsObj->arrayGet(i, &obj1); - } else { - ref.num = ref.gen = -1; - } - if (obj1.isDict()) { - if (drawWidgetAnnots || - !obj1.dictLookup("Subtype", &obj2)->isName("Widget")) { - annot = new Annot(doc, obj1.getDict(), &ref); - if (annot->isOk()) { - if (nAnnots >= size) { - size += 16; - annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); - } - annots[nAnnots++] = annot; - } else { - delete annot; - } - } - obj2.free(); - } - obj1.free(); + pageAnnots = (PageAnnots **)gmallocn(doc->getNumPages(), sizeof(PageAnnots*)); + for (int page = 1; page <= doc->getNumPages(); ++page) { + pageAnnots[page - 1] = NULL; + } + formFieldRefsSize = 0; + formFieldRefs = NULL; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +Annots::~Annots() { + for (int page = 1; page <= doc->getNumPages(); ++page) { + delete pageAnnots[page - 1]; + } + gfree(pageAnnots); + gfree(formFieldRefs); +#if MULTITHREADED + gDestroyMutex(&mutex); +#endif +} + +void Annots::loadAnnots(int page) { +#if MULTITHREADED + gLockMutex(&mutex); +#endif + if (pageAnnots[page - 1]) { +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + return; + } + + pageAnnots[page - 1] = new PageAnnots(); + + Object annotsObj; + doc->getCatalog()->getPage(page)->getAnnots(&annotsObj); + if (!annotsObj.isArray()) { + annotsObj.free(); +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + return; + } + + loadFormFieldRefs(); + + for (int i = 0; i < annotsObj.arrayGetLength(); ++i) { + Object annotObj; + Ref annotRef; + if (annotsObj.arrayGetNF(i, &annotObj)->isRef()) { + annotRef = annotObj.getRef(); + annotObj.free(); + annotsObj.arrayGet(i, &annotObj); + } else { + annotRef.num = annotRef.gen = -1; + } + if (!annotObj.isDict()) { + annotObj.free(); + continue; + } + + // skip any annotations which are used as AcroForm fields -- + // they'll be rendered by the AcroForm module + if (annotRef.num >= 0 && annotRef.num < formFieldRefsSize && + formFieldRefs[annotRef.num]) { + annotObj.free(); + continue; + } + + Annot *annot = new Annot(doc, annotObj.getDict(), &annotRef); + annotObj.free(); + if (annot->isOk()) { + pageAnnots[page - 1]->annots->append(annot); + } else { + delete annot; } } + + annotsObj.free(); + +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif } -Annots::~Annots() { - int i; +// Build a set of object refs for AcroForm fields. +void Annots::loadFormFieldRefs() { + if (formFieldRefs) { + return; + } - for (i = 0; i < nAnnots; ++i) { - delete annots[i]; + AcroForm *form = doc->getCatalog()->getForm(); + if (!form) { + return; + } + + int newFormFieldRefsSize = 256; + for (int i = 0; i < form->getNumFields(); ++i) { + AcroFormField *field = form->getField(i); + Object fieldRef; + field->getFieldRef(&fieldRef); + if (fieldRef.isRef()) { + if (fieldRef.getRefNum() >= formFieldRefsSize) { + while (fieldRef.getRefNum() >= newFormFieldRefsSize && + newFormFieldRefsSize <= INT_MAX / 2) { + newFormFieldRefsSize *= 2; + } + if (fieldRef.getRefNum() >= newFormFieldRefsSize) { + continue; + } + formFieldRefs = (char *)grealloc(formFieldRefs, newFormFieldRefsSize); + for (int j = formFieldRefsSize; j < newFormFieldRefsSize; ++j) { + formFieldRefs[j] = (char)0; + } + formFieldRefsSize = newFormFieldRefsSize; + } + formFieldRefs[fieldRef.getRefNum()] = (char)1; + } + fieldRef.free(); } - gfree(annots); } -Annot *Annots::find(double x, double y) { - int i; +int Annots::getNumAnnots(int page) { + loadAnnots(page); + return pageAnnots[page - 1]->annots->getLength(); +} + +Annot *Annots::getAnnot(int page, int idx) { + loadAnnots(page); + return (Annot *)pageAnnots[page - 1]->annots->get(idx); +} - for (i = nAnnots - 1; i >= 0; --i) { - if (annots[i]->inRect(x, y)) { - return annots[i]; +Annot *Annots::find(int page, double x, double y) { + loadAnnots(page); + PageAnnots *pa = pageAnnots[page - 1]; + for (int i = pa->annots->getLength() - 1; i >= 0; --i) { + Annot *annot = (Annot *)pa->annots->get(i); + if (annot->inRect(x, y)) { + return annot; } } return NULL; } -int Annots::findIdx(double x, double y) { - int i; - - for (i = nAnnots - 1; i >= 0; --i) { - if (annots[i]->inRect(x, y)) { +int Annots::findIdx(int page, double x, double y) { + loadAnnots(page); + PageAnnots *pa = pageAnnots[page - 1]; + for (int i = pa->annots->getLength() - 1; i >= 0; --i) { + Annot *annot = (Annot *)pa->annots->get(i); + if (annot->inRect(x, y)) { return i; } } return -1; } -void Annots::generateAnnotAppearances() { - int i; - - for (i = 0; i < nAnnots; ++i) { - annots[i]->generateAnnotAppearance(); +void Annots::add(int page, Object *annotObj) { + if (!annotObj->isDict()) { + return; + } + Ref annotRef = {-1, -1}; + Annot *annot = new Annot(doc, annotObj->getDict(), &annotRef); + if (annot->isOk()) { + annot->generateAnnotAppearance(annotObj); + pageAnnots[page - 1]->annots->append(annot); + } else { + delete annot; } } -Annot *Annots::findAnnot(Ref *ref) { - int i; - - for (i = 0; i < nAnnots; ++i) { - if (annots[i]->match(ref)) { - return annots[i]; +void Annots::generateAnnotAppearances(int page) { + loadAnnots(page); + PageAnnots *pa = pageAnnots[page - 1]; +#if MULTITHREADED + gLockMutex(&mutex); +#endif + if (!pa->appearancesGenerated) { + for (int i = 0; i < pa->annots->getLength(); ++i) { + Annot *annot = (Annot *)pa->annots->get(i); + annot->generateAnnotAppearance(NULL); } + pa->appearancesGenerated = gTrue; } - return NULL; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif } diff --git a/src/xpdf-4.04/xpdf/Annot.h b/src/xpdf-4.04/xpdf/Annot.h index 6ba5ff4..6ae89da 100644 --- a/src/xpdf-4.04/xpdf/Annot.h +++ b/src/xpdf-4.04/xpdf/Annot.h @@ -2,7 +2,7 @@ // // Annot.h // -// Copyright 2000-2003 Glyph & Cog, LLC +// Copyright 2000-2022 Glyph & Cog, LLC // //======================================================================== @@ -10,9 +10,8 @@ #define ANNOT_H #include - -#ifdef USE_GCC_PRAGMAS -#pragma interface +#if MULTITHREADED +#include "GMutex.h" #endif class XRef; @@ -20,6 +19,7 @@ class Catalog; class Gfx; class GfxFontDict; class PDFDoc; +class PageAnnots; //------------------------------------------------------------------------ // AnnotBorderStyle @@ -105,14 +105,14 @@ class Annot { GBool match(Ref *refA) { return ref.num == refA->num && ref.gen == refA->gen; } - void generateAnnotAppearance(); + void generateAnnotAppearance(Object *annotObj); private: - void generateLineAppearance(); - void generatePolyLineAppearance(); - void generatePolygonAppearance(); - void generateFreeTextAppearance(); + void generateLineAppearance(Object *annotObj); + void generatePolyLineAppearance(Object *annotObj); + void generatePolygonAppearance(Object *annotObj); + void generateFreeTextAppearance(Object *annotObj); void setLineStyle(AnnotBorderStyle *bs, double *lineWidth); void setStrokeColor(double *color, int nComps); GBool setFillColor(Object *colorObj); @@ -152,34 +152,38 @@ class Annot { class Annots { public: - // Build a list of Annot objects. - Annots(PDFDoc *docA, Object *annotsObj); + Annots(PDFDoc *docA); ~Annots(); - // Iterate through list of annotations. - int getNumAnnots() { return nAnnots; } - Annot *getAnnot(int i) { return annots[i]; } + // Iterate over annotations on a specific page. + int getNumAnnots(int page); + Annot *getAnnot(int page, int idx); + + // If point (,) is in an annotation, return the associated + // annotation (or annotation index); else return NULL (or -1). + Annot *find(int page, double x, double y); + int findIdx(int page, double x, double y); - // If point , is in an annotation, return the associated - // annotation; else return NULL. - Annot *find(double x, double y); - int findIdx(double x, double y); + // Add an annotation [annotObj] on page [page]. + void add(int page, Object *annotObj); // Generate an appearance stream for any non-form-field annotation - // that is missing it. - void generateAnnotAppearances(); + // on the specified page that is missing an appearance. + void generateAnnotAppearances(int page); private: - void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent, - Dict *acroForm); - - Annot *findAnnot(Ref *ref); + void loadAnnots(int page); + void loadFormFieldRefs(); PDFDoc *doc; - Annot **annots; - int nAnnots; + PageAnnots **pageAnnots; // list of annots for each page + int formFieldRefsSize; // number of entries in formFieldRefs[] + char *formFieldRefs; // set of AcroForm field refs +#if MULTITHREADED + GMutex mutex; +#endif }; #endif diff --git a/src/xpdf-4.04/xpdf/Array.cc b/src/xpdf-4.04/xpdf/Array.cc index 2bf948e..2771186 100644 --- a/src/xpdf-4.04/xpdf/Array.cc +++ b/src/xpdf-4.04/xpdf/Array.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -53,7 +49,7 @@ void Array::add(Object *elem) { Object *Array::get(int i, Object *obj, int recursion) { if (i < 0 || i >= length) { -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM abort(); #else return obj->initNull(); @@ -64,7 +60,7 @@ Object *Array::get(int i, Object *obj, int recursion) { Object *Array::getNF(int i, Object *obj) { if (i < 0 || i >= length) { -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM abort(); #else return obj->initNull(); diff --git a/src/xpdf-4.04/xpdf/Array.h b/src/xpdf-4.04/xpdf/Array.h index 8d10ead..9a887f4 100644 --- a/src/xpdf-4.04/xpdf/Array.h +++ b/src/xpdf-4.04/xpdf/Array.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #if MULTITHREADED #include "GMutex.h" #endif diff --git a/src/xpdf-4.04/xpdf/BuiltinFont.cc b/src/xpdf-4.04/xpdf/BuiltinFont.cc index d2f875e..51c2d33 100644 --- a/src/xpdf-4.04/xpdf/BuiltinFont.cc +++ b/src/xpdf-4.04/xpdf/BuiltinFont.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" diff --git a/src/xpdf-4.04/xpdf/BuiltinFont.h b/src/xpdf-4.04/xpdf/BuiltinFont.h index f24cbf9..042e4e0 100644 --- a/src/xpdf-4.04/xpdf/BuiltinFont.h +++ b/src/xpdf-4.04/xpdf/BuiltinFont.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" struct BuiltinFont; diff --git a/src/xpdf-4.04/xpdf/CMakeLists.txt b/src/xpdf-4.04/xpdf/CMakeLists.txt index 63a8dec..a965cd7 100644 --- a/src/xpdf-4.04/xpdf/CMakeLists.txt +++ b/src/xpdf-4.04/xpdf/CMakeLists.txt @@ -53,6 +53,7 @@ add_library(xpdf_objs OBJECT JPXStream.cc Lexer.cc Link.cc + LocalParams.cc NameToCharCode.cc Object.cc OptionalContent.cc diff --git a/src/xpdf-4.04/xpdf/CMap.cc b/src/xpdf-4.04/xpdf/CMap.cc index 12632c5..31e2a27 100644 --- a/src/xpdf-4.04/xpdf/CMap.cc +++ b/src/xpdf-4.04/xpdf/CMap.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -20,6 +16,7 @@ #include "gmempp.h" #include "gfile.h" #include "GString.h" +#include "GHash.h" #include "Error.h" #include "GlobalParams.h" #include "PSTokenizer.h" @@ -49,7 +46,8 @@ static int getCharFromStream(void *data) { //------------------------------------------------------------------------ -CMap *CMap::parse(CMapCache *cache, GString *collectionA, Object *obj) { +CMap *CMap::parse(CMapCache *cache, GString *collectionA, Object *obj, + GHash *usedCMaps) { CMap *cMap; GString *cMapNameA; @@ -62,9 +60,17 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA, Object *obj) { } delete cMapNameA; } else if (obj->isStream()) { - if (!(cMap = CMap::parse(NULL, collectionA, obj->getStream()))) { + GHash *newUsedCMaps = NULL; + if (!usedCMaps) { + usedCMaps = newUsedCMaps = new GHash(gTrue); + } + if (!(cMap = CMap::parse(NULL, collectionA, obj->getStream(), + usedCMaps))) { error(errSyntaxError, -1, "Invalid CMap in Type 0 font"); } + if (newUsedCMaps) { + delete newUsedCMaps; + } } else { error(errSyntaxError, -1, "Invalid Encoding in Type 0 font"); return NULL; @@ -73,7 +79,7 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA, Object *obj) { } CMap *CMap::parse(CMapCache *cache, GString *collectionA, - GString *cMapNameA) { + GString *cMapNameA, GHash *usedCMaps) { FILE *f; CMap *cMap; @@ -93,32 +99,60 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA, return NULL; } + GHash *newUsedCMaps = NULL; + if (!usedCMaps) { + usedCMaps = newUsedCMaps = new GHash(gTrue); + } + cMap = new CMap(collectionA->copy(), cMapNameA->copy()); - cMap->parse2(cache, &getCharFromFile, f); + cMap->parse2(cache, &getCharFromFile, f, usedCMaps); + + if (newUsedCMaps) { + delete newUsedCMaps; + } fclose(f); return cMap; } -CMap *CMap::parse(CMapCache *cache, GString *collectionA, Stream *str) { +CMap *CMap::parse(CMapCache *cache, GString *collectionA, Stream *str, + GHash *usedCMaps) { Object obj1; CMap *cMap; + // check for a loop + if (usedCMaps) { + GString *name; + if (str->getDict()->lookup("CMapName", &obj1)->isName()) { + name = new GString(obj1.getName()); + } else { + name = new GString(); + } + obj1.free(); + if (usedCMaps->lookupInt(name)) { + error(errSyntaxError, -1, "Loop in usecmap"); + delete name; + return NULL; + } + usedCMaps->add(name, 1); + } + cMap = new CMap(collectionA->copy(), NULL); if (!str->getDict()->lookup("UseCMap", &obj1)->isNull()) { - cMap->useCMap(cache, &obj1); + cMap->useCMap(cache, &obj1, usedCMaps); } obj1.free(); str->reset(); - cMap->parse2(cache, &getCharFromStream, str); + cMap->parse2(cache, &getCharFromStream, str, usedCMaps); str->close(); return cMap; } -void CMap::parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data) { +void CMap::parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data, + GHash *usedCMaps) { PSTokenizer *pst; char tok1[256], tok2[256], tok3[256]; int n1, n2, n3; @@ -129,7 +163,7 @@ void CMap::parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data) { while (pst->getToken(tok2, sizeof(tok2), &n2)) { if (!strcmp(tok2, "usecmap")) { if (tok1[0] == '/') { - useCMap(cache, tok1 + 1); + useCMap(cache, tok1 + 1, usedCMaps); } pst->getToken(tok1, sizeof(tok1), &n1); } else if (!strcmp(tok1, "/WMode")) { @@ -212,17 +246,25 @@ CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) { refCnt = 1; } -void CMap::useCMap(CMapCache *cache, char *useName) { +void CMap::useCMap(CMapCache *cache, char *useName, GHash *usedCMaps) { GString *useNameStr; CMap *subCMap; + // check for a loop + if (usedCMaps) { + if (usedCMaps->lookupInt(useName)) { + error(errSyntaxError, -1, "Loop in usecmap"); + return; + } + usedCMaps->add(new GString(useName), 1); + } + useNameStr = new GString(useName); // if cache is non-NULL, we already have a lock, and we can use // CMapCache::getCMap() directly; otherwise, we need to use - // GlobalParams::getCMap() in order to acqure the lock need to use - // GlobalParams::getCMap + // GlobalParams::getCMap() in order to acqure the lock if (cache) { - subCMap = cache->getCMap(collection, useNameStr); + subCMap = cache->getCMap(collection, useNameStr, usedCMaps); } else { subCMap = globalParams->getCMap(collection, useNameStr); } @@ -237,10 +279,10 @@ void CMap::useCMap(CMapCache *cache, char *useName) { subCMap->decRefCnt(); } -void CMap::useCMap(CMapCache *cache, Object *obj) { +void CMap::useCMap(CMapCache *cache, Object *obj, GHash *usedCMaps) { CMap *subCMap; - subCMap = CMap::parse(cache, collection, obj); + subCMap = CMap::parse(cache, collection, obj, usedCMaps); if (!subCMap) { return; } @@ -406,7 +448,8 @@ CMapCache::~CMapCache() { } } -CMap *CMapCache::getCMap(GString *collection, GString *cMapName) { +CMap *CMapCache::getCMap(GString *collection, GString *cMapName, + GHash *usedCMaps) { CMap *cmap; int i, j; @@ -425,7 +468,7 @@ CMap *CMapCache::getCMap(GString *collection, GString *cMapName) { return cmap; } } - if ((cmap = CMap::parse(this, collection, cMapName))) { + if ((cmap = CMap::parse(this, collection, cMapName, usedCMaps))) { if (cache[cMapCacheSize - 1]) { cache[cMapCacheSize - 1]->decRefCnt(); } diff --git a/src/xpdf-4.04/xpdf/CMap.h b/src/xpdf-4.04/xpdf/CMap.h index 55692b4..8a65575 100644 --- a/src/xpdf-4.04/xpdf/CMap.h +++ b/src/xpdf-4.04/xpdf/CMap.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "CharTypes.h" @@ -23,6 +19,7 @@ #endif class GString; +class GHash; class Object; class Stream; struct CMapVectorEntry; @@ -35,16 +32,18 @@ class CMap { // Parse a CMap from , which can be a name or a stream. Sets // the initial reference count to 1. Returns NULL on failure. - static CMap *parse(CMapCache *cache, GString *collectionA, Object *obj); + static CMap *parse(CMapCache *cache, GString *collectionA, Object *obj, + GHash *usedCMaps = NULL); // Create the CMap specified by and . Sets // the initial reference count to 1. Returns NULL on failure. static CMap *parse(CMapCache *cache, GString *collectionA, - GString *cMapNameA); + GString *cMapNameA, GHash *usedCMaps = NULL); // Parse a CMap from . Sets the initial reference count to 1. // Returns NULL on failure. - static CMap *parse(CMapCache *cache, GString *collectionA, Stream *str); + static CMap *parse(CMapCache *cache, GString *collectionA, Stream *str, + GHash *usedCMaps = NULL); ~CMap(); @@ -68,11 +67,12 @@ class CMap { private: - void parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data); + void parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data, + GHash *usedCMaps); CMap(GString *collectionA, GString *cMapNameA); CMap(GString *collectionA, GString *cMapNameA, int wModeA); - void useCMap(CMapCache *cache, char *useName); - void useCMap(CMapCache *cache, Object *obj); + void useCMap(CMapCache *cache, char *useName, GHash *usedCMaps); + void useCMap(CMapCache *cache, Object *obj, GHash *usedCMaps); void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src); void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID); void freeCMapVector(CMapVectorEntry *vec); @@ -105,7 +105,8 @@ class CMapCache { // Increments its reference count; there will be one reference for // the cache plus one for the caller of this function. Returns NULL // on failure. - CMap *getCMap(GString *collection, GString *cMapName); + CMap *getCMap(GString *collection, GString *cMapName, + GHash *usedCMaps = NULL); private: diff --git a/src/xpdf-4.04/xpdf/Catalog.cc b/src/xpdf-4.04/xpdf/Catalog.cc index ddcbad5..a2cf570 100644 --- a/src/xpdf-4.04/xpdf/Catalog.cc +++ b/src/xpdf-4.04/xpdf/Catalog.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -405,11 +401,15 @@ LinkDest *Catalog::findDest(GString *name) { } } if (!found && nameTree.isDict()) { - if (!findDestInTree(&nameTree, name, &obj1)->isNull()) { + char *touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + if (!findDestInTree(&nameTree, &nameTree, name, &obj1, touchedObjs) + ->isNull()) { found = gTrue; } else { obj1.free(); } + gfree(touchedObjs); } if (!found) { return NULL; @@ -438,12 +438,31 @@ LinkDest *Catalog::findDest(GString *name) { return dest; } -Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { +Object *Catalog::findDestInTree(Object *treeRef, Object *tree, GString *name, + Object *obj, char *touchedObjs) { Object names, name1; - Object kids, kid, limits, low, high; + Object kids, kidRef, kid, limits, low, high; GBool done, found; int cmp, i; + // check for invalid reference + if (treeRef->isRef() && + (treeRef->getRefNum() < 0 || + treeRef->getRefNum() >= xref->getNumObjects())) { + obj->initNull(); + return obj; + } + + // check for a destination tree loop + if (treeRef->isRef()) { + if (touchedObjs[treeRef->getRefNum()]) { + error(errSyntaxError, -1, "Loop in destination name tree"); + obj->initNull(); + return obj; + } + touchedObjs[treeRef->getRefNum()] = 1; + } + // leaf node if (tree->dictLookup("Names", &names)->isArray()) { done = found = gFalse; @@ -472,13 +491,15 @@ Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { done = gFalse; if (tree->dictLookup("Kids", &kids)->isArray()) { for (i = 0; !done && i < kids.arrayGetLength(); ++i) { - if (kids.arrayGet(i, &kid)->isDict()) { + kids.arrayGetNF(i, &kidRef); + kids.arrayGet(i, &kid); + if (kid.isDict()) { if (kid.dictLookup("Limits", &limits)->isArray()) { if (limits.arrayGet(0, &low)->isString() && name->cmp(low.getString()) >= 0) { if (limits.arrayGet(1, &high)->isString() && name->cmp(high.getString()) <= 0) { - findDestInTree(&kid, name, obj); + findDestInTree(&kidRef, &kid, name, obj, touchedObjs); done = gTrue; } high.free(); @@ -488,6 +509,7 @@ Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { limits.free(); } kid.free(); + kidRef.free(); } } kids.free(); @@ -526,7 +548,10 @@ GBool Catalog::readPageTree(Object *catDict) { // because other code tries to fetch pages 1 through n. // In both cases: ignore the given page count and scan the tree // instead. - numPages = countPageTree(&topPagesObj); + char *touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + numPages = countPageTree(&topPagesRef, touchedObjs); + gfree(touchedObjs); } } else { // assume we got a Page node instead of a Pages node @@ -553,30 +578,69 @@ GBool Catalog::readPageTree(Object *catDict) { return gTrue; } -int Catalog::countPageTree(Object *pagesObj) { - Object kids, kid; - int n, n2, i; - - if (!pagesObj->isDict()) { +int Catalog::countPageTree(Object *pagesNodeRef, char *touchedObjs) { + // check for invalid reference + if (pagesNodeRef->isRef() && + (pagesNodeRef->getRefNum() < 0 || + pagesNodeRef->getRefNum() >= xref->getNumObjects())) { return 0; } - if (pagesObj->dictLookup("Kids", &kids)->isArray()) { - n = 0; - for (i = 0; i < kids.arrayGetLength(); ++i) { - kids.arrayGet(i, &kid); - n2 = countPageTree(&kid); - if (n2 < INT_MAX - n) { - n += n2; - } else { - error(errSyntaxError, -1, "Page tree contains too many pages"); - n = INT_MAX; - } - kid.free(); + + // check for a page tree loop; fetch the node object + Object pagesNode; + if (pagesNodeRef->isRef()) { + if (touchedObjs[pagesNodeRef->getRefNum()]) { + error(errSyntaxError, -1, "Loop in Pages tree"); + return 0; } + touchedObjs[pagesNodeRef->getRefNum()] = 1; + xref->fetch(pagesNodeRef->getRefNum(), pagesNodeRef->getRefGen(), + &pagesNode); } else { - n = 1; + pagesNodeRef->copy(&pagesNode); + } + + // count the subtree + int n = 0; + if (pagesNode.isDict()) { + Object kidsRef, kids; + pagesNode.dictLookupNF("Kids", &kidsRef); + if (kidsRef.isRef() && + kidsRef.getRefNum() >= 0 && + kidsRef.getRefNum() < xref->getNumObjects()) { + if (touchedObjs[kidsRef.getRefNum()]) { + error(errSyntaxError, -1, "Loop in Pages tree"); + kidsRef.free(); + pagesNode.free(); + return 0; + } + touchedObjs[kidsRef.getRefNum()] = 1; + xref->fetch(kidsRef.getRefNum(), kidsRef.getRefGen(), &kids); + } else { + kidsRef.copy(&kids); + } + kidsRef.free(); + if (kids.isArray()) { + for (int i = 0; i < kids.arrayGetLength(); ++i) { + Object kid; + kids.arrayGetNF(i, &kid); + int n2 = countPageTree(&kid, touchedObjs); + if (n2 < INT_MAX - n) { + n += n2; + } else { + error(errSyntaxError, -1, "Page tree contains too many pages"); + n = INT_MAX; + } + kid.free(); + } + } else { + n = 1; + } + kids.free(); } - kids.free(); + + pagesNode.free(); + return n; } @@ -738,37 +802,55 @@ void Catalog::readEmbeddedFileList(Dict *catDict) { Object obj1, obj2; char *touchedObjs; + touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + // read the embedded file name tree if (catDict->lookup("Names", &obj1)->isDict()) { - if (obj1.dictLookup("EmbeddedFiles", &obj2)->isDict()) { - readEmbeddedFileTree(&obj2); - } + obj1.dictLookupNF("EmbeddedFiles", &obj2); + readEmbeddedFileTree(&obj2, touchedObjs); obj2.free(); } obj1.free(); // look for file attachment annotations - touchedObjs = (char *)gmalloc(xref->getNumObjects()); - memset(touchedObjs, 0, xref->getNumObjects()); readFileAttachmentAnnots(catDict->lookupNF("Pages", &obj1), touchedObjs); obj1.free(); + gfree(touchedObjs); } -void Catalog::readEmbeddedFileTree(Object *node) { - Object kidsObj, kidObj; +void Catalog::readEmbeddedFileTree(Object *nodeRef, char *touchedObjs) { + Object node, kidsObj, kidObj; Object namesObj, nameObj, fileSpecObj; int i; - if (node->dictLookup("Kids", &kidsObj)->isArray()) { + // check for an object loop + if (nodeRef->isRef()) { + if (nodeRef->getRefNum() < 0 || + nodeRef->getRefNum() >= xref->getNumObjects() || + touchedObjs[nodeRef->getRefNum()]) { + return; + } + touchedObjs[nodeRef->getRefNum()] = 1; + xref->fetch(nodeRef->getRefNum(), nodeRef->getRefGen(), &node); + } else { + nodeRef->copy(&node); + } + + if (!node.isDict()) { + node.free(); + return; + } + + if (checkDictLookup(&node, "Kids", &kidsObj, touchedObjs)->isArray()) { for (i = 0; i < kidsObj.arrayGetLength(); ++i) { - if (kidsObj.arrayGet(i, &kidObj)->isDict()) { - readEmbeddedFileTree(&kidObj); - } + kidsObj.arrayGetNF(i, &kidObj); + readEmbeddedFileTree(&kidObj, touchedObjs); kidObj.free(); } } else { - if (node->dictLookup("Names", &namesObj)->isArray()) { + if (checkDictLookup(&node, "Names", &namesObj, touchedObjs)->isArray()) { for (i = 0; i+1 < namesObj.arrayGetLength(); ++i) { namesObj.arrayGet(i, &nameObj); namesObj.arrayGet(i+1, &fileSpecObj); @@ -780,6 +862,8 @@ void Catalog::readEmbeddedFileTree(Object *node) { namesObj.free(); } kidsObj.free(); + + node.free(); } void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, @@ -788,8 +872,9 @@ void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, int i; // check for an invalid object reference (e.g., in a damaged PDF file) - if (pageNodeRef->getRefNum() < 0 || - pageNodeRef->getRefNum() >= xref->getNumObjects()) { + if (pageNodeRef->isRef() && + (pageNodeRef->getRefNum() < 0 || + pageNodeRef->getRefNum() >= xref->getNumObjects())) { return; } @@ -805,20 +890,22 @@ void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, } if (pageNode.isDict()) { - if (pageNode.dictLookup("Kids", &kids)->isArray()) { + if (checkDictLookup(&pageNode, "Kids", &kids, touchedObjs)->isArray()) { for (i = 0; i < kids.arrayGetLength(); ++i) { readFileAttachmentAnnots(kids.arrayGetNF(i, &kid), touchedObjs); kid.free(); } } else { - if (pageNode.dictLookup("Annots", &annots)->isArray()) { + if (checkDictLookup(&pageNode, "Annots", + &annots, touchedObjs)->isArray()) { for (i = 0; i < annots.arrayGetLength(); ++i) { - if (annots.arrayGet(i, &annot)->isDict()) { - if (annot.dictLookup("Subtype", &subtype) + if (checkArrayGet(&annots, i, &annot, touchedObjs)->isDict()) { + if (checkDictLookup(&annot, "Subtype", &subtype, touchedObjs) ->isName("FileAttachment")) { - if (annot.dictLookup("FS", &fileSpec)) { + if (checkDictLookup(&annot, "FS", &fileSpec, touchedObjs)) { readEmbeddedFile(&fileSpec, - annot.dictLookup("Contents", &contents)); + checkDictLookup(&annot, "Contents", + &contents, touchedObjs)); contents.free(); } fileSpec.free(); @@ -901,10 +988,14 @@ Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) { void Catalog::readPageLabelTree(Object *root) { PageLabelNode *label0, *label1; + char *touchedObjs; int i; + touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); pageLabels = new GList(); - readPageLabelTree2(root); + readPageLabelTree2(root, touchedObjs); + gfree(touchedObjs); if (pageLabels->getLength() == 0) { deleteGList(pageLabels, PageLabelNode); @@ -922,15 +1013,29 @@ void Catalog::readPageLabelTree(Object *root) { label0->lastPage = numPages; } -void Catalog::readPageLabelTree2(Object *node) { - Object nums, num, labelObj, kids, kid; +void Catalog::readPageLabelTree2(Object *nodeRef, char *touchedObjs) { + Object node, nums, num, labelObj, kidsRef, kids, kid; int i; - if (!node->isDict()) { + // check for an object loop + if (nodeRef->isRef()) { + if (nodeRef->getRefNum() < 0 || + nodeRef->getRefNum() >= xref->getNumObjects() || + touchedObjs[nodeRef->getRefNum()]) { + return; + } + touchedObjs[nodeRef->getRefNum()] = 1; + xref->fetch(nodeRef->getRefNum(), nodeRef->getRefGen(), &node); + } else { + nodeRef->copy(&node); + } + + if (!node.isDict()) { + node.free(); return; } - if (node->dictLookup("Nums", &nums)->isArray()) { + if (node.dictLookup("Nums", &nums)->isArray()) { for (i = 0; i < nums.arrayGetLength() - 1; i += 2) { if (nums.arrayGet(i, &num)->isInt()) { if (nums.arrayGet(i+1, &labelObj)->isDict()) { @@ -944,14 +1049,32 @@ void Catalog::readPageLabelTree2(Object *node) { } nums.free(); - if (node->dictLookup("Kids", &kids)->isArray()) { + // check for an object loop in the Kids entry + if (node.dictLookupNF("Kids", &kidsRef)->isRef()) { + if (kidsRef.getRefNum() < 0 || + kidsRef.getRefNum() >= doc->getXRef()->getNumObjects() || + touchedObjs[kidsRef.getRefNum()]) { + kidsRef.free(); + node.free(); + return; + } + touchedObjs[kidsRef.getRefNum()] = 1; + kidsRef.fetch(doc->getXRef(), &kids); + } else { + kidsRef.copy(&kids); + } + kidsRef.free(); + + if (kids.isArray()) { for (i = 0; i < kids.arrayGetLength(); ++i) { - kids.arrayGet(i, &kid); - readPageLabelTree2(&kid); + kids.arrayGetNF(i, &kid); + readPageLabelTree2(&kid, touchedObjs); kid.free(); } } kids.free(); + + node.free(); } TextString *Catalog::getPageLabel(int pageNum) { @@ -1195,3 +1318,169 @@ GBool Catalog::convertPageLabelToInt(TextString *pageLabel, int prefixLength, } return gFalse; } + +GBool Catalog::usesJavaScript() { + Object catDict; + if (!xref->getCatalog(&catDict)->isDict()) { + catDict.free(); + return gFalse; + } + + GBool usesJS = gFalse; + + // check for Catalog.Names.JavaScript + Object namesObj; + if (catDict.dictLookup("Names", &namesObj)->isDict()) { + Object jsNamesObj; + namesObj.dictLookup("JavaScript", &jsNamesObj); + if (jsNamesObj.isDict()) { + usesJS = gTrue; + } + jsNamesObj.free(); + } + namesObj.free(); + + // look for JavaScript actionas in Page.AA + if (!usesJS) { + char *touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + Object pagesObj; + usesJS = scanPageTreeForJavaScript(catDict.dictLookupNF("Pages", &pagesObj), + touchedObjs); + pagesObj.free(); + gfree(touchedObjs); + } + + catDict.free(); + + return usesJS; +} + +GBool Catalog::scanPageTreeForJavaScript(Object *pageNodeRef, + char *touchedObjs) { + // check for an invalid object reference (e.g., in a damaged PDF file) + if (pageNodeRef->isRef() && + (pageNodeRef->getRefNum() < 0 || + pageNodeRef->getRefNum() >= xref->getNumObjects())) { + return gFalse; + } + + // check for a page tree loop + Object pageNode; + if (pageNodeRef->isRef()) { + if (touchedObjs[pageNodeRef->getRefNum()]) { + return gFalse; + } + touchedObjs[pageNodeRef->getRefNum()] = 1; + xref->fetch(pageNodeRef->getRefNum(), pageNodeRef->getRefGen(), &pageNode); + } else { + pageNodeRef->copy(&pageNode); + } + + // scan the page tree node + GBool usesJS = gFalse; + if (pageNode.isDict()) { + Object kids; + if (checkDictLookup(&pageNode, "Kids", &kids, touchedObjs)->isArray()) { + for (int i = 0; i < kids.arrayGetLength() && !usesJS; ++i) { + Object kid; + if (scanPageTreeForJavaScript(kids.arrayGetNF(i, &kid), touchedObjs)) { + usesJS = gTrue; + } + kid.free(); + } + } else { + + // scan Page.AA + Object pageAA; + if (checkDictLookup(&pageNode, "AA", &pageAA, touchedObjs)->isDict()) { + if (scanAAForJavaScript(&pageAA)) { + usesJS = gTrue; + } + } + pageAA.free(); + + // scanPage.Annots + if (!usesJS) { + Object annots; + if (checkDictLookup(&pageNode, "Annots", + &annots, touchedObjs)->isArray()) { + for (int i = 0; i < annots.arrayGetLength() && !usesJS; ++i) { + Object annot; + if (checkArrayGet(&annots, i, &annot, touchedObjs)->isDict()) { + Object annotAA; + if (checkDictLookup(&annot, "AA", &annotAA, + touchedObjs)->isDict()) { + if (scanAAForJavaScript(&annotAA)) { + usesJS = gTrue; + } + } + annotAA.free(); + } + annot.free(); + } + } + annots.free(); + } + } + kids.free(); + } + + pageNode.free(); + + return usesJS; +} + +GBool Catalog::scanAAForJavaScript(Object *aaObj) { + GBool usesJS = gFalse; + for (int i = 0; i < aaObj->dictGetLength() && !usesJS; ++i) { + Object action; + if (aaObj->dictGetVal(i, &action)->isDict()) { + Object js; + if (!action.dictLookupNF("JS", &js)->isNull()) { + usesJS = gTrue; + } + js.free(); + } + action.free(); + } + return usesJS; +} + +Object *Catalog::checkDictLookup(Object *dictObj, const char *key, + Object *element, char *touchedObjs) { + Object refObj; + dictObj->dictLookupNF(key, &refObj); + if (refObj.isRef()) { + int num = refObj.getRefNum(); + if (num >= 0 && num < xref->getNumObjects() && !touchedObjs[num]) { + touchedObjs[num] = 1; + xref->fetch(num, refObj.getRefGen(), element); + } else { + element->initNull(); + } + refObj.free(); + } else { + *element = refObj; + } + return element; +} + +Object *Catalog::checkArrayGet(Object *arrayObj, int i, + Object *element, char *touchedObjs) { + Object refObj; + arrayObj->arrayGetNF(i, &refObj); + if (refObj.isRef()) { + int num = refObj.getRefNum(); + if (num >= 0 && num < xref->getNumObjects() && !touchedObjs[num]) { + touchedObjs[num] = 1; + xref->fetch(num, refObj.getRefGen(), element); + } else { + element->initNull(); + } + refObj.free(); + } else { + *element = refObj; + } + return element; +} diff --git a/src/xpdf-4.04/xpdf/Catalog.h b/src/xpdf-4.04/xpdf/Catalog.h index 0acdd2d..9922b28 100644 --- a/src/xpdf-4.04/xpdf/Catalog.h +++ b/src/xpdf-4.04/xpdf/Catalog.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #if MULTITHREADED #include "GMutex.h" #endif @@ -118,6 +114,9 @@ class Catalog { Object *getViewerPreferences() { return &viewerPrefs; } + // Return true if the document uses JavaScript. + GBool usesJavaScript(); + private: PDFDoc *doc; @@ -144,23 +143,30 @@ class Catalog { Object viewerPrefs; // ViewerPreferences object GBool ok; // true if catalog is valid - Object *findDestInTree(Object *tree, GString *name, Object *obj); + Object *findDestInTree(Object *treeRef, Object *tree, GString *name, + Object *obj, char *touchedObjs); GBool readPageTree(Object *catDict); - int countPageTree(Object *pagesObj); + int countPageTree(Object *pagesNodeRef, char *touchedObjs); void loadPage(int pg); void loadPage2(int pg, int relPg, PageTreeNode *node); void readEmbeddedFileList(Dict *catDict); - void readEmbeddedFileTree(Object *node); + void readEmbeddedFileTree(Object *nodeRef, char *touchedObjs); void readFileAttachmentAnnots(Object *pageNodeRef, char *touchedObjs); void readEmbeddedFile(Object *fileSpec, Object *name1); void readPageLabelTree(Object *root); - void readPageLabelTree2(Object *node); + void readPageLabelTree2(Object *node, char *touchedObjs); PageLabelNode *findPageLabel(int pageNum); GString *makeRomanNumeral(int num, GBool uppercase); GString *makeLetterLabel(int num, GBool uppercase); GBool convertPageLabelToInt(TextString *pageLabel, int prefixLength, char style, int *n); + GBool scanPageTreeForJavaScript(Object *pageNodeRef, char *touchedObjs); + GBool scanAAForJavaScript(Object *aaObj); + Object *checkDictLookup(Object *dictObj, const char *key, + Object *element, char *touchedObjs); + Object *checkArrayGet(Object *arrayObj, int i, + Object *element, char *touchedObjs); }; #endif diff --git a/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc b/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc index 0a2100f..8372006 100644 --- a/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc +++ b/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -274,7 +270,18 @@ GBool CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, pst = new PSTokenizer(getCharFunc, data); pst->getToken(tok1, sizeof(tok1), &n1); while (pst->getToken(tok2, sizeof(tok2), &n2)) { - if (!strcmp(tok2, "usecmap")) { + if (!strcmp(tok1, "begincodespacerange")) { + if (globalParams->getIgnoreWrongSizeToUnicode() && + tok2[0] == '<' && tok2[n2 - 1] == '>' && + n2 - 2 != nBits / 4) { + error(errSyntaxWarning, -1, + "Incorrect character size in ToUnicode CMap"); + ok = gFalse; + break; + } + while (pst->getToken(tok1, sizeof(tok1), &n1) && + strcmp(tok1, "endcodespacerange")) ; + } else if (!strcmp(tok2, "usecmap")) { if (tok1[0] == '/') { name = new GString(tok1 + 1); if ((f = globalParams->findToUnicodeFile(name))) { @@ -465,6 +472,7 @@ GBool CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, pst->getToken(tok1, sizeof(tok1), &n1); } else { strcpy(tok1, tok2); + n1 = n2; } } delete pst; diff --git a/src/xpdf-4.04/xpdf/CharCodeToUnicode.h b/src/xpdf-4.04/xpdf/CharCodeToUnicode.h index be90251..7bbc97f 100644 --- a/src/xpdf-4.04/xpdf/CharCodeToUnicode.h +++ b/src/xpdf-4.04/xpdf/CharCodeToUnicode.h @@ -13,10 +13,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "CharTypes.h" #if MULTITHREADED diff --git a/src/xpdf-4.04/xpdf/Decrypt.cc b/src/xpdf-4.04/xpdf/Decrypt.cc index d4f8d4e..d36626d 100644 --- a/src/xpdf-4.04/xpdf/Decrypt.cc +++ b/src/xpdf-4.04/xpdf/Decrypt.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include "gmem.h" #include "gmempp.h" @@ -1492,14 +1488,14 @@ static void sha512(Guchar *msg, int msgLen, Guchar *hash) { SHA512Uint64 H[8]; int blkLen, i; - H[0] = 0x6a09e667f3bcc908LL; - H[1] = 0xbb67ae8584caa73bLL; - H[2] = 0x3c6ef372fe94f82bLL; - H[3] = 0xa54ff53a5f1d36f1LL; - H[4] = 0x510e527fade682d1LL; - H[5] = 0x9b05688c2b3e6c1fLL; - H[6] = 0x1f83d9abfb41bd6bLL; - H[7] = 0x5be0cd19137e2179LL; + H[0] = 0x6a09e667f3bcc908ULL; + H[1] = 0xbb67ae8584caa73bULL; + H[2] = 0x3c6ef372fe94f82bULL; + H[3] = 0xa54ff53a5f1d36f1ULL; + H[4] = 0x510e527fade682d1ULL; + H[5] = 0x9b05688c2b3e6c1fULL; + H[6] = 0x1f83d9abfb41bd6bULL; + H[7] = 0x5be0cd19137e2179ULL; blkLen = 0; for (i = 0; i + 128 <= msgLen; i += 128) { @@ -1558,14 +1554,14 @@ static void sha384(Guchar *msg, int msgLen, Guchar *hash) { SHA512Uint64 H[8]; int blkLen, i; - H[0] = 0xcbbb9d5dc1059ed8LL; - H[1] = 0x629a292a367cd507LL; - H[2] = 0x9159015a3070dd17LL; - H[3] = 0x152fecd8f70e5939LL; - H[4] = 0x67332667ffc00b31LL; - H[5] = 0x8eb44a8768581511LL; - H[6] = 0xdb0c2e0d64f98fa7LL; - H[7] = 0x47b5481dbefa4fa4LL; + H[0] = 0xcbbb9d5dc1059ed8ULL; + H[1] = 0x629a292a367cd507ULL; + H[2] = 0x9159015a3070dd17ULL; + H[3] = 0x152fecd8f70e5939ULL; + H[4] = 0x67332667ffc00b31ULL; + H[5] = 0x8eb44a8768581511ULL; + H[6] = 0xdb0c2e0d64f98fa7ULL; + H[7] = 0x47b5481dbefa4fa4ULL; blkLen = 0; for (i = 0; i + 128 <= msgLen; i += 128) { diff --git a/src/xpdf-4.04/xpdf/Decrypt.h b/src/xpdf-4.04/xpdf/Decrypt.h index 2b10abd..d0f3840 100644 --- a/src/xpdf-4.04/xpdf/Decrypt.h +++ b/src/xpdf-4.04/xpdf/Decrypt.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "GString.h" #include "Object.h" diff --git a/src/xpdf-4.04/xpdf/Dict.cc b/src/xpdf-4.04/xpdf/Dict.cc index c8c2973..71ea377 100644 --- a/src/xpdf-4.04/xpdf/Dict.cc +++ b/src/xpdf-4.04/xpdf/Dict.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" diff --git a/src/xpdf-4.04/xpdf/Dict.h b/src/xpdf-4.04/xpdf/Dict.h index b05f729..804fcdf 100644 --- a/src/xpdf-4.04/xpdf/Dict.h +++ b/src/xpdf-4.04/xpdf/Dict.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #if MULTITHREADED #include "GMutex.h" #endif diff --git a/src/xpdf-4.04/xpdf/DisplayState.cc b/src/xpdf-4.04/xpdf/DisplayState.cc index e0d3068..f1e8dcf 100644 --- a/src/xpdf-4.04/xpdf/DisplayState.cc +++ b/src/xpdf-4.04/xpdf/DisplayState.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include "gmempp.h" #include "GString.h" diff --git a/src/xpdf-4.04/xpdf/DisplayState.h b/src/xpdf-4.04/xpdf/DisplayState.h index 12c8170..a078c75 100644 --- a/src/xpdf-4.04/xpdf/DisplayState.h +++ b/src/xpdf-4.04/xpdf/DisplayState.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "SplashTypes.h" diff --git a/src/xpdf-4.04/xpdf/Error.cc b/src/xpdf-4.04/xpdf/Error.cc index 5a97505..c46378e 100644 --- a/src/xpdf-4.04/xpdf/Error.cc +++ b/src/xpdf-4.04/xpdf/Error.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include diff --git a/src/xpdf-4.04/xpdf/Error.h b/src/xpdf-4.04/xpdf/Error.h index 39e7613..574330f 100644 --- a/src/xpdf-4.04/xpdf/Error.h +++ b/src/xpdf-4.04/xpdf/Error.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #include "config.h" #include "gfile.h" diff --git a/src/xpdf-4.04/xpdf/Function.cc b/src/xpdf-4.04/xpdf/Function.cc index 82f32b9..a0554db 100644 --- a/src/xpdf-4.04/xpdf/Function.cc +++ b/src/xpdf-4.04/xpdf/Function.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -1292,7 +1288,7 @@ int PostScriptFunction::exec(double *stack, int sp0) { goto underflow; } nn = (int)stack[sp++]; - if (nn < 0) { + if (nn < 0 || nn > psStackSize) { goto invalidArg; } if (sp + nn > psStackSize) { @@ -1408,8 +1404,8 @@ int PostScriptFunction::exec(double *stack, int sp0) { goto underflow; } k = (int)stack[sp]; - if (k < 0) { - goto invalidArg; + if (k < 0 || k > psStackSize) { + goto invalidArg; } if (sp + 1 + k >= psStackSize) { goto underflow; @@ -1498,8 +1494,8 @@ int PostScriptFunction::exec(double *stack, int sp0) { } k = (int)stack[sp++]; nn = (int)stack[sp++]; - if (nn < 0) { - goto invalidArg; + if (k < -psStackSize || k > psStackSize || nn < 0 || nn > psStackSize) { + goto invalidArg; } if (nn > 0) { if (sp + nn > psStackSize) { diff --git a/src/xpdf-4.04/xpdf/Function.h b/src/xpdf-4.04/xpdf/Function.h index bf1f25e..73c92ab 100644 --- a/src/xpdf-4.04/xpdf/Function.h +++ b/src/xpdf-4.04/xpdf/Function.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" diff --git a/src/xpdf-4.04/xpdf/Gfx.cc b/src/xpdf-4.04/xpdf/Gfx.cc index 1539b84..b9fb006 100644 --- a/src/xpdf-4.04/xpdf/Gfx.cc +++ b/src/xpdf-4.04/xpdf/Gfx.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -516,7 +512,8 @@ GBool GfxResources::lookupPropertiesNF(const char *name, Object *obj) { // Gfx //------------------------------------------------------------------------ -Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, +Gfx::Gfx(PDFDoc *docA, OutputDev *outA, LocalParams *localParams, + int pageNum, Dict *resDict, double hDPI, double vDPI, PDFRectangle *box, PDFRectangle *cropBox, int rotate, GBool (*abortCheckCbkA)(void *data), @@ -534,8 +531,10 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, // initialize out = outA; - state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); + state = new GfxState(localParams, hDPI, vDPI, + box, rotate, out->upsideDown()); fontChanged = gFalse; + haveSavedClipPath = gFalse; clip = clipNone; ignoreUndef = 0; out->startPage(pageNum, state); @@ -565,8 +564,8 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, } } -Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox, +Gfx::Gfx(PDFDoc *docA, OutputDev *outA, LocalParams *localParams, + Dict *resDict, PDFRectangle *box, PDFRectangle *cropBox, GBool (*abortCheckCbkA)(void *data), void *abortCheckCbkDataA) { int i; @@ -582,8 +581,9 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, // initialize out = outA; - state = new GfxState(72, 72, box, 0, gFalse); + state = new GfxState(localParams, 72, 72, box, 0, gFalse); fontChanged = gFalse; + haveSavedClipPath = gFalse; clip = clipNone; ignoreUndef = 0; for (i = 0; i < 6; ++i) { @@ -1169,6 +1169,13 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { } obj2.free(); + // alpha is shape + if (obj1.dictLookup("AIS", &obj2)->isBool()) { + state->setAlphaIsShape(obj2.getBool()); + out->updateAlphaIsShape(state); + } + obj2.free(); + // soft mask if (!obj1.dictLookup("SMask", &obj2)->isNull()) { if (obj2.isName("None")) { @@ -1246,11 +1253,6 @@ void Gfx::doSoftMask(Object *str, Object *strRef, GBool alpha, Object obj1, obj2; int i; - // check for excessive recursion - if (formDepth > 20) { - return; - } - // get stream dict dict = str->streamGetDict(); @@ -1295,10 +1297,8 @@ void Gfx::doSoftMask(Object *str, Object *strRef, GBool alpha, resDict = obj1.isDict() ? obj1.getDict() : (Dict *)NULL; // draw it - ++formDepth; drawForm(strRef, resDict, m, bbox, gTrue, gTrue, isolated, knockout, alpha, transferFunc, backdropColorObj); - --formDepth; obj1.free(); } @@ -1829,15 +1829,20 @@ void Gfx::opFillStroke(Object args[], int numArgs) { } if (state->isPath()) { if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->fill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); - } else { - out->stroke(state); + out->fillStroke(state, gFalse); } } } @@ -1852,15 +1857,20 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) { if (state->isPath()) { state->closePath(); if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gFalse); } } } @@ -1874,15 +1884,20 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) { } if (state->isPath()) { if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gTrue); } } } @@ -1897,15 +1912,20 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { if (state->isPath()) { state->closePath(); if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gTrue); } } } @@ -1966,7 +1986,7 @@ void Gfx::doPatternStroke() { } } -void Gfx::doPatternText() { +void Gfx::doPatternText(GBool stroke) { GfxPattern *pattern; // this is a bit of a kludge -- patterns can be really slow, so we @@ -1976,7 +1996,8 @@ void Gfx::doPatternText() { return; } - if (!(pattern = state->getFillPattern())) { + pattern = stroke ? state->getStrokePattern() : state->getFillPattern(); + if (!pattern) { return; } switch (pattern->getType()) { @@ -2193,16 +2214,30 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, if (bbox[1] > bbox[3]) { t = bbox[1]; bbox[1] = bbox[3]; bbox[3] = t; } - xstep = fabs(tPat->getXStep()); - ystep = fabs(tPat->getYStep()); - xi0 = (int)ceil((xMin - bbox[2]) / xstep); - xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; - yi0 = (int)ceil((yMin - bbox[3]) / ystep); - yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + xstep = tPat->getXStep(); + ystep = tPat->getYStep(); + if (xstep == 0 || ystep == 0) { + error(errSyntaxError, getPos(), "Zero x or y step in tiling pattern fill"); + goto err; + } + if (xstep > 0) { + xi0 = (int)ceil((xMin - bbox[2]) / xstep); + xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; + } else { + xi0 = (int)ceil((xMax - bbox[0]) / xstep); + xi1 = (int)floor((xMin - bbox[2]) / xstep) + 1; + } + if (ystep > 0) { + yi0 = (int)ceil((yMin - bbox[3]) / ystep); + yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + } else { + yi0 = (int)ceil((yMax - bbox[1]) / ystep); + yi1 = (int)floor((yMin - bbox[3]) / ystep) + 1; + } for (i = 0; i < 4; ++i) { m1[i] = m[i]; } - if (out->useTilingPatternFill()) { + if (out->useTilingPatternFill() && !tPat->usesBlendMode(xref)) { m1[4] = m[4]; m1[5] = m[5]; out->tilingPatternFill(state, this, tPat->getContentStreamRef(), @@ -3521,12 +3556,16 @@ void Gfx::fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth) { } void Gfx::doEndPath() { - if (state->isCurPt() && clip != clipNone) { - state->clip(); - if (clip == clipNormal) { - out->clip(state); + if (clip != clipNone) { + if (state->isCurPt()) { + state->clip(); + if (clip == clipNormal) { + out->clip(state); + } else { + out->eoClip(state); + } } else { - out->eoClip(state); + error(errSyntaxError, getPos(), "Empty path in clip"); } } clip = clipNone; @@ -3555,9 +3594,15 @@ void Gfx::opBeginText(Object args[], int numArgs) { out->updateTextMat(state); out->updateTextPos(state); fontChanged = gTrue; + haveSavedClipPath = gFalse; } void Gfx::opEndText(Object args[], int numArgs) { + if (haveSavedClipPath) { + out->clipToSavedClipPath(state); + haveSavedClipPath = gFalse; + } + out->endTextObject(state); } @@ -3786,27 +3831,8 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { } void Gfx::doShowText(GString *s) { - GfxFont *font; - int wMode; - double riseX, riseY; - CharCode code; - Unicode u[8]; - double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, ddx, ddy; - double originX, originY, tOriginX, tOriginY; - double x0, y0, x1, y1; - double oldCTM[6], newCTM[6]; - double *mat; - Object charProcRef, charProc; - Dict *resDict; - Parser *oldParser; - GfxState *savedState; - char *p; - int render; - GBool patternFill; - int len, n, uLen, nChars, nSpaces, i; - - font = state->getFont(); - wMode = font->getWMode(); + GfxFont *font = state->getFont(); + int wMode = font->getWMode(); if (globalParams->isDroppedFont(font->getName() ? font->getName()->getCString() : "")) { @@ -3818,35 +3844,63 @@ void Gfx::doShowText(GString *s) { out->beginString(state, s); } - // if we're doing a pattern fill, set up clipping - render = state->getRender(); - if (!(render & 1) && - state->getFillColorSpace()->getMode() == csPattern) { - patternFill = gTrue; - saveState(); - // disable fill, enable clipping, leave stroke unchanged - if ((render ^ (render >> 1)) & 1) { - render = 5; + // figure out the drawing mode + // note: clipping, pattern fill, and pattern stroke are all handled + // by saving the path and then performing the appropriate + // actions in opEndText() + GBool doFill = gFalse; + GBool doStroke = gFalse; + GBool doMakePath = gFalse; + int render = state->getRender() & 7; + switch (render & 7) { + case 0: // fill + if (state->getFillColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; } else { - render = 7; + doFill = gTrue; } - state->setRender(render); - out->updateRender(state); - } else { - patternFill = gFalse; + break; + case 1: // stroke + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; + } else { + doStroke = gTrue; + } + break; + case 2: // fill + stroke + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; + } else { + doFill = gTrue; + doStroke = gTrue; + } + break; + case 3: // invisible + // nothing + break; + case 4: // fill + clip + case 5: // stroke + clip + case 6: // fill + stroke + clip + case 7: // clip + doMakePath = gTrue; + break; } + double riseX, riseY; state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - x0 = state->getCurX() + riseX; - y0 = state->getCurY() + riseY; + double xMin = state->getCurX() + riseX; + double yMin = state->getCurY() + riseY; // handle a Type 3 char if (font->getType() == fontType3 && out->interpretType3Chars()) { - mat = state->getCTM(); - for (i = 0; i < 6; ++i) { + double *mat = state->getCTM(); + double oldCTM[6]; + for (int i = 0; i < 6; ++i) { oldCTM[i] = mat[i]; } mat = state->getTextMat(); + double newCTM[6]; newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; @@ -3862,24 +3916,29 @@ void Gfx::doShowText(GString *s) { newCTM[3] *= state->getFontSize(); newCTM[0] *= state->getHorizScaling(); newCTM[1] *= state->getHorizScaling(); - curX = state->getCurX(); - curY = state->getCurY(); - oldParser = parser; - p = s->getCString(); - len = s->getLength(); + double curX = state->getCurX(); + double curY = state->getCurY(); + Parser *oldParser = parser; + char *p = s->getCString(); + int len = s->getLength(); while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); dx = dx * state->getFontSize() + state->getCharSpace(); if (n == 1 && *p == ' ') { dx += state->getWordSpace(); } dx *= state->getHorizScaling(); dy *= state->getFontSize(); + double tdx, tdy, ddx, ddy, x, y; state->textTransformDelta(dx, dy, &tdx, &tdy); state->transform(curX + riseX, curY + riseY, &x, &y); - savedState = saveStateStack(); + GfxState *savedState = saveStateStack(); state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); //~ the CTM concat values here are wrong (but never used) out->updateCTM(state, 1, 0, 0, 1, 0, 0); @@ -3899,9 +3958,11 @@ void Gfx::doShowText(GString *s) { #endif if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, code, u, uLen)) { + Object charProcRef, charProc; ((Gfx8BitFont *)font)->getCharProcNF(code, &charProcRef); charProcRef.fetch(xref, &charProc); - if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + Dict *resDict = ((Gfx8BitFont *)font)->getResources(); + if (resDict) { pushResources(resDict); } if (charProc.isStream()) { @@ -3927,12 +3988,16 @@ void Gfx::doShowText(GString *s) { parser = oldParser; } else if (out->useDrawChar()) { - p = s->getCString(); - len = s->getLength(); + char *p = s->getCString(); + int len = s->getLength(); while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); if (wMode) { dx *= state->getFontSize(); dy = dy * state->getFontSize() + state->getCharSpace(); @@ -3947,26 +4012,32 @@ void Gfx::doShowText(GString *s) { dx *= state->getHorizScaling(); dy *= state->getFontSize(); } + double tdx, tdy, tOriginX, tOriginY; state->textTransformDelta(dx, dy, &tdx, &tdy); originX *= state->getFontSize(); originY *= state->getFontSize(); state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, - tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); + tdx, tdy, tOriginX, tOriginY, code, n, u, uLen, + doFill, doStroke, doMakePath); state->shift(tdx, tdy); p += n; len -= n; } } else { - dx = dy = 0; - p = s->getCString(); - len = s->getLength(); - nChars = nSpaces = 0; + double dx = 0, dy = 0; + char *p = s->getCString(); + int len = s->getLength(); + int nChars = 0, nSpaces = 0; while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx2, &dy2, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx2, dy2, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx2, &dy2, &originX, &originY); dx += dx2; dy += dy2; if (n == 1 && *p == ' ') { @@ -3988,8 +4059,9 @@ void Gfx::doShowText(GString *s) { dx *= state->getHorizScaling(); dy *= state->getFontSize(); } + double tdx, tdy; state->textTransformDelta(dx, dy, &tdx, &tdy); - out->drawString(state, s); + out->drawString(state, s, doFill, doStroke, doMakePath); state->shift(tdx, tdy); } @@ -3997,40 +4069,70 @@ void Gfx::doShowText(GString *s) { out->endString(state); } - if (patternFill) { - out->saveTextPos(state); - // tell the OutputDev to do the clipping - out->endTextObject(state); - // set up a clipping bbox so doPatternText will work -- assume + if (doMakePath) { + // compute the clipping bbox for the saved text path -- assume // that the text bounding box does not extend past the baseline in // any direction by more than twice the font size - x1 = state->getCurX() + riseX; - y1 = state->getCurY() + riseY; - if (x0 > x1) { - x = x0; x0 = x1; x1 = x; + double xMax = state->getCurX() + riseX; + double yMax = state->getCurY() + riseY; + double t; + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; } - if (y0 > y1) { - y = y0; y0 = y1; y1 = y; + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; } - state->textTransformDelta(0, state->getFontSize(), &dx, &dy); + double dx1, dy1, dx2, dy2; + state->textTransformDelta(0, state->getFontSize(), &dx1, &dy1); state->textTransformDelta(state->getFontSize(), 0, &dx2, &dy2); - dx = fabs(dx); + dx1 = fabs(dx1); dx2 = fabs(dx2); - if (dx2 > dx) { - dx = dx2; + if (dx2 > dx1) { + dx1 = dx2; } - dy = fabs(dy); + dy1 = fabs(dy1); dy2 = fabs(dy2); - if (dy2 > dy) { - dy = dy2; - } - state->clipToRect(x0 - 2 * dx, y0 - 2 * dy, x1 + 2 * dx, y1 + 2 * dy); - // set render mode to fill-only - state->setRender(0); - out->updateRender(state); - doPatternText(); - restoreState(); - out->restoreTextPos(state); + if (dy2 > dy1) { + dy1 = dy2; + } + xMin -= 2 * dx1; + yMin -= 2 * dy1; + xMax += 2 * dx1; + yMax += 2 * dy1; + + //--- fill + if ((render & 3) == 0 || (render & 3) == 2) { + if (state->getFillColorSpace()->getMode() == csPattern) { + saveState(); + state->clipToRect(xMin, yMin, xMax, yMax); + out->clipToTextPath(state); + doPatternText(gFalse); + restoreState(); + } else { + out->fillTextPath(state); + } + } + + //--- stroke + if ((render & 3) == 1 || (render & 3) == 2) { + if (state->getStrokeColorSpace()->getMode() == csPattern) { + saveState(); + state->clipToRect(xMin, yMin, xMax, yMax); + out->clipToTextStrokePath(state); + doPatternText(gTrue); + restoreState(); + } else { + out->strokeTextPath(state); + } + } + + //--- clip + if (render & 4) { + out->addTextPathToSavedClipPath(state); + haveSavedClipPath = gTrue; + } else { + out->clearTextPath(state); + } } opCounter += 10 * s->getLength(); @@ -4116,6 +4218,7 @@ void Gfx::opXObject(Object args[], int numArgs) { xObj.streamGetDict()->lookup("Level1", &obj3); out->psXObject(xObj.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL); + obj3.free(); } } else if (obj2.isName()) { error(errSyntaxError, getPos(), @@ -4191,10 +4294,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("W", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + width = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image width"); + width = (int)obj1.getReal(); + } else { goto err2; } - width = obj1.getInt(); obj1.free(); if (width <= 0) { goto err1; @@ -4204,10 +4311,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("H", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + height = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image height"); + height = (int)obj1.getReal(); + } else { goto err2; } - height = obj1.getInt(); obj1.free(); if (height <= 0) { goto err1; @@ -4233,8 +4344,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("BPC", &obj1); } - if (obj1.isInt()) { - bits = obj1.getInt(); + if (obj1.isNum()) { + if (obj1.isInt()) { + bits = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), + "Non-integer image bits per component"); + bits = (int)obj1.getReal(); + } if (bits < 1 || bits > 16) { goto err2; } @@ -4377,26 +4494,34 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("W", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskWidth = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask width"); + maskWidth = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskWidth = obj1.getInt(); obj1.free(); maskDict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); maskDict->lookup("H", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskHeight = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask height"); + maskHeight = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskHeight = obj1.getInt(); obj1.free(); if (maskWidth <= 0 || maskHeight <= 0) { delete colorMap; @@ -4409,13 +4534,18 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("BPC", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskBits = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), + "Non-integer image mask bits per component"); + maskBits = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskBits = obj1.getInt(); obj1.free(); if (maskBits < 1 || maskBits > 16) { delete colorMap; @@ -4512,6 +4642,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } } else if (maskObj.isStream()) { // explicit mask + haveExplicitMask = gTrue; if (inlineImg) { delete colorMap; maskObj.free(); @@ -4526,32 +4657,31 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("W", &obj1); } - if (!obj1.isInt()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + if (obj1.isInt()) { + maskWidth = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask width"); + maskWidth = (int)obj1.getReal(); + } else { + haveExplicitMask = gFalse; } - maskWidth = obj1.getInt(); obj1.free(); maskDict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); maskDict->lookup("H", &obj1); } - if (!obj1.isInt()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + if (obj1.isInt()) { + maskHeight = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask height"); + maskHeight = (int)obj1.getReal(); + } else { + haveExplicitMask = gFalse; } - maskHeight = obj1.getInt(); obj1.free(); if (maskWidth <= 0 || maskHeight <= 0) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } maskDict->lookup("ImageMask", &obj1); if (obj1.isNull()) { @@ -4559,10 +4689,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskDict->lookup("IM", &obj1); } if (!obj1.isBool() || !obj1.getBool()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } obj1.free(); maskInvert = gFalse; @@ -4576,13 +4703,12 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskInvert = obj2.isNum() && obj2.getNum() == 1; obj2.free(); } else if (!obj1.isNull()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } obj1.free(); - haveExplicitMask = gTrue; + if (!haveExplicitMask) { + error(errSyntaxError, getPos(), "Bad image parameters"); + } } // if drawing is disabled, skip over inline image data @@ -4666,11 +4792,6 @@ void Gfx::doForm(Object *strRef, Object *str) { Object obj1, obj2, obj3; int i; - // check for excessive recursion - if (formDepth > 100) { - return; - } - // check for optional content if (!ocState && !out->needCharCount()) { return; @@ -4747,9 +4868,7 @@ void Gfx::doForm(Object *strRef, Object *str) { obj1.free(); // draw it - ++formDepth; drawForm(strRef, resDict, m, bbox, transpGroup, gFalse, isolated, knockout); - --formDepth; resObj.free(); } @@ -4768,6 +4887,14 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, double oldBaseMatrix[6]; int i; + if (formDepth > 100) { + error(errSyntaxError, getPos(), "Excessive recursion in Form XObjects"); + return; + } + ++formDepth; + + out->startStream(strRef->getRef(), state); + // push new resources on stack pushResources(resDict); @@ -4897,7 +5024,9 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, delete blendingColorSpace; } - return; + out->endStream(strRef->getRef()); + + --formDepth; } void Gfx::takeContentStreamStack(Gfx *oldGfx) { @@ -4936,7 +5065,9 @@ void Gfx::opBeginImage(Object args[], int numArgs) { // if we have the stream length, skip to end-of-stream and then // skip 'EI' in the original stream } else if (haveLength) { - while ((c1 = str->getChar()) != EOF) ; + // NB: getUndecodedStream() returns the EmbedStream created by + // buildImageStream() + while ((c1 = str->getUndecodedStream()->getChar()) != EOF) ; delete str; str = parser->getStream(); c1 = str->getChar(); @@ -5091,15 +5222,28 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { } obj.free(); mcKind = gfxMCOptionalContent; - } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) { - if (args[1].dictLookup("ActualText", &obj)->isString()) { - s = new TextString(obj.getString()); - out->beginActualText(state, s->getUnicode(), s->getLength()); - delete s; - mcKind = gfxMCActualText; + } else if (numArgs == 2 && args[1].isDict()) { + if (args[0].isName("Span")) { + if (args[1].dictLookup("ActualText", &obj)->isString()) { + s = new TextString(obj.getString()); + out->beginActualText(state, s->getUnicode(), s->getLength()); + delete s; + mcKind = gfxMCActualText; + } + obj.free(); + } + if (args[1].dictLookup("MCID", &obj)->isInt()) { + out->beginStructureItem(args[0].getName(), obj.getInt(), + args[1].getDict()); + if (mcKind == gfxMCActualText) { + mcKind = gfxMCStructureItemAndActualText; + } else { + mcKind = gfxMCStructureItem; + } } obj.free(); } + mc = new GfxMarkedContent(mcKind, ocState); markedContentStack->append(mc); } @@ -5123,6 +5267,11 @@ void Gfx::opEndMarkedContent(Object args[], int numArgs) { } } else if (mcKind == gfxMCActualText) { out->endActualText(state); + } else if (mcKind == gfxMCStructureItem) { + out->endStructureItem(); + } else if (mcKind == gfxMCStructureItemAndActualText) { + out->endStructureItem(); + out->endActualText(state); } } else { error(errSyntaxWarning, getPos(), "Mismatched EMC operator"); @@ -5193,10 +5342,14 @@ void Gfx::drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, // get the form matrix dict->lookup("Matrix", &matrixObj); - if (matrixObj.isArray()) { + if (matrixObj.isArray() && matrixObj.arrayGetLength() == 6) { for (i = 0; i < 6; ++i) { matrixObj.arrayGet(i, &obj1); - m[i] = obj1.getNum(); + if (obj1.isNum()) { + m[i] = obj1.getNum(); + } else { + m[i] = 0; + } obj1.free(); } } else { @@ -5253,13 +5406,13 @@ void Gfx::drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, // [0 sy 0] // [tx ty 1] // bbox to the annotation rectangle - if (formXMin == formXMax) { + if (formXMax - formXMin < 1e-8) { // this shouldn't happen sx = 1; } else { sx = (xMax - xMin) / (formXMax - formXMin); } - if (formYMin == formYMax) { + if (formYMax - formYMin < 1e-8) { // this shouldn't happen sy = 1; } else { diff --git a/src/xpdf-4.04/xpdf/Gfx.h b/src/xpdf-4.04/xpdf/Gfx.h index 14d7a60..73fff85 100644 --- a/src/xpdf-4.04/xpdf/Gfx.h +++ b/src/xpdf-4.04/xpdf/Gfx.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "gfile.h" #include "GfxState.h" @@ -34,6 +30,7 @@ class GfxFont; class Gfx; class PDFRectangle; class AnnotBorderStyle; +class LocalParams; //------------------------------------------------------------------------ @@ -106,6 +103,8 @@ class GfxResources { enum GfxMarkedContentKind { gfxMCOptionalContent, gfxMCActualText, + gfxMCStructureItem, + gfxMCStructureItemAndActualText, gfxMCOther }; @@ -131,15 +130,16 @@ class Gfx { public: // Constructor for regular output. - Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, + Gfx(PDFDoc *docA, OutputDev *outA, LocalParams *localParams, + int pageNum, Dict *resDict, double hDPI, double vDPI, PDFRectangle *box, PDFRectangle *cropBox, int rotate, GBool (*abortCheckCbkA)(void *data) = NULL, void *abortCheckCbkDataA = NULL); // Constructor for a sub-page object. - Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox, + Gfx(PDFDoc *docA, OutputDev *outA, LocalParams *localParams, + Dict *resDict, PDFRectangle *box, PDFRectangle *cropBox, GBool (*abortCheckCbkA)(void *data) = NULL, void *abortCheckCbkDataA = NULL); @@ -163,6 +163,9 @@ class Gfx { // Get the current graphics state object. GfxState *getState() { return state; } + // Get the current base matrix. + double *getBaseMatrix() { return baseMatrix; } + void drawForm(Object *strRef, Dict *resDict, double *matrix, double *bbox, GBool transpGroup = gFalse, GBool softMask = gFalse, GBool isolated = gFalse, GBool knockout = gFalse, @@ -194,6 +197,7 @@ class Gfx { GfxState *state; // current graphics state GBool fontChanged; // set if font or text matrix has changed + GBool haveSavedClipPath; GfxClipType clip; // do a clip? int ignoreUndef; // current BX/EX nesting level double baseMatrix[6]; // default matrix for most recent @@ -273,7 +277,7 @@ class Gfx { void opCloseEOFillStroke(Object args[], int numArgs); void doPatternFill(GBool eoFill); void doPatternStroke(); - void doPatternText(); + void doPatternText(GBool stroke); void doPatternImageMask(Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg, GBool interpolate); void doTilingPatternFill(GfxTilingPattern *tPat, diff --git a/src/xpdf-4.04/xpdf/GfxFont.cc b/src/xpdf-4.04/xpdf/GfxFont.cc index 30e8bd1..5050ab6 100644 --- a/src/xpdf-4.04/xpdf/GfxFont.cc +++ b/src/xpdf-4.04/xpdf/GfxFont.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -307,26 +303,10 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { obj2.initNull(); } + // NB: the PDF spec doesn't say anything about precedence, but Adobe + // uses FontFile3 over FontFile2 if both are present. if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) { - if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { - *embID = obj3.getRef(); - if (expectedType != fontType1) { - err = gTrue; - } - } - obj3.free(); - if (embID->num == -1 && - fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { - *embID = obj3.getRef(); - if (isType0) { - expectedType = fontCIDType2; - } else if (expectedType != fontTrueType) { - err = gTrue; - } - } - obj3.free(); - if (embID->num == -1 && - fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { + if (fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { *embID = obj3.getRef(); if (obj3.fetch(xref, &obj4)->isStream()) { obj4.streamGetDict()->lookup("Subtype", &subtype); @@ -375,6 +355,26 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { obj4.free(); } obj3.free(); + if (embID->num == -1) { + if (fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { + *embID = obj3.getRef(); + if (isType0) { + expectedType = fontCIDType2; + } else if (expectedType != fontTrueType) { + err = gTrue; + } + } + obj3.free(); + } + if (embID->num == -1) { + if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { + *embID = obj3.getRef(); + if (expectedType != fontType1) { + err = gTrue; + } + } + obj3.free(); + } } fontDesc.free(); @@ -411,12 +411,19 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { error(errSyntaxError, -1, "Embedded font file may be invalid"); break; } + } else { + error(errSyntaxError, -1, "Embedded font object is wrong type"); } obj4.free(); obj3.free(); } + // If the embedded font doesn't exist, or it's not a stream object, + // or we couldn't identify its type, then remove the reference so + // nothing tries to use it later. if (t == fontUnknownType) { + embID->num = -1; + embID->gen = -1; t = expectedType; } @@ -465,8 +472,18 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { } obj2.free(); - // get Ascent - // (CapHeight is a little more reliable - so use it if present) + // font FontBBox + if (obj1.dictLookup("FontBBox", &obj2)->isArray()) { + for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + fontBBox[i] = 0.001 * obj3.getNum(); + } + obj3.free(); + } + } + obj2.free(); + + // get Ascent (but also look at CapHeight) obj1.dictLookup("Ascent", &obj2); obj1.dictLookup("CapHeight", &obj3); if (obj2.isNum() || obj3.isNum()) { @@ -491,15 +508,25 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { if (t != 0 && t < 1.9) { declaredAscent = t; } - // if both Ascent and CapHeight are set, use the smaller one - // (because the most common problem is that Ascent is too large) - if (t2 != 0 && (t == 0 || t2 < t)) { - t = t2; - } - // some broken font descriptors set ascent and descent to 0; - // others set it to ridiculous values (e.g., 32768) - if (t != 0 && t < 1.9) { + // The ascent is generally expected to be in the (0.55, 1.9) range. + // If Ascent and/or CapHeight is in that range, use the smaller one + // (because the most common problem is that Ascent is too large). + // Otherwise check for a value in (0, 0.55], and use that. + if (t > 0.55 && t < 1.9) { + if (t2 > 0.55 && t2 < 1.9) { + ascent = (t < t2) ? t : t2; + } else { + ascent = t; + } + } else if (t2 > 0.55 && t2 < 1.9) { + ascent = t2; + } else if (fontBBox[3] > 0.55 && fontBBox[3] < 1.9 && + fontBBox[1] < fontBBox[3]) { + ascent = fontBBox[3]; + } else if (t > 0 && t < 1.9) { ascent = t; + } else if (t2 > 0 && t2 < 1.9) { + ascent = t2; } } obj2.free(); @@ -514,25 +541,46 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { t = -t; } // some broken font descriptors set ascent and descent to 0 - if (t != 0 && t > -1.9) { + if (t < 0 && t > -1.9) { descent = t; + } else if (fontBBox[1] > -1.9 && fontBBox[1] <= 0 && + fontBBox[1] < fontBBox[3]) { + descent = fontBBox[1]; } } obj2.free(); - // font FontBBox - if (obj1.dictLookup("FontBBox", &obj2)->isArray()) { - for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) { - if (obj2.arrayGet(i, &obj3)->isNum()) { - fontBBox[i] = 0.001 * obj3.getNum(); - } - obj3.free(); + } + obj1.free(); + + // scan font name for bold/italic tags and update the flags + if (name) { + i = name->getLength(); + if (i > 2 && !strncmp(name->getCString() + i - 2, "MT", 2)) { + i -= 2; + } + if (i > 6 && !strncmp(name->getCString() + i - 6, "Italic", 6)) { + flags |= fontItalic; + i -= 6; + } else if (i > 2 && !strncmp(name->getCString() + i - 2, "It", 2)) { + flags |= fontItalic; + i -= 2; + } else if (i > 7 && !strncmp(name->getCString() + i - 7, "Oblique", 7)) { + flags |= fontItalic; + i -= 7; + } + if (i > 0) { + char c = name->getChar(i-1); + if (!((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9'))) { + --i; } } - obj2.free(); - + if (i > 4 && !strncmp(name->getCString() + i - 4, "Bold", 4)) { + flags |= fontBold; + } } - obj1.free(); } CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, @@ -665,39 +713,41 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { fontLoc->locType = gfxFontLocExternal; fontLoc->path = path; fontLoc->fontNum = fontNum; - if (isCIDFont()) { - if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { - fontLoc->fontType = fontCIDType2; - return fontLoc; - } else if (sysFontType == sysFontOTF) { - fft = FoFiIdentifier::identifyFile(fontLoc->path->getCString()); - if (fft == fofiIdOpenTypeCFFCID) { - fontLoc->fontType = fontCIDType0COT; - return fontLoc; - } else if (fft == fofiIdTrueType) { - fontLoc->fontType = fontCIDType2; - return fontLoc; - } - } - } else { - if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { - fontLoc->fontType = fontTrueType; - return fontLoc; - } else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) { - fontLoc->fontType = fontType1; - return fontLoc; - } else if (sysFontType == sysFontOTF) { - fft = FoFiIdentifier::identifyFile(fontLoc->path->getCString()); - if (fft == fofiIdOpenTypeCFF8Bit) { - fontLoc->fontType = fontType1COT; - return fontLoc; - } else if (fft == fofiIdTrueType) { - fontLoc->fontType = fontTrueTypeOT; - return fontLoc; - } - } + fft = FoFiIdentifier::identifyFile(fontLoc->path->getCString()); + switch (fft) { + case fofiIdType1PFA: + case fofiIdType1PFB: + fontLoc->fontType = fontType1; + break; + case fofiIdCFF8Bit: + fontLoc->fontType = fontType1C; + break; + case fofiIdCFFCID: + fontLoc->fontType = fontCIDType0C; + break; + case fofiIdTrueType: + case fofiIdTrueTypeCollection: + fontLoc->fontType = isCIDFont() ? fontCIDType2 : fontTrueType; + break; + case fofiIdOpenTypeCFF8Bit: + fontLoc->fontType = fontType1COT; + break; + case fofiIdOpenTypeCFFCID: + fontLoc->fontType = fontCIDType0COT; + break; + case fofiIdDfont: + fontLoc->fontType = isCIDFont() ? fontCIDType2 : fontTrueType; + break; + case fofiIdUnknown: + case fofiIdError: + default: + delete fontLoc; + fontLoc = NULL; + break; + } + if (fontLoc) { + return fontLoc; } - delete fontLoc; } if (!isCIDFont()) { @@ -1082,6 +1132,17 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, baseEnc = winAnsiEncoding; } + // a non-embedded Symbol or ZapfDingbats font should never use one + // of the non-symbol encodings -- I've encountered PDF files that + // set the Encoding to WinAnsiEncoding, which doesn't make any sense + // (and other viewers also seem to ignore it) + if (builtinFont && embFontID.num < 0 && + (builtinFont->defaultBaseEnc == symbolEncoding || + builtinFont->defaultBaseEnc == zapfDingbatsEncoding) && + !obj1.isDict()) { + baseEnc = NULL; + } + // check embedded font file for base encoding // (only for Type 1 fonts - trying to get an encoding out of a // TrueType font is a losing proposition) @@ -1436,7 +1497,7 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() { int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { int *map; int cmapPlatform, cmapEncoding; - int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; + int unicodeCmap, macRomanCmap, macUnicodeCmap, msSymbolCmap, cmap; GBool nonsymbolic, useMacRoman, useUnicode; char *charName; Unicode u; @@ -1450,15 +1511,16 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { // This is based on the cmap/encoding selection algorithm in the PDF // 2.0 spec, but with some differences to match up with Adobe's // behavior. - unicodeCmap = macRomanCmap = msSymbolCmap = -1; + unicodeCmap = macRomanCmap = macUnicodeCmap = msSymbolCmap = -1; for (i = 0; i < ff->getNumCmaps(); ++i) { cmapPlatform = ff->getCmapPlatform(i); cmapEncoding = ff->getCmapEncoding(i); - if ((cmapPlatform == 3 && cmapEncoding == 1) || - (cmapPlatform == 0 && cmapEncoding <= 4)) { + if (cmapPlatform == 3 && cmapEncoding == 1) { unicodeCmap = i; } else if (cmapPlatform == 1 && cmapEncoding == 0) { macRomanCmap = i; + } else if (cmapPlatform == 0 && cmapEncoding <= 4) { + macUnicodeCmap = i; } else if (cmapPlatform == 3 && cmapEncoding == 0) { msSymbolCmap = i; } @@ -1466,24 +1528,25 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { useMacRoman = gFalse; useUnicode = gFalse; nonsymbolic = !(flags & fontSymbolic); - if (usesMacRomanEnc && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { - cmap = unicodeCmap; - useUnicode = gTrue; - } else if (nonsymbolic && unicodeCmap >= 0) { + if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { cmap = unicodeCmap; useUnicode = gTrue; - } else if (nonsymbolic && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (msSymbolCmap >= 0) { + } else if (!nonsymbolic && msSymbolCmap >= 0) { cmap = msSymbolCmap; } else if (unicodeCmap >= 0) { cmap = unicodeCmap; + useUnicode = nonsymbolic; + } else if (usesMacRomanEnc && macRomanCmap >= 0) { + // MacRoman cmap has higher precedence than Mac Unicode only if + // the font uses the MacRoman encoding + cmap = macRomanCmap; + useMacRoman = gTrue; + } else if (macUnicodeCmap >= 0) { + cmap = macUnicodeCmap; + useUnicode = nonsymbolic; } else if (macRomanCmap >= 0) { cmap = macRomanCmap; + useMacRoman = nonsymbolic; } else { cmap = 0; } @@ -1630,7 +1693,8 @@ GBool Gfx8BitFont::problematicForUnicode() { return !hasToUnicode && (!hasEncoding || usedNumericHeuristic); case fontType3: - return !hasToUnicode && !hasEncoding; + // this never happens -- Type 3 fonts don't set embFontID + return !hasToUnicode && (!hasEncoding || usedNumericHeuristic); case fontTrueType: case fontTrueTypeOT: @@ -1640,6 +1704,9 @@ GBool Gfx8BitFont::problematicForUnicode() { return !hasToUnicode; } + } else if (type == fontType3) { + return !hasToUnicode && (!hasEncoding || usedNumericHeuristic); + } else { // NB: type will be fontTypeUnknown if the PDF specifies an // invalid font type -- which is ok, if we have a ToUnicode map or @@ -1648,6 +1715,10 @@ GBool Gfx8BitFont::problematicForUnicode() { } } +GBool Gfx8BitFont::parensAreSwapped(XRef *xref) { + return gFalse; +} + //------------------------------------------------------------------------ // GfxCIDFont //------------------------------------------------------------------------ @@ -2007,7 +2078,7 @@ void GfxCIDFont::readTrueTypeUnicodeMapping(XRef *xref) { int nGlyphs, nMappings, gid, i; // must be an embedded TrueType font, with an unknown char collection - if ((type != fontCIDType2 && type == fontCIDType2OT) || + if ((type != fontCIDType2 && type != fontCIDType2OT) || embFontID.num < 0 || hasKnownCollection) { goto err0; @@ -2225,79 +2296,197 @@ GBool GfxCIDFont::problematicForUnicode() { } } +GBool GfxCIDFont::parensAreSwapped(XRef *xref) { + char *buf = NULL; + FoFiTrueType *ff = NULL; + int bufLen; + int unicodeCmap, leftParenGID, rightParenGID, leftParenCID, rightParenCID; + Unicode leftParenUnicode, rightParenUnicode; + GBool swapped; + + // only relevant for embedded TrueType fonts, with unknown char + // collections, and with ToUnicode maps + if ((type != fontCIDType2 && type != fontCIDType2OT) || + embFontID.num < 0 || + hasKnownCollection || + !hasToUnicode) { + return gFalse; + } + + // read the embedded font and construct a FoFiTrueType + if (!(buf = readEmbFontFile(xref, &bufLen))) { + goto err; + } + if (!(ff = FoFiTrueType::make(buf, bufLen, 0))) { + goto err; + } + + // find the TrueType Unicode cmap + unicodeCmap = -1; + for (int i = 0; i < ff->getNumCmaps(); ++i) { + int cmapPlatform = ff->getCmapPlatform(i); + int cmapEncoding = ff->getCmapEncoding(i); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + unicodeCmap = i; + break; + } + } + if (unicodeCmap < 0) { + goto err; + } + + // map parens to GIDs using the TrueType Unicode cmap + leftParenGID = ff->mapCodeToGID(unicodeCmap, 0x28); + rightParenGID = ff->mapCodeToGID(unicodeCmap, 0x29); + if (leftParenGID == 0 || rightParenGID == 0) { + goto err; + } + + // map GIDs to CIDs using the inverted CIDToGID map + leftParenCID = -1; + rightParenCID = -1; + if (cidToGID) { + for (int i = 0; + i <= cidToGIDLen && leftParenCID < 0 && rightParenCID < 0; + ++i) { + if (cidToGID[i] == leftParenGID) { + leftParenCID = i; + } else if (cidToGID[i] == rightParenGID) { + rightParenCID = i; + } + } + if (leftParenCID < 0 || rightParenCID < 0) { + goto err; + } + } else { + leftParenCID = leftParenGID; + rightParenCID = rightParenGID; + } + + // map CIDs to Unicode using the ToUnicode map + if (ctu->mapToUnicode((CharCode)leftParenCID, &leftParenUnicode, 1) < 1 || + ctu->mapToUnicode((CharCode)rightParenCID, &rightParenUnicode, 1) < 1) { + goto err; + } + + // check for swap + swapped = leftParenUnicode == 0x29 && rightParenUnicode == 0x28; + + delete ff; + ff = NULL; + gfree(buf); + buf = NULL; + + return swapped; + + err: + if (ff) { + delete ff; + } + if (buf) { + gfree(buf); + } + return gFalse; +} + //------------------------------------------------------------------------ // GfxFontDict //------------------------------------------------------------------------ -GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { - GfxFont *font; - char *tag; - Object obj1, obj2; - Ref r; - int i; +class GfxFontDictEntry { +public: + + GfxFontDictEntry(Ref refA, Object *fontObjA); + ~GfxFontDictEntry(); + void load(GfxFont *fontA); + + GBool loaded; + Ref ref; + Object fontObj; // valid if unloaded + GfxFont *font; // valid if loaded +}; + +GfxFontDictEntry::GfxFontDictEntry(Ref refA, Object *fontObjA) { + loaded = gFalse; + ref = refA; + fontObjA->copy(&fontObj); + font = NULL; +} +GfxFontDictEntry::~GfxFontDictEntry() { + // NB: If the font has been loaded, font is non-NULL and is owned by + // GfxFontDict.uniqueFonts. + if (!loaded) { + fontObj.free(); + } +} + +void GfxFontDictEntry::load(GfxFont *fontA) { + loaded = gTrue; + font = fontA; + fontObj.free(); +} + +GfxFontDict::GfxFontDict(XRef *xrefA, Ref *fontDictRef, Dict *fontDict) { + xref = xrefA; fonts = new GHash(gTrue); uniqueFonts = new GList(); - for (i = 0; i < fontDict->getLength(); ++i) { - tag = fontDict->getKey(i); - fontDict->getValNF(i, &obj1); - obj1.fetch(xref, &obj2); - if (!obj2.isDict()) { - error(errSyntaxError, -1, "font resource is not a dictionary"); - } else if (obj1.isRef() && (font = lookupByRef(obj1.getRef()))) { - fonts->add(new GString(tag), font); + + for (int i = 0; i < fontDict->getLength(); ++i) { + char *tag = fontDict->getKey(i); + Object fontObj; + fontDict->getValNF(i, &fontObj); + Ref r; + if (fontObj.isRef()) { + r = fontObj.getRef(); + } else if (fontDictRef) { + // legal generation numbers are five digits, so we use a + // 6-digit number here + r.gen = 100000 + fontDictRef->num; + r.num = i; } else { - if (obj1.isRef()) { - r = obj1.getRef(); - } else if (fontDictRef) { - // legal generation numbers are five digits, so we use a - // 6-digit number here - r.gen = 100000 + fontDictRef->num; - r.num = i; - } else { - // no indirect reference for this font, or for the containing - // font dict, so hash the font and use that - r.gen = 100000; - r.num = hashFontObject(&obj2); - } - if ((font = GfxFont::makeFont(xref, tag, r, obj2.getDict()))) { - if (!font->isOk()) { - delete font; - } else { - uniqueFonts->append(font); - fonts->add(new GString(tag), font); - } - } + // no indirect reference for this font, or for the containing + // font dict, so hash the font and use that + r.gen = 100000; + r.num = hashFontObject(&fontObj); } - obj1.free(); - obj2.free(); + fonts->add(new GString(tag), new GfxFontDictEntry(r, &fontObj)); + fontObj.free(); } } GfxFontDict::~GfxFontDict() { deleteGList(uniqueFonts, GfxFont); - delete fonts; + deleteGHash(fonts, GfxFontDictEntry); } GfxFont *GfxFontDict::lookup(char *tag) { - return (GfxFont *)fonts->lookup(tag); + GfxFontDictEntry *entry = (GfxFontDictEntry *)fonts->lookup(tag); + if (!entry) { + return NULL; + } + load(tag, entry); + return entry->font; } GfxFont *GfxFontDict::lookupByRef(Ref ref) { - GfxFont *font; - int i; - - for (i = 0; i < uniqueFonts->getLength(); ++i) { - font = (GfxFont *)uniqueFonts->get(i); - if (font->getID()->num == ref.num && - font->getID()->gen == ref.gen) { - return font; + GHashIter *iter; + GString *tag; + GfxFontDictEntry *entry; + fonts->startIter(&iter); + while (fonts->getNext(&iter, &tag, (void **)&entry)) { + if (entry->ref.num == ref.num && entry->ref.gen == ref.gen) { + fonts->killIter(&iter); + load(tag->getCString(), entry); + return entry->font; } } return NULL; } int GfxFontDict::getNumFonts() { + loadAll(); return uniqueFonts->getLength(); } @@ -2305,6 +2494,52 @@ GfxFont *GfxFontDict::getFont(int i) { return (GfxFont *)uniqueFonts->get(i); } +void GfxFontDict::loadAll() { + GHashIter *iter; + GString *tag; + GfxFontDictEntry *entry; + fonts->startIter(&iter); + while (fonts->getNext(&iter, &tag, (void **)&entry)) { + load(tag->getCString(), entry); + } +} + +void GfxFontDict::load(char *tag, GfxFontDictEntry *entry) { + if (entry->loaded) { + return; + } + + // check for a duplicate that has already been loaded + // (don't do this for "synthetic" refs) + if (entry->fontObj.isRef()) { + for (int i = 0; i < uniqueFonts->getLength(); ++i) { + GfxFont *font = (GfxFont *)uniqueFonts->get(i); + if (font->getID()->num == entry->ref.num && + font->getID()->gen == entry->ref.gen) { + entry->load(font); + return; + } + } + } + + GfxFont *font = NULL; + Object obj; + entry->fontObj.fetch(xref, &obj); + if (obj.isDict()) { + font = GfxFont::makeFont(xref, tag, entry->ref, obj.getDict()); + if (font->isOk()) { + uniqueFonts->append(font); + } else { + delete font; + font = NULL; + } + } else { + error(errSyntaxError, -1, "font resource is not a dictionary"); + } + obj.free(); + entry->load(font); +} + // FNV-1a hash class FNVHash { public: diff --git a/src/xpdf-4.04/xpdf/GfxFont.h b/src/xpdf-4.04/xpdf/GfxFont.h index e752ded..cc27ff7 100644 --- a/src/xpdf-4.04/xpdf/GfxFont.h +++ b/src/xpdf-4.04/xpdf/GfxFont.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "GString.h" #include "Object.h" @@ -29,6 +25,7 @@ class FoFiTrueType; class FoFiType1C; struct GfxFontCIDWidths; struct Base14FontMapEntry; +class GfxFontDictEntry; class FNVHash; //------------------------------------------------------------------------ @@ -218,6 +215,11 @@ class GfxFont { // converting text to Unicode. virtual GBool problematicForUnicode() = 0; + // Returns true if this font swaps the left and right parens in its + // ToUnicode map. This is likely a kludge used by bad PDF generators + // with Arabic fonts. + virtual GBool parensAreSwapped(XRef *xref) = 0; + protected: static GfxFontType getFontType(XRef *xref, Dict *fontDict, Ref *embID); @@ -298,6 +300,8 @@ class Gfx8BitFont: public GfxFont { virtual GBool problematicForUnicode(); + virtual GBool parensAreSwapped(XRef *xref); + private: Base14FontMapEntry *base14; // for Base-14 fonts only; NULL otherwise @@ -359,6 +363,8 @@ class GfxCIDFont: public GfxFont { virtual GBool problematicForUnicode(); + virtual GBool parensAreSwapped(XRef *xref); + private: void readTrueTypeUnicodeMapping(XRef *xref); @@ -388,7 +394,7 @@ class GfxFontDict { public: // Build the font dictionary, given the PDF font dictionary. - GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict); + GfxFontDict(XRef *xrefA, Ref *fontDictRef, Dict *fontDict); // Destructor. ~GfxFontDict(); @@ -405,13 +411,18 @@ class GfxFontDict { friend class GfxFont; + void loadAll(); + void load(char *tag, GfxFontDictEntry *entry); static int hashFontObject(Object *obj); static void hashFontObject1(Object *obj, FNVHash *h); - GHash *fonts; // hash table of fonts -- this may - // include duplicates, i.e., when - // two tags map to the same font + XRef *xref; + GHash *fonts; // hash table of fonts, mapping from + // tag to GfxFontDictEntry; this may + // contain duplicates, i.e., two + // tags that map to the same font GList *uniqueFonts; // list of all unique font objects (no dups) + // that have been loaded }; #endif diff --git a/src/xpdf-4.04/xpdf/GfxState.cc b/src/xpdf-4.04/xpdf/GfxState.cc index 43503aa..6e5bb6c 100644 --- a/src/xpdf-4.04/xpdf/GfxState.cc +++ b/src/xpdf-4.04/xpdf/GfxState.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -19,6 +15,7 @@ #include "gmempp.h" #include "Error.h" #include "GlobalParams.h" +#include "LocalParams.h" #include "Object.h" #include "Array.h" #include "Page.h" @@ -936,15 +933,15 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, } nCompsA = obj2.getInt(); obj2.free(); - if (nCompsA > 4) { - error(errSyntaxError, -1, - "ICCBased color space with too many ({0:d} > 4) components", - nCompsA); - nCompsA = 4; - } - if (dict->lookup("Alternate", &obj2)->isNull() || - !(altA = GfxColorSpace::parse(&obj2, - recursion + 1))) { + if (!dict->lookup("Alternate", &obj2)->isNull() && + (altA = GfxColorSpace::parse(&obj2, + recursion + 1))) { + if (altA->getNComps() != nCompsA) { + error(errSyntaxError, -1, + "Number of components in ICCBased color space doesn't match alternate color space"); + nCompsA = altA->getNComps(); + } + } else { switch (nCompsA) { case 1: altA = GfxColorSpace::create(csDeviceGray); @@ -1784,6 +1781,258 @@ GfxPattern *GfxTilingPattern::copy() { &resDict, matrix, &contentStreamRef); } +GBool GfxTilingPattern::usesBlendMode(XRef *xref) { + char *scannedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(scannedObjs, 0, xref->getNumObjects()); + GBool ret = scanResourcesForBlendMode(&resDict, scannedObjs, xref); + gfree(scannedObjs); + return ret; +} + +GBool GfxTilingPattern::scanResourcesForBlendMode(Object *resDict2, + char *scannedObjs, + XRef *xref) { + Object ref1, obj1, obj2; + + if (!resDict2->isDict()) { + return gFalse; + } + + //----- ExtGStates + resDict2->dictLookupNF("ExtGState", &ref1); + if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() && + !scannedObjs[ref1.getRefNum()])) { + if (ref1.isRef()) { + scannedObjs[ref1.getRefNum()] = 1; + ref1.fetch(xref, &obj1); + } else { + ref1.copy(&obj1); + } + if (obj1.isDict()) { + for (int i = 0; i < obj1.dictGetLength(); ++i) { + if (scanExtGStateForBlendMode(obj1.dictGetValNF(i, &obj2), + scannedObjs, xref)) { + obj2.free(); + obj1.free(); + ref1.free(); + return gTrue; + } + obj2.free(); + } + } + obj1.free(); + } + ref1.free(); + + //----- patterns + resDict2->dictLookupNF("Pattern", &ref1); + if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() && + !scannedObjs[ref1.getRefNum()])) { + if (ref1.isRef()) { + scannedObjs[ref1.getRefNum()] = 1; + ref1.fetch(xref, &obj1); + } else { + ref1.copy(&obj1); + } + if (obj1.isDict()) { + for (int i = 0; i < obj1.dictGetLength(); ++i) { + if (scanPatternForBlendMode(obj1.dictGetValNF(i, &obj2), + scannedObjs, xref)) { + obj2.free(); + obj1.free(); + ref1.free(); + return gTrue; + } + obj2.free(); + } + } + obj1.free(); + } + ref1.free(); + + //----- XObjects + resDict2->dictLookupNF("XObject", &ref1); + if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() && + !scannedObjs[ref1.getRefNum()])) { + if (ref1.isRef()) { + scannedObjs[ref1.getRefNum()] = 1; + ref1.fetch(xref, &obj1); + } else { + ref1.copy(&obj1); + } + if (obj1.isDict()) { + for (int i = 0; i < obj1.dictGetLength(); ++i) { + if (scanXObjectForBlendMode(obj1.dictGetValNF(i, &obj2), + scannedObjs, xref)) { + obj2.free(); + obj1.free(); + ref1.free(); + return gTrue; + } + obj2.free(); + } + } + obj1.free(); + } + ref1.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanExtGStateForBlendMode(Object *gsObj, + char *scannedObjs, + XRef *xref) { + Object gsDict, obj1; + + if (gsObj->isRef()) { + if (gsObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[gsObj->getRefNum()]) { + return gFalse; + } + scannedObjs[gsObj->getRefNum()] = 1; + gsObj->fetch(xref, &gsDict); + } else { + gsObj->copy(&gsDict); + } + if (!gsDict.isDict()) { + gsDict.free(); + return gFalse; + } + + gsDict.dictLookup("BM", &obj1); + if (obj1.isName() && !obj1.isName("Normal")) { + obj1.free(); + gsDict.free(); + return gTrue; + } + obj1.free(); + + if (!gsDict.dictLookupNF("SMask", &obj1)->isNull()) { + if (scanSoftMaskForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + gsDict.free(); + return gTrue; + } + } + obj1.free(); + + gsDict.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanSoftMaskForBlendMode(Object *softMaskObj, + char *scannedObjs, + XRef *xref) { + Object softMaskDict, obj1; + + if (softMaskObj->isRef()) { + if (softMaskObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[softMaskObj->getRefNum()]) { + return gFalse; + } + scannedObjs[softMaskObj->getRefNum()] = 1; + softMaskObj->fetch(xref, &softMaskDict); + } else { + softMaskObj->copy(&softMaskDict); + } + if (!softMaskDict.isDict()) { + softMaskDict.free(); + return gFalse; + } + + if (!softMaskDict.dictLookupNF("G", &obj1)->isNull()) { + if (scanXObjectForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + softMaskDict.free(); + return gTrue; + } + } + obj1.free(); + + softMaskDict.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanPatternForBlendMode(Object *patternObj, + char *scannedObjs, + XRef *xref) { + Object patternObj2, obj1; + Dict *patternDict; + + if (patternObj->isRef()) { + if (patternObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[patternObj->getRefNum()]) { + return gFalse; + } + scannedObjs[patternObj->getRefNum()] = 1; + patternObj->fetch(xref, &patternObj2); + } else { + patternObj->copy(&patternObj2); + } + if (patternObj2.isDict()) { + patternDict = patternObj2.getDict(); + } else if (patternObj2.isStream()) { + patternDict = patternObj2.streamGetDict(); + } else { + patternObj2.free(); + return gFalse; + } + + if (!patternDict->lookupNF("Resources", &obj1)->isNull()) { + if (scanResourcesForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + patternObj2.free(); + return gTrue; + } + } + obj1.free(); + + patternObj2.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanXObjectForBlendMode(Object *xObj, + char *scannedObjs, + XRef *xref) { + Object xObj2, obj1; + Dict *dict; + + if (xObj->isRef()) { + if (xObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[xObj->getRefNum()]) { + return gFalse; + } + scannedObjs[xObj->getRefNum()] = 1; + xObj->fetch(xref, &xObj2); + } else { + xObj->copy(&xObj2); + } + if (xObj2.isDict()) { + dict = xObj2.getDict(); + } else if (xObj2.isStream()) { + dict = xObj2.streamGetDict(); + } else { + xObj2.free(); + return gFalse; + } + + if (!dict->lookupNF("Resources", &obj1)->isNull()) { + if (scanResourcesForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + xObj2.free(); + return gTrue; + } + } + obj1.free(); + + xObj2.free(); + + return gFalse; +} + //------------------------------------------------------------------------ // GfxShadingPattern //------------------------------------------------------------------------ @@ -2880,6 +3129,11 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( delete bitBuf; if (typeA == 5) { nRows = nVerticesA / vertsPerRow; + if (nRows == 0) { + error(errSyntaxError, -1, + "Invalid VerticesPerRow in shading dictionary"); + goto err3; + } nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1); trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int)); k = 0; @@ -2926,6 +3180,12 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( return shading; + err3: + gfree(trianglesA); + gfree(verticesA); + for (i = 0; i < nFuncsA; ++i) { + delete funcsA[i]; + } err2: obj1.free(); err1: @@ -2963,8 +3223,8 @@ void GfxGouraudTriangleShading::getTriangle( } } -void GfxGouraudTriangleShading::getBBox(double *xMin, double *yMin, - double *xMax, double *yMax) { +void GfxGouraudTriangleShading::getBBox(double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { double xxMin = 0; double yyMin = 0; double xxMax = 0; @@ -2985,10 +3245,10 @@ void GfxGouraudTriangleShading::getBBox(double *xMin, double *yMin, yyMax = vertices[i].y; } } - *xMin = xxMin; - *yMin = yyMin; - *xMax = xxMax; - *yMax = yyMax; + *xMinA = xxMin; + *yMinA = yyMin; + *xMaxA = xxMax; + *yMaxA = yyMax; } void GfxGouraudTriangleShading::getColor(double *in, GfxColor *out) { @@ -3621,8 +3881,8 @@ GfxShading *GfxPatchMeshShading::copy() { return new GfxPatchMeshShading(this); } -void GfxPatchMeshShading::getBBox(double *xMin, double *yMin, - double *xMax, double *yMax) { +void GfxPatchMeshShading::getBBox(double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { double xxMin = 0; double yyMin = 0; double xxMax = 0; @@ -3647,10 +3907,10 @@ void GfxPatchMeshShading::getBBox(double *xMin, double *yMin, } } } - *xMin = xxMin; - *yMin = yyMin; - *xMax = xxMax; - *yMax = yyMax; + *xMinA = xxMin; + *yMinA = yyMin; + *xMaxA = xxMax; + *yMaxA = yyMax; } void GfxPatchMeshShading::getColor(double *in, GfxColor *out) { @@ -4240,11 +4500,13 @@ void GfxPath::offset(double dx, double dy) { // GfxState //------------------------------------------------------------------------ -GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, +GfxState::GfxState(LocalParams *localParamsA, + double hDPIA, double vDPIA, PDFRectangle *pageBox, int rotateA, GBool upsideDown ) { double kx, ky; + localParams = localParamsA; hDPI = hDPIA; vDPI = vDPIA; rotate = rotateA; @@ -4303,7 +4565,11 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, strokeOpacity = 1; fillOverprint = gFalse; strokeOverprint = gFalse; - renderingIntent = gfxRenderingIntentRelativeColorimetric; + if (localParams) { + renderingIntent = localParams->getDefaultRenderingIntent(); + } else { + renderingIntent = gfxRenderingIntentRelativeColorimetric; + } overprintMode = 0; transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL; @@ -4316,6 +4582,7 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, lineCap = 0; miterLimit = 10; strokeAdjust = gFalse; + alphaIsShape = gFalse; font = NULL; fontSize = 0; @@ -4577,6 +4844,12 @@ void GfxState::setStrokePattern(GfxPattern *pattern) { strokePattern = pattern; } +void GfxState::setRenderingIntent(GfxRenderingIntent ri) { + if (!(localParams && localParams->getForceRenderingIntent())) { + renderingIntent = ri; + } +} + void GfxState::setTransfer(Function **funcs) { int i; @@ -4651,35 +4924,36 @@ void GfxState::clipToStrokePath() { // There are two cases for each point on the path: // (1) miter join, under miter limit => compute the miter point // (2) all other joins and caps => use the path point +/- 0.5 * line width - double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double uxMin = 0, uyMin = 0, uxMax = 0, uyMax = 0; double w = 0.5 * lineWidth; for (int i = 0; i < path->getNumSubpaths(); ++i) { GfxSubpath *subpath = path->getSubpath(i); - for (int j = 0; j < subpath->getNumPoints(); ++j) { + int nPoints; + if (subpath->isClosed()) { + nPoints = subpath->getNumPoints() - 1; + } else { + nPoints = subpath->getNumPoints(); + } + for (int j = 0; j < nPoints; ++j) { double x1 = subpath->getX(j); double y1 = subpath->getY(j); if (i == 0 && j == 0) { - xMin = xMax = x1; - yMin = yMax = y1; + uxMin = uxMax = x1; + uyMin = uyMax = y1; } GBool useMiter = gFalse; if (lineJoin == 0 && // miter join - ((j > 0 && j < subpath->getNumPoints() - 1) || subpath->isClosed())) { + (subpath->isClosed() || (j > 0 && j < subpath->getNumPoints() - 1))) { double x0, y0, x2, y2; - if (j > 0) { + if (j == 0) { + x0 = subpath->getX(nPoints - 1); + y0 = subpath->getY(nPoints - 1); + } else { x0 = subpath->getX(j - 1); y0 = subpath->getY(j - 1); - } else { - x0 = subpath->getLastX(); - y0 = subpath->getLastY(); - } - if (j < subpath->getNumPoints() - 1) { - x2 = subpath->getX(j + 1); - y2 = subpath->getY(j + 1); - } else { - x2 = subpath->getX(0); - y2 = subpath->getY(0); } + x2 = subpath->getX(j + 1); + y2 = subpath->getY(j + 1); if ((fabs(x1 - x0) > 0.0001 || fabs(y1 - y0) > 0.0001) && (fabs(x2 - x1) > 0.0001 || fabs(y2 - y1) > 0.0001)) { double d01 = 1 / sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); @@ -4704,15 +4978,15 @@ void GfxState::clipToStrokePath() { } double mx = ax + m * w * ux; double my = ay + m * w * uy; - if (mx < xMin) { - xMin = mx; - } else if (mx > xMax) { - xMax = mx; + if (mx < uxMin) { + uxMin = mx; + } else if (mx > uxMax) { + uxMax = mx; } - if (my < yMin) { - yMin = my; - } else if (my > yMax) { - yMax = my; + if (my < uyMin) { + uyMin = my; + } else if (my > uyMax) { + uyMax = my; } useMiter = gTrue; } @@ -4720,66 +4994,71 @@ void GfxState::clipToStrokePath() { } } if (!useMiter) { - if (x1 - w < xMin) { - xMin = x1 - w; + if (x1 - w < uxMin) { + uxMin = x1 - w; } - if (x1 + w > xMax) { - xMax = x1 + w; + if (x1 + w > uxMax) { + uxMax = x1 + w; } - if (y1 - w < yMin) { - yMin = y1 - w; + if (y1 - w < uyMin) { + uyMin = y1 - w; } - if (y1 + w > yMax) { - yMax = y1 + w; + if (y1 + w > uyMax) { + uyMax = y1 + w; } } } } - double xx, yy; - transform(xMin, yMin, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; - } - transform(xMin, yMax, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; - } - transform(xMax, yMin, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; - } - transform(xMax, yMax, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; + double dxMin, dyMin, dxMax, dyMax, xx, yy; + transform(uxMin, uyMin, &xx, &yy); + dxMin = dxMax = xx; + dyMin = dyMax = yy; + transform(uxMin, uyMax, &xx, &yy); + if (xx < dxMin) { + dxMin = xx; + } else if (xx > dxMax) { + dxMax = xx; + } + if (yy < dyMin) { + dyMin = yy; + } else if (yy > dyMax) { + dyMax = yy; + } + transform(uxMax, uyMin, &xx, &yy); + if (xx < dxMin) { + dxMin = xx; + } else if (xx > dxMax) { + dxMax = xx; + } + if (yy < dyMin) { + dyMin = yy; + } else if (yy > dyMax) { + dyMax = yy; + } + transform(uxMax, uyMax, &xx, &yy); + if (xx < dxMin) { + dxMin = xx; + } else if (xx > dxMax) { + dxMax = xx; + } + if (yy < dyMin) { + dyMin = yy; + } else if (yy > dyMax) { + dyMax = yy; + } + + if (dxMin > clipXMin) { + clipXMin = dxMin; + } + if (dyMin > clipYMin) { + clipYMin = dyMin; + } + if (dxMax < clipXMax) { + clipXMax = dxMax; + } + if (dyMax < clipYMax) { + clipYMax = dyMax; } } diff --git a/src/xpdf-4.04/xpdf/GfxState.h b/src/xpdf-4.04/xpdf/GfxState.h index 60d4852..594329a 100644 --- a/src/xpdf-4.04/xpdf/GfxState.h +++ b/src/xpdf-4.04/xpdf/GfxState.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" #include "Function.h" @@ -26,6 +22,7 @@ class GfxDeviceNColorSpace; class GfxSeparationColorSpace; class GfxShading; class GfxState; +class LocalParams; //------------------------------------------------------------------------ // GfxBlendMode @@ -663,6 +660,7 @@ class GfxTilingPattern: public GfxPattern { { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; } double *getMatrix() { return matrix; } Object *getContentStreamRef() { return &contentStreamRef; } + GBool usesBlendMode(XRef *xref); private: @@ -670,6 +668,16 @@ class GfxTilingPattern: public GfxPattern { double *bboxA, double xStepA, double yStepA, Object *resDictA, double *matrixA, Object *contentStreamA); + GBool scanResourcesForBlendMode(Object *resDict2, + char *scannedObjs, XRef *xref); + GBool scanExtGStateForBlendMode(Object *gsObj, + char *scannedObjs, XRef *xref); + GBool scanSoftMaskForBlendMode(Object *softMaskObj, + char *scannedObjs, XRef *xref); + GBool scanPatternForBlendMode(Object *patternObj, + char *scannedObjs, XRef *xref); + GBool scanXObjectForBlendMode(Object *xObj, + char *scannedObjs, XRef *xref); int paintType; int tilingType; @@ -883,7 +891,7 @@ class GfxGouraudTriangleShading: public GfxShading { void getTriangle(int i, double *x0, double *y0, double *color0, double *x1, double *y1, double *color1, double *x2, double *y2, double *color2); - void getBBox(double *xMin, double *yMin, double *xMax, double *yMax); + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA); void getColor(double *in, GfxColor *out); private: @@ -923,7 +931,7 @@ class GfxPatchMeshShading: public GfxShading { int getNComps() { return nComps; } int getNPatches() { return nPatches; } GfxPatch *getPatch(int i) { return &patches[i]; } - void getBBox(double *xMin, double *yMin, double *xMax, double *yMax); + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA); void getColor(double *in, GfxColor *out); private: @@ -1121,7 +1129,8 @@ class GfxState { // Construct a default GfxState, for a device with resolution // x , page box , page rotation , and // coordinate system specified by . - GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, + GfxState(LocalParams *localParamsA, + double hDPIA, double vDPIA, PDFRectangle *pageBox, int rotateA, GBool upsideDown ); @@ -1177,6 +1186,7 @@ class GfxState { int getLineCap() { return lineCap; } double getMiterLimit() { return miterLimit; } GBool getStrokeAdjust() { return strokeAdjust; } + GBool getAlphaIsShape() { return alphaIsShape; } GfxFont *getFont() { return font; } double getFontSize() { return fontSize; } double *getTextMat() { return textMat; } @@ -1238,7 +1248,7 @@ class GfxState { void setFillOverprint(GBool op) { fillOverprint = op; } void setStrokeOverprint(GBool op) { strokeOverprint = op; } void setOverprintMode(int opm) { overprintMode = opm; } - void setRenderingIntent(GfxRenderingIntent ri) { renderingIntent = ri; } + void setRenderingIntent(GfxRenderingIntent ri); void setTransfer(Function **funcs); void setLineWidth(double width) { lineWidth = width; } void setLineDash(double *dash, int length, double start); @@ -1247,6 +1257,7 @@ class GfxState { void setLineCap(int lineCap1) { lineCap = lineCap1; } void setMiterLimit(double limit) { miterLimit = limit; } void setStrokeAdjust(GBool sa) { strokeAdjust = sa; } + void setAlphaIsShape(GBool ais) { alphaIsShape = ais; } void setFont(GfxFont *fontA, double fontSizeA) { font = fontA; fontSize = fontSizeA; } void setTextMat(double a, double b, double c, @@ -1306,6 +1317,8 @@ class GfxState { private: + LocalParams *localParams; + double hDPI, vDPI; // resolution double ctm[6]; // coord transform matrix double px1, py1, px2, py2; // page corners (user coords) @@ -1339,6 +1352,7 @@ class GfxState { int lineCap; // line cap style double miterLimit; // line miter limit GBool strokeAdjust; // stroke adjustment + GBool alphaIsShape; GfxFont *font; // font double fontSize; // font size diff --git a/src/xpdf-4.04/xpdf/GlobalParams.cc b/src/xpdf-4.04/xpdf/GlobalParams.cc index 5fd4393..92f77d7 100644 --- a/src/xpdf-4.04/xpdf/GlobalParams.cc +++ b/src/xpdf-4.04/xpdf/GlobalParams.cc @@ -8,10 +8,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include @@ -44,9 +40,11 @@ #include "GlobalParams.h" #ifdef _WIN32 +#ifndef __GNUC__ # define strcasecmp stricmp # define strncasecmp strnicmp #endif +#endif #if MULTITHREADED # define lockGlobalParams gLockMutex(&mutex) @@ -81,34 +79,119 @@ static struct { const char *ttFileName; const char *macFileName; // may be .dfont, .ttf, or .ttc const char *macFontName; // font name inside .dfont or .ttc + const char *fcFontName; // fontconfig font name const char *obliqueFont; // name of font to oblique double obliqueFactor; // oblique sheer factor } displayFontTab[] = { - {"Courier", "n022003l.pfb", "cour.ttf", "Courier", "Courier", NULL, 0}, - {"Courier-Bold", "n022004l.pfb", "courbd.ttf", "Courier", "Courier Bold", NULL, 0}, - {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf", "Courier", "Courier Bold Oblique", "Courier-Bold", 0.212557}, - {"Courier-Oblique", "n022023l.pfb", "couri.ttf", "Courier", "Courier Oblique", "Courier", 0.212557}, - {"Helvetica", "n019003l.pfb", "arial.ttf", "Helvetica", "Helvetica", NULL, 0}, - {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf", "Helvetica", "Helvetica Bold", NULL, 0}, - {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf", "Helvetica", "Helvetica Bold Oblique", "Helvetica-Bold", 0.212557}, - {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf", "Helvetica", "Helvetica Oblique", "Helvetica", 0.212557}, - {"Symbol", "s050000l.pfb", NULL, "Symbol", "Symbol", NULL, 0}, - {"Times-Bold", "n021004l.pfb", "timesbd.ttf", "Times", "Times Bold", NULL, 0}, - {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf", "Times", "Times Bold Italic", NULL, 0}, - {"Times-Italic", "n021023l.pfb", "timesi.ttf", "Times", "Times Italic", NULL, 0}, - {"Times-Roman", "n021003l.pfb", "times.ttf", "Times", "Times Roman", NULL, 0}, - {"ZapfDingbats", "d050000l.pfb", NULL, "ZapfDingbats", "Zapf Dingbats", NULL, 0}, + {"Courier", // name + "n022003l.pfb", // t1FileName + "cour.ttf", // ttFileName + "Courier", "Courier", // macFileName, macFontName + "NimbusMonoPS-Regular", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Courier-Bold", // name + "n022004l.pfb", // t1FileName + "courbd.ttf", // ttFileName + "Courier", "Courier Bold", // macFileName, macFontName + "NimbusMonoPS-Bold", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Courier-BoldOblique", // name + "n022024l.pfb", // t1FileName + "courbi.ttf", // ttFileName + "Courier", "Courier Bold Oblique", // macFileName, macFontName + "NimbusMonoPS-BoldItalic", // fcFontName + "Courier-Bold", 0.212557 // obliqueFont, obliqueFactor + }, + {"Courier-Oblique", // name + "n022023l.pfb", // t1FileName + "couri.ttf", // ttFileName + "Courier", "Courier Oblique", // macFileName, macFontName + "NimbusMonoPS-Italic", // fcFontName + "Courier", 0.212557 // obliqueFont, obliqueFactor + }, + {"Helvetica", // name + "n019003l.pfb", // t1FileName + "arial.ttf", // ttFileName + "Helvetica", "Helvetica", // macFileName, macFontName + "NimbusSans-Regular", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Helvetica-Bold", // name + "n019004l.pfb", // t1FileName + "arialbd.ttf", // ttFileName + "Helvetica", "Helvetica Bold", // macFileName, macFontName + "NimbusSans-Bold", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Helvetica-BoldOblique", // name + "n019024l.pfb", // t1FileName + "arialbi.ttf", // ttFileName + "Helvetica", "Helvetica Bold Oblique", // macFileName, macFontName + "NimbusSans-BoldItalic", // fcFontName + "Helvetica-Bold", 0.212557 // obliqueFont, obliqueFactor + }, + {"Helvetica-Oblique", // name + "n019023l.pfb", // t1FileName + "ariali.ttf", // ttFileName + "Helvetica", "Helvetica Oblique", // macFileName, macFontName + "NimbusSans-Italic", // fcFontName + "Helvetica", 0.212557 // obliqueFont, obliqueFactor + }, + {"Symbol", // name + "s050000l.pfb", // t1FileName + NULL, // ttFileName + "Symbol", "Symbol", // macFileName, macFontName + "Standard Symbols PS", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Times-Bold", // name + "n021004l.pfb", // t1FileName + "timesbd.ttf", // ttFileName + "Times", "Times Bold", // macFileName, macFontName + "NimbusRoman-Bold", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Times-BoldItalic", // name + "n021024l.pfb", // t1FileName + "timesbi.ttf", // ttFileName + "Times", "Times Bold Italic", // macFileName, macFontName + "NimbusRoman-BoldItalic", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Times-Italic", // name + "n021023l.pfb", // t1FileName + "timesi.ttf", // ttFileName + "Times", "Times Italic", // macFileName, macFontName + "NimbusRoman-Italic", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"Times-Roman", // name + "n021003l.pfb", // t1FileName + "times.ttf", // ttFileName + "Times", "Times Roman", // macFileName, macFontName + "NimbusRoman-Regular", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, + {"ZapfDingbats", // name + "d050000l.pfb", // t1FileName + NULL, // ttFileName + "ZapfDingbats", "Zapf Dingbats", // macFileName, macFontName + "D050000L", // fcFontName + NULL, 0 // obliqueFont, obliqueFactor + }, {NULL} }; -#ifdef _WIN32 static const char *displayFontDirs[] = { +#ifdef BASE14_FONT_DIR + BASE14_FONT_DIR, +#endif +#ifdef _WIN32 "c:/windows/fonts", "c:/winnt/fonts", - NULL -}; -#else -static const char *displayFontDirs[] = { +#else // _WIN32 "/usr/share/ghostscript/fonts", "/usr/local/share/ghostscript/fonts", "/usr/share/fonts/default/Type1", @@ -117,9 +200,9 @@ static const char *displayFontDirs[] = { #if defined(__sun) && defined(__SVR4) "/usr/sfw/share/ghostscript/fonts", #endif +#endif // _WIN32 NULL }; -#endif #ifdef __APPLE__ static const char *macSystemFontPath = "/System/Library/Fonts"; @@ -179,7 +262,7 @@ class SysFontInfo { ~SysFontInfo(); GString *mungeName1(GString *in); GString *mungeName2(GString *in); - void mungeName3(GString *name, GBool *bold, GBool *italic); + void mungeName3(GString *nameA, GBool *bold, GBool *italic); int match(GString *nameA); }; @@ -256,24 +339,24 @@ GString *SysFontInfo::mungeName2(GString *in) { // Remove trailing bold/italic/regular/roman tags from the name. // (Note: the names have already been uppercased by mungeName1/2.) -void SysFontInfo::mungeName3(GString *name, GBool *bold, GBool *italic) { +void SysFontInfo::mungeName3(GString *nameA, GBool *bold, GBool *italic) { *bold = gFalse; *italic = gFalse; - int n = name->getLength(); + int n = nameA->getLength(); while (1) { - if (n >= 4 && !strcmp(name->getCString() + n - 4, "BOLD")) { - name->del(n - 4, 4); + if (n >= 4 && !strcmp(nameA->getCString() + n - 4, "BOLD")) { + nameA->del(n - 4, 4); n -= 4; *bold = gTrue; - } else if (n >= 6 && !strcmp(name->getCString() + n - 6, "ITALIC")) { - name->del(n - 6, 6); + } else if (n >= 6 && !strcmp(nameA->getCString() + n - 6, "ITALIC")) { + nameA->del(n - 6, 6); n -= 6; *italic = gTrue; - } else if (n >= 7 && !strcmp(name->getCString() + n - 7, "REGULAR")) { - name->del(n - 7, 7); + } else if (n >= 7 && !strcmp(nameA->getCString() + n - 7, "REGULAR")) { + nameA->del(n - 7, 7); n -= 7; - } else if (n >= 5 && !strcmp(name->getCString() + n - 5, "ROMAN")) { - name->del(n - 5, 5); + } else if (n >= 5 && !strcmp(nameA->getCString() + n - 5, "ROMAN")) { + nameA->del(n - 5, 5); n -= 5; } else { break; @@ -655,7 +738,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) { base14SysFonts = new GHash(gTrue); sysFonts = new SysFontList(); #if HAVE_PAPER_H - char *paperName; + const char *paperName; const struct paper *paperType; paperinit(); if ((paperName = systempapername())) { @@ -681,7 +764,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) { psShrinkLarger = gTrue; psCenter = gTrue; psDuplex = gFalse; - psLevel = psLevel2; + psLevel = psLevel3; psResidentFonts = new GHash(gTrue); psResidentFonts16 = new GList(); psResidentFontsCC = new GList(); @@ -711,11 +794,27 @@ GlobalParams::GlobalParams(const char *cfgFileName) { textKeepTinyChars = gTrue; initialZoom = new GString("125"); defaultFitZoom = 0; + zoomScaleFactor = 1; + zoomValues = new GList(); + zoomValues->append(new GString("25")); + zoomValues->append(new GString("50")); + zoomValues->append(new GString("75")); + zoomValues->append(new GString("100")); + zoomValues->append(new GString("110")); + zoomValues->append(new GString("125")); + zoomValues->append(new GString("150")); + zoomValues->append(new GString("175")); + zoomValues->append(new GString("200")); + zoomValues->append(new GString("300")); + zoomValues->append(new GString("400")); + zoomValues->append(new GString("600")); + zoomValues->append(new GString("800")); initialDisplayMode = new GString("continuous"); initialToolbarState = gTrue; initialSidebarState = gTrue; initialSidebarWidth = 0; initialSelectMode = new GString("linear"); + initialMaximized = gFalse; maxTileWidth = 1500; maxTileHeight = 1500; tileCacheSize = 10; @@ -738,12 +837,14 @@ GlobalParams::GlobalParams(const char *cfgFileName) { drawAnnotations = gTrue; drawFormFields = gTrue; enableXFA = gTrue; + preferXFAFieldValues = gTrue; overprintPreview = gFalse; paperColor = new GString("#ffffff"); matteColor = new GString("#808080"); fullScreenMatteColor = new GString("#000000"); selectionColor = new GString("#8080ff"); reverseVideoInvertImages = gFalse; + allowLinksToChangeZoom = gTrue; launchCommand = NULL; movieCommand = NULL; defaultPrinter = NULL; @@ -751,10 +852,14 @@ GlobalParams::GlobalParams(const char *cfgFileName) { mapUnknownCharNames = gFalse; mapExtTrueTypeFontsViaUnicode = gTrue; useTrueTypeUnicodeMapping = gFalse; + ignoreWrongSizeToUnicode = gFalse; droppedFonts = new GHash(gTrue); + separateRotatedText = gFalse; + discardCoveredText = gFalse; createDefaultKeyBindings(); popupMenuCmds = new GList(); - tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state"); + initStateFilePaths(); + saveSessionOnQuit = gTrue; savePageNumbers = gTrue; printCommands = gFalse; printStatusInfo = gFalse; @@ -790,38 +895,8 @@ GlobalParams::GlobalParams(const char *cfgFileName) { map = new UnicodeMap("UCS-2", gTrue, &mapUCS2); residentUnicodeMaps->add(map->getEncodingName(), map); - // look for a user config file, then a system-wide config file - f = NULL; - fileName = NULL; - if (cfgFileName && cfgFileName[0]) { - fileName = new GString(cfgFileName); - if (!(f = fopen(fileName->getCString(), "r"))) { - delete fileName; - } - } - if (!f) { - fileName = appendToPath(getHomeDir(), xpdfUserConfigFile); - if (!(f = fopen(fileName->getCString(), "r"))) { - delete fileName; - } - } - if (!f) { -#ifdef _WIN32 - char buf[512]; - i = GetModuleFileNameA(NULL, buf, sizeof(buf)); - if (i <= 0 || i >= sizeof(buf)) { - // error or path too long for buffer - just use the current dir - buf[0] = '\0'; - } - fileName = grabPath(buf); - appendToPath(fileName, xpdfSysConfigFile); -#else - fileName = new GString(xpdfSysConfigFile); -#endif - if (!(f = fopen(fileName->getCString(), "r"))) { - delete fileName; - } - } + // read the config file + f = openConfigFile(cfgFileName, &fileName); if (f) { parseFile(fileName, f); delete fileName; @@ -1011,6 +1086,130 @@ void GlobalParams::createDefaultKeyBindings() { xpdfKeyContextAny, "zoomFitWidth")); } +void GlobalParams::initStateFilePaths() { +#ifdef _WIN32 + // Windows state files are {APPDATA}/xpdf/xpdf.pages etc + char path[MAX_PATH]; + if (SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, + SHGFP_TYPE_CURRENT, path) != S_OK) { + return; + } + GString *stateDir = appendToPath(new GString(path), "xpdf"); + CreateDirectoryA(stateDir->getCString(), NULL); + pagesFile = appendToPath(stateDir->copy(), "xpdf.pages"); + tabStateFile = appendToPath(stateDir->copy(), "xpdf.tab-state"); + sessionFile = appendToPath(stateDir, "xpdf.session"); +#elif USE_XDG + // XDG state files are {XDG_STATE}/xpdf/pages etc + char *path = getenv("XDG_STATE_HOME"); + GString *stateDir; + if (path) { + stateDir = new GString(path); + } else { + stateDir = appendToPath(getHomeDir(), ".local/state"); + } + createDir(stateDir->getCString(), 0700); + appendToPath(stateDir, "xpdf"); + createDir(stateDir->getCString(), 0700); + pagesFile = appendToPath(stateDir->copy(), "pages"); + tabStateFile = appendToPath(stateDir->copy(), "tab-state"); + sessionFile = appendToPath(stateDir, "session"); +#else + // Unix (non-XDG) state files are ~/.xpdf.pages etc + GString *stateDir = getHomeDir(); + pagesFile = appendToPath(stateDir->copy(), ".xpdf.pages"); + tabStateFile = appendToPath(stateDir->copy(), ".xpdf.tab-state"); + sessionFile = appendToPath(stateDir, ".xpdf.session"); +#endif +} + +// Try all supported paths for the config file. +FILE *GlobalParams::openConfigFile(const char *cfgFileName, + GString **fileName) { + FILE *f = NULL; + GString *actualName = NULL; + + //--- try the path specified on the command line + if (cfgFileName && cfgFileName[0]) { + actualName = new GString(cfgFileName); + if (!(f = fopen(actualName->getCString(), "r"))) { + delete actualName; + } + } + + //--- try the XDG config path: {XDG_CONFIG}/xpdf/xpdfrc +#if USE_XDG + if (!f) { + char *path = getenv("XDG_CONFIG_HOME"); + if (path) { + actualName = new GString(path); + } else { + actualName = appendToPath(getHomeDir(), ".config"); + } + appendToPath(actualName, "xpdf/xpdfrc"); + if (!(f = fopen(actualName->getCString(), "r"))) { + delete actualName; + } + } +#endif + +#ifdef _WIN32 + //--- try the Windows user path: {APPDATA}/xpdf/xpdfrc + if (!f) { + char path[MAX_PATH]; + if (SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path) + == S_OK) { + actualName = appendToPath(new GString(path), "xpdf/xpdfrc"); + if (!(f = fopen(actualName->getCString(), "r"))) { + delete actualName; + } + } + } + +#else + //--- try the Unix user path: ~/.xpdfrc + if (!f) { + actualName = appendToPath(getHomeDir(), ".xpdfrc"); + if (!(f = fopen(actualName->getCString(), "r"))) { + delete actualName; + } + } +#endif + +#ifdef _WIN32 + //--- try the Windows system path: {EXEDIR}/xpdfrc + if (!f) { + char buf[512]; + int i = GetModuleFileNameA(NULL, buf, sizeof(buf)); + if (i <= 0 || i >= sizeof(buf)) { + // error or path too long for buffer - just use the current dir + buf[0] = '\0'; + } + actualName = grabPath(buf); + appendToPath(actualName, "xpdfrc"); + if (!(f = fopen(actualName->getCString(), "r"))) { + delete actualName; + } + } + +#else + //--- try the Unix system path: {xpdfSysConfigFile} + if (!f) { + actualName = new GString(xpdfSysConfigFile); + if (!(f = fopen(actualName->getCString(), "r"))) { + delete actualName; + } + } +#endif + + if (f) { + *fileName = actualName; + } else { + *fileName = NULL; + } + return f; +} + void GlobalParams::parseFile(GString *fileName, FILE *f) { int line; char buf[512]; @@ -1151,6 +1350,10 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parseString("initialZoom", &initialZoom, tokens, fileName, line); } else if (!cmd->cmp("defaultFitZoom")) { parseInteger("defaultFitZoom", &defaultFitZoom, tokens, fileName, line); + } else if (!cmd->cmp("zoomScaleFactor")) { + parseZoomScaleFactor(tokens, fileName, line); + } else if (!cmd->cmp("zoomValues")) { + parseZoomValues(tokens, fileName, line); } else if (!cmd->cmp("initialDisplayMode")) { parseString("initialDisplayMode", &initialDisplayMode, tokens, fileName, line); @@ -1166,6 +1369,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("initialSelectMode")) { parseString("initialSelectMode", &initialSelectMode, tokens, fileName, line); + } else if (!cmd->cmp("initialMaximized")) { + parseYesNo("initialMaximized", &initialMaximized, + tokens, fileName, line); } else if (!cmd->cmp("maxTileWidth")) { parseInteger("maxTileWidth", &maxTileWidth, tokens, fileName, line); } else if (!cmd->cmp("maxTileHeight")) { @@ -1223,6 +1429,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("enableXFA")) { parseYesNo("enableXFA", &enableXFA, tokens, fileName, line); + } else if (!cmd->cmp("preferXFAFieldValues")) { + parseYesNo("preferXFAFieldValues", &preferXFAFieldValues, + tokens, fileName, line); } else if (!cmd->cmp("overprintPreview")) { parseYesNo("overprintPreview", &overprintPreview, tokens, fileName, line); @@ -1238,6 +1447,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("reverseVideoInvertImages")) { parseYesNo("reverseVideoInvertImages", &reverseVideoInvertImages, tokens, fileName, line); + } else if (!cmd->cmp("allowLinksToChangeZoom")) { + parseYesNo("allowLinksToChangeZoom", &allowLinksToChangeZoom, + tokens, fileName, line); } else if (!cmd->cmp("launchCommand")) { parseString("launchCommand", &launchCommand, tokens, fileName, line); } else if (!cmd->cmp("movieCommand")) { @@ -1255,11 +1467,19 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { &mapExtTrueTypeFontsViaUnicode, tokens, fileName, line); } else if (!cmd->cmp("useTrueTypeUnicodeMapping")) { - parseYesNo("useTrueTypeUnicodeMapping", - &useTrueTypeUnicodeMapping, + parseYesNo("useTrueTypeUnicodeMapping", &useTrueTypeUnicodeMapping, + tokens, fileName, line); + } else if (!cmd->cmp("ignoreWrongSizeToUnicode")) { + parseYesNo("ignoreWrongSizeToUnicode", &ignoreWrongSizeToUnicode, tokens, fileName, line); } else if (!cmd->cmp("dropFont")) { parseDropFont(tokens, fileName, line); + } else if (!cmd->cmp("separateRotatedText")) { + parseYesNo("separateRotatedText", &separateRotatedText, + tokens, fileName, line); + } else if (!cmd->cmp("discardCoveredText")) { + parseYesNo("discardCoveredText", &discardCoveredText, + tokens, fileName, line); } else if (!cmd->cmp("bind")) { parseBind(tokens, fileName, line); } else if (!cmd->cmp("unbind")) { @@ -1268,6 +1488,11 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parsePopupMenuCmd(tokens, fileName, line); } else if (!cmd->cmp("tabStateFile")) { parseString("tabStateFile", &tabStateFile, tokens, fileName, line); + } else if (!cmd->cmp("sessionFile")) { + parseString("sessionFile", &sessionFile, tokens, fileName, line); + } else if (!cmd->cmp("saveSessionOnQuit")) { + parseYesNo("saveSessionOnQuit", &saveSessionOnQuit, + tokens, fileName, line); } else if (!cmd->cmp("savePageNumbers")) { parseYesNo("savePageNumbers", &savePageNumbers, tokens, fileName, line); } else if (!cmd->cmp("printCommands")) { @@ -1967,6 +2192,59 @@ void GlobalParams::parsePopupMenuCmd(GList *tokens, cmds)); } +void GlobalParams::parseZoomScaleFactor(GList *tokens, + GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad 'zoomScaleFactor' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + GString *tok = (GString *)tokens->get(1); + if (tok->getLength() == 0) { + error(errConfig, -1, "Bad 'zoomScaleFactor' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + if (tok->cmp("actual") == 0) { + zoomScaleFactor = -1; + } else { + for (int i = 0; i < tok->getLength(); ++i) { + if (!((tok->getChar(i) >= '0' && tok->getChar(i) <= '9') || + tok->getChar(i) == '.')) { + error(errConfig, -1, "Bad 'zoomScaleFactor' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + } + zoomScaleFactor = atof(tok->getCString()); + } +} + +void GlobalParams::parseZoomValues(GList *tokens, + GString *fileName, int line) { + if (tokens->getLength() < 2) { + error(errConfig, -1, "Bad 'zoomValues' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + for (int i = 1; i < tokens->getLength(); ++i) { + GString *tok = (GString *)tokens->get(i); + for (int j = 0; j < tok->getLength(); ++j) { + if (tok->getChar(j) < '0' || tok->getChar(j) > '9') { + error(errConfig, -1, "Bad 'zoomValues' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + } + } + deleteGList(zoomValues, GString); + zoomValues = new GList(); + for (int i = 1; i < tokens->getLength(); ++i) { + GString *tok = (GString *)tokens->get(i); + zoomValues->append(tok->copy()); + } +} + void GlobalParams::parseYesNo(const char *cmdName, GBool *flag, GList *tokens, GString *fileName, int line) { GString *tok; @@ -2098,6 +2376,7 @@ GlobalParams::~GlobalParams() { deleteGList(psResidentFontsCC, PSFontParam16); delete textEncoding; delete initialZoom; + deleteGList(zoomValues, GString); delete initialDisplayMode; delete initialSelectMode; if (paperColor) { @@ -2124,7 +2403,9 @@ GlobalParams::~GlobalParams() { delete droppedFonts; deleteGList(keyBindings, KeyBinding); deleteGList(popupMenuCmds, PopupMenuCmd); + delete pagesFile; delete tabStateFile; + delete sessionFile; delete debugLogFile; cMapDirs->startIter(&iter); @@ -2249,6 +2530,10 @@ void GlobalParams::setupBaseFonts(const char *dir) { GList *dfontFontNames; GBool found; int k; +#endif +#if HAVE_FONTCONFIG + SysFontInfo *fi; + GString *fcName; #endif FILE *f; int i, j; @@ -2258,6 +2543,14 @@ void GlobalParams::setupBaseFonts(const char *dir) { #endif #ifdef __APPLE__ dfontFontNames = NULL; +#endif +#ifdef _WIN32 + if (winFontDir[0]) { + sysFonts->scanWindowsFonts(winFontDir); + } +#endif +#if HAVE_FONTCONFIG + sysFonts->scanFontconfigFonts(); #endif for (i = 0; displayFontTab[i].name; ++i) { if (fontFiles->lookup(displayFontTab[i].name)) { @@ -2334,6 +2627,16 @@ void GlobalParams::setupBaseFonts(const char *dir) { } } #endif // __APPLE__ +#if HAVE_FONTCONFIG + if (!fileName) { + fcName = new GString(displayFontTab[i].fcFontName); + if ((fi = sysFonts->find(fcName))) { + fileName = fi->path->copy(); + fontNum = fi->fontNum; + } + delete fcName; + } +#endif // HAVE_FONTCONFIG // On Linux, this checks the "standard" ghostscript font // directories. On Windows, it checks the "standard" system font // directories (because SHGetSpecialFolderPath(CSIDL_FONTS) @@ -2383,14 +2686,6 @@ void GlobalParams::setupBaseFonts(const char *dir) { } } } -#ifdef _WIN32 - if (winFontDir[0]) { - sysFonts->scanWindowsFonts(winFontDir); - } -#endif -#if HAVE_FONTCONFIG - sysFonts->scanFontconfigFonts(); -#endif } //------------------------------------------------------------------------ @@ -2950,6 +3245,19 @@ int GlobalParams::getDefaultFitZoom() { return z; } +double GlobalParams::getZoomScaleFactor() { + double z; + + lockGlobalParams; + z = zoomScaleFactor; + unlockGlobalParams; + return z; +} + +GList *GlobalParams::getZoomValues() { + return zoomValues; +} + GString *GlobalParams::getInitialDisplayMode() { GString *s; @@ -2995,6 +3303,15 @@ GString *GlobalParams::getInitialSelectMode() { return s; } +GBool GlobalParams::getInitialMaximized() { + GBool state; + + lockGlobalParams; + state = initialMaximized; + unlockGlobalParams; + return state; +} + int GlobalParams::getMaxTileWidth() { int w; @@ -3194,6 +3511,15 @@ GBool GlobalParams::getEnableXFA() { return xfa; } +GBool GlobalParams::getPreferXFAFieldValues() { + GBool xfa; + + lockGlobalParams; + xfa = preferXFAFieldValues; + unlockGlobalParams; + return xfa; +} + GString *GlobalParams::getPaperColor() { @@ -3241,6 +3567,15 @@ GBool GlobalParams::getReverseVideoInvertImages() { return invert; } +GBool GlobalParams::getAllowLinksToChangeZoom() { + GBool allow; + + lockGlobalParams; + allow = allowLinksToChangeZoom; + unlockGlobalParams; + return allow; +} + GString *GlobalParams::getDefaultPrinter() { GString *s; @@ -3286,6 +3621,15 @@ GBool GlobalParams::getUseTrueTypeUnicodeMapping() { return use; } +GBool GlobalParams::getIgnoreWrongSizeToUnicode() { + GBool ignore; + + lockGlobalParams; + ignore = ignoreWrongSizeToUnicode; + unlockGlobalParams; + return ignore; +} + GBool GlobalParams::isDroppedFont(const char *fontName) { GBool isDropped; @@ -3295,6 +3639,24 @@ GBool GlobalParams::isDroppedFont(const char *fontName) { return isDropped; } +GBool GlobalParams::getSeparateRotatedText() { + GBool sep; + + lockGlobalParams; + sep = separateRotatedText; + unlockGlobalParams; + return sep; +} + +GBool GlobalParams::getDiscardCoveredText() { + GBool discard; + + lockGlobalParams; + discard = discardCoveredText; + unlockGlobalParams; + return discard; +} + GList *GlobalParams::getKeyBinding(int code, int mods, int context) { KeyBinding *binding; GList *cmds; @@ -3347,6 +3709,15 @@ PopupMenuCmd *GlobalParams::getPopupMenuCmd(int idx) { return cmd; } +GString *GlobalParams::getPagesFile() { + GString *s; + + lockGlobalParams; + s = pagesFile->copy(); + unlockGlobalParams; + return s; +} + GString *GlobalParams::getTabStateFile() { GString *s; @@ -3356,6 +3727,15 @@ GString *GlobalParams::getTabStateFile() { return s; } +GString *GlobalParams::getSessionFile() { + GString *s; + + lockGlobalParams; + s = sessionFile->copy(); + unlockGlobalParams; + return s; +} + GBool GlobalParams::getSavePageNumbers() { GBool s; @@ -3365,6 +3745,15 @@ GBool GlobalParams::getSavePageNumbers() { return s; } +GBool GlobalParams::getSaveSessionOnQuit() { + GBool s; + + lockGlobalParams; + s = saveSessionOnQuit; + unlockGlobalParams; + return s; +} + GBool GlobalParams::getPrintCommands() { GBool p; @@ -3703,6 +4092,12 @@ void GlobalParams::setInitialZoom(char *s) { unlockGlobalParams; } +void GlobalParams::setDefaultFitZoom(int z) { + lockGlobalParams; + defaultFitZoom = z; + unlockGlobalParams; +} + GBool GlobalParams::setEnableFreeType(char *s) { GBool ok; @@ -3806,6 +4201,13 @@ void GlobalParams::setTabStateFile(char *tabStateFileA) { unlockGlobalParams; } +void GlobalParams::setSessionFile(char *sessionFileA) { + lockGlobalParams; + delete sessionFile; + sessionFile = new GString(sessionFileA); + unlockGlobalParams; +} + void GlobalParams::setPrintCommands(GBool printCommandsA) { lockGlobalParams; printCommands = printCommandsA; diff --git a/src/xpdf-4.04/xpdf/GlobalParams.h b/src/xpdf-4.04/xpdf/GlobalParams.h index b8299fc..b92088a 100644 --- a/src/xpdf-4.04/xpdf/GlobalParams.h +++ b/src/xpdf-4.04/xpdf/GlobalParams.h @@ -11,10 +11,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include #ifdef _WIN32 # include @@ -300,11 +296,14 @@ class GlobalParams { GBool getTextKeepTinyChars(); GString *getInitialZoom(); int getDefaultFitZoom(); + double getZoomScaleFactor(); + GList *getZoomValues(); GString *getInitialDisplayMode(); GBool getInitialToolbarState(); GBool getInitialSidebarState(); int getInitialSidebarWidth(); GString *getInitialSelectMode(); + GBool getInitialMaximized(); int getMaxTileWidth(); int getMaxTileHeight(); int getTileCacheSize(); @@ -327,12 +326,14 @@ class GlobalParams { GBool getDrawAnnotations(); GBool getDrawFormFields(); GBool getEnableXFA(); + GBool getPreferXFAFieldValues(); GBool getOverprintPreview() { return overprintPreview; } GString *getPaperColor(); GString *getMatteColor(); GString *getFullScreenMatteColor(); GString *getSelectionColor(); GBool getReverseVideoInvertImages(); + GBool getAllowLinksToChangeZoom(); GString *getLaunchCommand() { return launchCommand; } GString *getMovieCommand() { return movieCommand; } GString *getDefaultPrinter(); @@ -340,12 +341,18 @@ class GlobalParams { GBool getMapUnknownCharNames(); GBool getMapExtTrueTypeFontsViaUnicode(); GBool getUseTrueTypeUnicodeMapping(); + GBool getIgnoreWrongSizeToUnicode(); GBool isDroppedFont(const char *fontName); + GBool getSeparateRotatedText(); + GBool getDiscardCoveredText(); GList *getKeyBinding(int code, int mods, int context); GList *getAllKeyBindings(); int getNumPopupMenuCmds(); PopupMenuCmd *getPopupMenuCmd(int idx); + GString *getPagesFile(); GString *getTabStateFile(); + GString *getSessionFile(); + GBool getSaveSessionOnQuit(); GBool getSavePageNumbers(); GBool getPrintCommands(); GBool getPrintStatusInfo(); @@ -387,6 +394,7 @@ class GlobalParams { void setTextPageBreaks(GBool pageBreaks); void setTextKeepTinyChars(GBool keep); void setInitialZoom(char *s); + void setDefaultFitZoom(int z); GBool setEnableFreeType(char *s); GBool setAntialias(char *s); GBool setVectorAntialias(char *s); @@ -402,6 +410,7 @@ class GlobalParams { void setMapUnknownCharNames(GBool map); void setMapExtTrueTypeFontsViaUnicode(GBool map); void setTabStateFile(char *tabStateFileA); + void setSessionFile(char *sessionFileA); void setPrintCommands(GBool printCommandsA); void setPrintStatusInfo(GBool printStatusInfoA); void setErrQuiet(GBool errQuietA); @@ -417,6 +426,8 @@ class GlobalParams { void setDataDirVar(); void createDefaultKeyBindings(); + void initStateFilePaths(); + FILE *openConfigFile(const char *cfgFileName, GString **fileName); void parseFile(GString *fileName, FILE *f); GList *parseLineTokens(char *buf, GString *fileName, int line); void parseNameToUnicode(GList *tokens, GString *fileName, int line); @@ -447,6 +458,8 @@ class GlobalParams { const char *cmdName, GList *tokens, GString *fileName, int line); void parsePopupMenuCmd(GList *tokens, GString *fileName, int line); + void parseZoomScaleFactor(GList *tokens, GString *fileName, int line); + void parseZoomValues(GList *tokens, GString *fileName, int line); void parseYesNo(const char *cmdName, GBool *flag, GList *tokens, GString *fileName, int line); GBool parseYesNo2(char *token, GBool *flag); @@ -545,7 +558,9 @@ class GlobalParams { GBool textKeepTinyChars; // keep all characters in text output GString *initialZoom; // initial zoom level int defaultFitZoom; // default zoom factor if initialZoom is - // 'page' or 'width'. + // 'page' or 'width' + double zoomScaleFactor; // displayed zoom values are scaled by this + GList *zoomValues; // zoom values for the combo box GString *initialDisplayMode; // initial display mode (single, // continuous, etc.) GBool initialToolbarState; // initial toolbar state - open (true) @@ -554,6 +569,7 @@ class GlobalParams { // or closed (false) int initialSidebarWidth; // initial sidebar width GString *initialSelectMode; // initial selection mode (block or linear) + GBool initialMaximized; // initial window maximized state int maxTileWidth; // maximum rasterization tile width int maxTileHeight; // maximum rasterization tile height int tileCacheSize; // number of rasterization tiles in cache @@ -577,12 +593,14 @@ class GlobalParams { GBool drawAnnotations; // draw annotations or not GBool drawFormFields; // draw form fields or not GBool enableXFA; // enable XFA form parsing + GBool preferXFAFieldValues; // prefer XFA field values over AcroForm values GBool overprintPreview; // enable overprint preview GString *paperColor; // paper (page background) color GString *matteColor; // matte (background outside of page) color GString *fullScreenMatteColor; // matte color in full-screen mode GString *selectionColor; // selection color GBool reverseVideoInvertImages; // invert images in reverse video mode + GBool allowLinksToChangeZoom; // allow clicking on a link to change the zoom GString *launchCommand; // command executed for 'launch' links GString *movieCommand; // command executed for movie annotations GString *defaultPrinter; // default printer (for interactive printing @@ -594,10 +612,17 @@ class GlobalParams { GBool useTrueTypeUnicodeMapping; // use the Unicode cmaps in TrueType // fonts, rather than the PDF // ToUnicode mapping + GBool ignoreWrongSizeToUnicode; // ignore ToUnicode CMaps if their size + // (8-bit vs 16-bit) doesn't match the font GHash *droppedFonts; // dropped fonts [int] + GBool separateRotatedText; // separate text at each rotation + GBool discardCoveredText; // discard text covered by fill or image GList *keyBindings; // key & mouse button bindings [KeyBinding] GList *popupMenuCmds; // popup menu commands [PopupMenuCmd] + GString *pagesFile; // path for the page number save file GString *tabStateFile; // path for the tab state save file + GString *sessionFile; // path for the session save file + GBool saveSessionOnQuit; // save session info when xpdf is quit GBool savePageNumbers; // save page number when file is closed // and restore page number when opened GBool printCommands; // print the drawing commands diff --git a/src/xpdf-4.04/xpdf/HTMLGen.cc b/src/xpdf-4.04/xpdf/HTMLGen.cc index a077655..15bd497 100644 --- a/src/xpdf-4.04/xpdf/HTMLGen.cc +++ b/src/xpdf-4.04/xpdf/HTMLGen.cc @@ -13,7 +13,6 @@ //~ generic serif/sans-serif/monospace name) //~ - check that htmlDir exists and is a directory //~ - links: -//~ - internal links (to pages, to named destinations) //~ - links from non-text content //~ - rotated text should go in the background image //~ - metadata @@ -21,10 +20,6 @@ #include -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include #include #include "gmem.h" @@ -35,6 +30,7 @@ #include "PDFDoc.h" #include "GfxFont.h" #include "AcroForm.h" +#include "TextString.h" #include "TextOutputDev.h" #include "SplashOutputDev.h" #include "ErrorCodes.h" @@ -42,9 +38,11 @@ #include "HTMLGen.h" #ifdef _WIN32 +#ifndef __GNUC__ # define strcasecmp stricmp # define strncasecmp strnicmp #endif +#endif //------------------------------------------------------------------------ @@ -297,6 +295,7 @@ HTMLGen::HTMLGen(double backgroundResolutionA, GBool tableMode) { convertFormFields = gFalse; embedBackgroundImage = gFalse; embedFonts = gFalse; + includeMetadata = gFalse; // set up the TextOutputDev textOutControl.mode = tableMode ? textOutTableLayout : textOutReadingOrder; @@ -312,6 +311,10 @@ HTMLGen::HTMLGen(double backgroundResolutionA, GBool tableMode) { splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); fontDefns = NULL; + + nVisibleChars = 0; + nInvisibleChars = 0; + nRemovedDupChars = 0; } HTMLGen::~HTMLGen() { @@ -394,7 +397,7 @@ int HTMLGen::convertPage( // generate the background bitmap splashOut->setSkipText(!allTextInvisible, gFalse); - doc->displayPage(splashOut, pg, + doc->displayPage(splashOut, NULL, pg, backgroundResolution, backgroundResolution * vStretch, 0, gFalse, gTrue, gFalse); bitmap = splashOut->getBitmap(); @@ -409,7 +412,7 @@ int HTMLGen::convertPage( } // get the PDF text - doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + doc->displayPage(textOut, NULL, pg, 72, 72, 0, gFalse, gTrue, gFalse); doc->processLinks(textOut, pg); text = textOut->takeText(); primaryDir = text->primaryDirectionIsLR() ? 1 : -1; @@ -462,11 +465,11 @@ int HTMLGen::convertPage( llyI = bitmap->getHeight() - 1; } if (uryI <= llyI && llxI <= urxI) { - SplashColorPtr p = bitmap->getDataPtr() - + uryI * bitmap->getRowSize() + llxI * 3; - for (int y = uryI; y <= llyI; ++y) { - memset(p, 0xff, (urxI - llxI + 1) * 3); - p += bitmap->getRowSize(); + SplashColorPtr pix = bitmap->getDataPtr() + + uryI * bitmap->getRowSize() + llxI * 3; + for (y = uryI; y <= llyI; ++y) { + memset(pix, 0xff, (urxI - llxI + 1) * 3); + pix += bitmap->getRowSize(); } } @@ -483,8 +486,13 @@ int HTMLGen::convertPage( pr(writeHTML, htmlStream, "\n"); pr(writeHTML, htmlStream, "\n"); pr(writeHTML, htmlStream, "\n"); + if (includeMetadata) { + genDocMetadata(writeHTML, htmlStream); + } pr(writeHTML, htmlStream, "\n" + "\n" + "\n" + "
\n" + " \n" + "
\n" + " \n" + "
\n" + "
\n" + "\n" + "\n" + "\n"; + +static GBool createFrameIndex(char *htmlDir) { + GString *htmlFileName; + FILE *html; + int pg; + + htmlFileName = GString::format("{0:s}/index.html", htmlDir); + html = openFile(htmlFileName->getCString(), "w"); + if (!html) { + error(errIO, -1, "Couldn't open HTML file '{0:t}'", htmlFileName); + delete htmlFileName; + return gFalse; + } + delete htmlFileName; + + fputs(frameHead, html); + for (pg = firstPage; pg <= lastPage; ++pg) { + fprintf(html, "
  • page %d
  • \n", + pg, pg); + } + fputs(frameTail, html); + + fclose(html); + + return gTrue; +} diff --git a/src/xpdf-4.04/xpdf/pdftopng.cc b/src/xpdf-4.04/xpdf/pdftopng.cc index 7f3b97b..a8827cd 100644 --- a/src/xpdf-4.04/xpdf/pdftopng.cc +++ b/src/xpdf-4.04/xpdf/pdftopng.cc @@ -99,6 +99,10 @@ static void writePNGData(png_structp png, SplashBitmap *bitmap); static void finishPNG(png_structp *png, png_infop *pngInfo); int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; char *pngRoot; @@ -126,12 +130,15 @@ int main(int argc, char *argv[]) { fprintf(stderr, "The -alpha flag cannot be used with -mono\n"); goto err0; } - if (!ok || argc != 3 || printVersion || printHelp) { + if (printVersion) { + printf("pdftopng version %s [www.xpdfreader.com]\n", xpdfVersion); + printf("%s\n", xpdfCopyright); + goto err0; + } + if (!ok || argc != 3 || printHelp) { fprintf(stderr, "pdftopng version %s [www.xpdfreader.com]\n", xpdfVersion); fprintf(stderr, "%s\n", xpdfCopyright); - if (!printVersion) { - printUsage("pdftopng", " ", argDesc); - } + printUsage("pdftopng", " ", argDesc); goto err0; } fileName = argv[1]; @@ -221,7 +228,7 @@ int main(int argc, char *argv[]) { printf("[processing page %d]\n", pg); fflush(stdout); } - doc->displayPage(splashOut, pg, resolution, resolution, rotate, + doc->displayPage(splashOut, NULL, pg, resolution, resolution, rotate, gFalse, gTrue, gFalse); if (mono) { if (toStdout) { @@ -296,6 +303,13 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } static void setupPNG(png_structp *png, png_infop *pngInfo, FILE *f, diff --git a/src/xpdf-4.04/xpdf/pdftoppm.cc b/src/xpdf-4.04/xpdf/pdftoppm.cc index 28861ef..f78b959 100644 --- a/src/xpdf-4.04/xpdf/pdftoppm.cc +++ b/src/xpdf-4.04/xpdf/pdftoppm.cc @@ -98,6 +98,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; char *ppmRoot; @@ -139,12 +143,15 @@ int main(int argc, char *argv[]) { if (n > 1) { ok = gFalse; } - if (!ok || argc != 3 || printVersion || printHelp) { + if (printVersion) { + printf("pdftoppm version %s [www.xpdfreader.com]\n", xpdfVersion); + printf("%s\n", xpdfCopyright); + goto err0; + } + if (!ok || argc != 3 || printHelp) { fprintf(stderr, "pdftoppm version %s [www.xpdfreader.com]\n", xpdfVersion); fprintf(stderr, "%s\n", xpdfCopyright); - if (!printVersion) { - printUsage("pdftoppm", " ", argDesc); - } + printUsage("pdftoppm", " ", argDesc); goto err0; } fileName = argv[1]; @@ -249,7 +256,7 @@ int main(int argc, char *argv[]) { printf("[processing page %d]\n", pg); fflush(stdout); } - doc->displayPage(splashOut, pg, resolution, resolution, rotate, + doc->displayPage(splashOut, NULL, pg, resolution, resolution, rotate, gFalse, gTrue, gFalse); if (toStdout) { #ifdef _WIN32 @@ -277,4 +284,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } diff --git a/src/xpdf-4.04/xpdf/pdftops.cc b/src/xpdf-4.04/xpdf/pdftops.cc index 77e90fe..685b3aa 100644 --- a/src/xpdf-4.04/xpdf/pdftops.cc +++ b/src/xpdf-4.04/xpdf/pdftops.cc @@ -153,6 +153,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; GString *psFileName; @@ -184,12 +188,15 @@ int main(int argc, char *argv[]) { // parse args fixCommandLine(&argc, &argv); ok = parseArgs(argDesc, &argc, argv); - if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { + if (printVersion) { + printf("pdftops version %s [www.xpdfreader.com]\n", xpdfVersion); + printf("%s\n", xpdfCopyright); + exit(1); + } + if (!ok || argc < 2 || argc > 3 || printHelp) { fprintf(stderr, "pdftops version %s [www.xpdfreader.com]\n", xpdfVersion); fprintf(stderr, "%s\n", xpdfCopyright); - if (!printVersion) { - printUsage("pdftops", " []", argDesc); - } + printUsage("pdftops", " []", argDesc); exit(1); } if ((level1 ? 1 : 0) + @@ -211,6 +218,8 @@ int main(int argc, char *argv[]) { level = psLevel1; } else if (level1Sep) { level = psLevel1Sep; + } else if (level2) { + level = psLevel2; } else if (level2Gray) { level = psLevel2Gray; } else if (level2Sep) { @@ -222,7 +231,7 @@ int main(int argc, char *argv[]) { } else if (level3Sep) { level = psLevel3Sep; } else { - level = psLevel2; + level = psLevel3; } if (doForm && level < psLevel2) { fprintf(stderr, "Error: forms are only available with Level 2 output.\n"); @@ -374,7 +383,7 @@ int main(int argc, char *argv[]) { exitCode = 2; goto err2; } - doc->displayPages(psOut, firstPage, lastPage, 72, 72, + doc->displayPages(psOut, NULL, firstPage, lastPage, 72, 72, 0, !globalParams->getPSUseCropBoxAsPage(), globalParams->getPSCrop(), gTrue); exitCode = 0; @@ -396,4 +405,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } diff --git a/src/xpdf-4.04/xpdf/pdftotext.cc b/src/xpdf-4.04/xpdf/pdftotext.cc index d8bf6df..470a901 100644 --- a/src/xpdf-4.04/xpdf/pdftotext.cc +++ b/src/xpdf-4.04/xpdf/pdftotext.cc @@ -132,6 +132,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; GString *textFileName; @@ -178,12 +182,15 @@ int main(int argc, char *argv[]) { delete globalParams; goto err0; } - if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { + if (printVersion) { + printf("pdftotext version %s [www.xpdfreader.com]\n", xpdfVersion); + printf("%s\n", xpdfCopyright); + goto err0; + } + if (!ok || argc < 2 || argc > 3 || printHelp) { fprintf(stderr, "pdftotext version %s [www.xpdfreader.com]\n", xpdfVersion); fprintf(stderr, "%s\n", xpdfCopyright); - if (!printVersion) { - printUsage("pdftotext", " []", argDesc); - } + printUsage("pdftotext", " []", argDesc); goto err0; } fileName = argv[1]; @@ -303,7 +310,7 @@ int main(int argc, char *argv[]) { textOut = new TextOutputDev(textFileName->getCString(), &textOutControl, gFalse, gTrue); if (textOut->isOk()) { - doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, + doc->displayPages(textOut, NULL, firstPage, lastPage, 72, 72, 0, gFalse, gTrue, gFalse); } else { delete textOut; @@ -329,4 +336,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } From 062acf59197cf8324e945b73fe7daa934527502d Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:57:30 +0200 Subject: [PATCH 07/10] Reapply former fix --- src/xpdf-4.04/xpdf/TextOutputDev.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/xpdf-4.04/xpdf/TextOutputDev.cc b/src/xpdf-4.04/xpdf/TextOutputDev.cc index 5db4e0d..9a58d21 100644 --- a/src/xpdf-4.04/xpdf/TextOutputDev.cc +++ b/src/xpdf-4.04/xpdf/TextOutputDev.cc @@ -1464,8 +1464,7 @@ void TextPage::updateFont(GfxState *state) { diagonal = fabs(m[0]) > diagonalThreshold * fabs(m[1]); } // this matches the 'horiz' test in SplashOutputDev::drawChar() - rotated = !(m[0] > 0 && fabs(m[1]) < 0.001 && - fabs(m[2]) < 0.001 && m[3] < 0); + rotated = !(m[0] > 0 && (fabs(m[1]) < 0.001 || fabs(m[2]) < 0.001) && m[3] < 0); } void TextPage::addChar(GfxState *state, double x, double y, From 88a1328fc3561720bf0170ee7eca4652a60e56ad Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 12:58:44 +0200 Subject: [PATCH 08/10] Rename folder --- src/{xpdf-4.04 => xpdf-4.06}/ANNOUNCE | 0 src/{xpdf-4.04 => xpdf-4.06}/CHANGES | 0 src/{xpdf-4.04 => xpdf-4.06}/CMakeLists.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/COPYING | 0 src/{xpdf-4.04 => xpdf-4.06}/COPYING3 | 0 src/{xpdf-4.04 => xpdf-4.06}/INSTALL | 0 src/{xpdf-4.04 => xpdf-4.06}/README | 0 src/{xpdf-4.04 => xpdf-4.06}/aconf.h | 0 src/{xpdf-4.04 => xpdf-4.06}/aconf.h.in | 0 src/{xpdf-4.04 => xpdf-4.06}/cmake-config.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdfdetach.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdfdetach.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdffonts.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdffonts.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdfimages.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdfimages.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdfinfo.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdfinfo.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftohtml.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftohtml.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftopng.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftopng.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftoppm.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftoppm.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftops.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftops.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftotext.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/pdftotext.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/sample-xpdfrc | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/xpdf.1 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/xpdf.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/xpdfrc.5 | 0 src/{xpdf-4.04 => xpdf-4.06}/doc/xpdfrc.cat | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/CMakeLists.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiBase.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiBase.h | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiEncodings.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiEncodings.h | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiIdentifier.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiIdentifier.h | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiTrueType.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiTrueType.h | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1.h | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1C.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1C.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/CMakeLists.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/FixedPoint.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/FixedPoint.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GHash.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GHash.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GList.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GList.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GMutex.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GString.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/GString.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/Trace.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/Trace.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gfile.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gfile.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gmem.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gmem.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gmempp.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gmempp.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/gtypes.h | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/parseargs.c | 0 src/{xpdf-4.04 => xpdf-4.06}/goo/parseargs.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/CMakeLists.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/Splash.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/Splash.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashBitmap.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashBitmap.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashClip.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashClip.h | 0 .../splash/SplashErrorCodes.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFont.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFont.h | 0 .../splash/SplashFTFontEngine.cc | 0 .../splash/SplashFTFontEngine.h | 0 .../splash/SplashFTFontFile.cc | 0 .../splash/SplashFTFontFile.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFont.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFont.h | 0 .../splash/SplashFontEngine.cc | 0 .../splash/SplashFontEngine.h | 0 .../splash/SplashFontFile.cc | 0 .../splash/SplashFontFile.h | 0 .../splash/SplashFontFileID.cc | 0 .../splash/SplashFontFileID.h | 0 .../splash/SplashGlyphBitmap.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashMath.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPath.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPath.h | 0 .../splash/SplashPattern.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPattern.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashScreen.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashScreen.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashState.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashState.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashTypes.h | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashXPath.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/splash/SplashXPath.h | 0 .../splash/SplashXPathScanner.cc | 0 .../splash/SplashXPathScanner.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/CMakeLists.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/QtPDFCore.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/QtPDFCore.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfApp.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfApp.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfViewer.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfViewer.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfWidget.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfWidget.h | 0 .../xpdf-qt/XpdfWidgetPrint.cc | 0 .../xpdf-qt/XpdfWidgetPrint.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/back.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/findNext.svg | 0 .../xpdf-qt/findPrevious.svg | 0 .../xpdf-qt/findSettings.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitPage.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitPageOn.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitWidth.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitWidthOn.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/forward.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/icons.qrc | 0 .../xpdf-qt/indicator-icon-err0.svg | 0 .../xpdf-qt/indicator-icon-err1.svg | 0 .../xpdf-qt/indicator-icon-err2.svg | 0 .../xpdf-qt/indicator-icon-err3.svg | 0 .../xpdf-qt/indicator-icon-err4.svg | 0 .../xpdf-qt/indicator-icon-err5.svg | 0 .../xpdf-qt/indicator-icon-err6.svg | 0 .../xpdf-qt/indicator-icon-err7.svg | 0 .../xpdf-qt/indicator-icon0.svg | 0 .../xpdf-qt/indicator-icon1.svg | 0 .../xpdf-qt/indicator-icon2.svg | 0 .../xpdf-qt/indicator-icon3.svg | 0 .../xpdf-qt/indicator-icon4.svg | 0 .../xpdf-qt/indicator-icon5.svg | 0 .../xpdf-qt/indicator-icon6.svg | 0 .../xpdf-qt/indicator-icon7.svg | 0 .../xpdf-qt/selectModeBlock.svg | 0 .../xpdf-qt/selectModeLinear.svg | 0 .../xpdf-qt/toggleSidebar.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf-icon.ico | Bin src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf-icon.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf.rc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/zoomIn.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/zoomOut.svg | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/AcroForm.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/AcroForm.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Annot.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Annot.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Array.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Array.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/BuiltinFont.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/BuiltinFont.h | 0 .../xpdf/BuiltinFontTables.cc | 0 .../xpdf/BuiltinFontTables.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/CMakeLists.txt | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/CMap.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/CMap.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Catalog.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Catalog.h | 0 .../xpdf/CharCodeToUnicode.cc | 0 .../xpdf/CharCodeToUnicode.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/CharTypes.h | 0 .../xpdf/CompactFontTables.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Decrypt.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Decrypt.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Dict.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Dict.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/DisplayState.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/DisplayState.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Error.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Error.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/ErrorCodes.h | 0 .../xpdf/FontEncodingTables.cc | 0 .../xpdf/FontEncodingTables.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Function.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Function.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Gfx.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Gfx.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxFont.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxFont.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxState.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxState.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/GlobalParams.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/GlobalParams.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/HTMLGen.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/HTMLGen.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/ImageOutputDev.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/ImageOutputDev.h | 0 .../xpdf/JArithmeticDecoder.cc | 0 .../xpdf/JArithmeticDecoder.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/JBIG2Stream.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/JBIG2Stream.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/JPXStream.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/JPXStream.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Lexer.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Lexer.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Link.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Link.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/LocalParams.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/LocalParams.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/NameToCharCode.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/NameToCharCode.h | 0 .../xpdf/NameToUnicodeTable.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Object.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Object.h | 0 .../xpdf/OptionalContent.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/OptionalContent.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Outline.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Outline.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/OutputDev.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/OutputDev.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDF417Barcode.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDF417Barcode.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFCore.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFCore.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDoc.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDoc.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDocEncoding.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDocEncoding.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSOutputDev.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSOutputDev.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSTokenizer.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSTokenizer.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Page.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Page.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Parser.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Parser.h | 0 .../xpdf/PreScanOutputDev.cc | 0 .../xpdf/PreScanOutputDev.h | 0 .../xpdf/SecurityHandler.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/SecurityHandler.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/ShadingImage.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/ShadingImage.h | 0 .../xpdf/SplashOutputDev.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/SplashOutputDev.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Stream-CCITT.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Stream.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Stream.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextOutputDev.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextOutputDev.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextString.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextString.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCache.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCache.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCompositor.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCompositor.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileMap.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileMap.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/UTF8.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/UTF8.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeMap.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeMap.h | 0 .../xpdf/UnicodeMapTables.h | 0 .../xpdf/UnicodeRemapping.cc | 0 .../xpdf/UnicodeRemapping.h | 0 .../xpdf/UnicodeTypeTable.cc | 0 .../xpdf/UnicodeTypeTable.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/WebFont.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/WebFont.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/XFAScanner.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/XFAScanner.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/XRef.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/XRef.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Zoox.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/Zoox.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/config.h | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdfdetach.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdffonts.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdfimages.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdfinfo.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftohtml.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftopng.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftoppm.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftops.cc | 0 src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftotext.cc | 0 .../xpdf/winLongPath.exe.manifest | 0 282 files changed, 0 insertions(+), 0 deletions(-) rename src/{xpdf-4.04 => xpdf-4.06}/ANNOUNCE (100%) rename src/{xpdf-4.04 => xpdf-4.06}/CHANGES (100%) rename src/{xpdf-4.04 => xpdf-4.06}/CMakeLists.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/COPYING (100%) rename src/{xpdf-4.04 => xpdf-4.06}/COPYING3 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/INSTALL (100%) rename src/{xpdf-4.04 => xpdf-4.06}/README (100%) rename src/{xpdf-4.04 => xpdf-4.06}/aconf.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/aconf.h.in (100%) rename src/{xpdf-4.04 => xpdf-4.06}/cmake-config.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdfdetach.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdfdetach.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdffonts.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdffonts.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdfimages.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdfimages.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdfinfo.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdfinfo.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftohtml.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftohtml.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftopng.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftopng.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftoppm.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftoppm.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftops.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftops.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftotext.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/pdftotext.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/sample-xpdfrc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/xpdf.1 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/xpdf.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/xpdfrc.5 (100%) rename src/{xpdf-4.04 => xpdf-4.06}/doc/xpdfrc.cat (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/CMakeLists.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiBase.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiBase.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiEncodings.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiEncodings.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiIdentifier.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiIdentifier.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiTrueType.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiTrueType.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1C.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/fofi/FoFiType1C.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/CMakeLists.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/FixedPoint.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/FixedPoint.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GHash.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GHash.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GList.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GList.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GMutex.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GString.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/GString.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/Trace.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/Trace.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gfile.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gfile.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gmem.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gmem.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gmempp.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gmempp.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/gtypes.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/parseargs.c (100%) rename src/{xpdf-4.04 => xpdf-4.06}/goo/parseargs.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/CMakeLists.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/Splash.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/Splash.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashBitmap.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashBitmap.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashClip.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashClip.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashErrorCodes.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFont.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFont.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFontEngine.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFontEngine.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFontFile.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFTFontFile.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFont.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFont.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFontEngine.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFontEngine.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFontFile.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFontFile.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFontFileID.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashFontFileID.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashGlyphBitmap.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashMath.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPath.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPath.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPattern.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashPattern.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashScreen.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashScreen.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashState.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashState.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashTypes.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashXPath.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashXPath.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashXPathScanner.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/splash/SplashXPathScanner.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/CMakeLists.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/QtPDFCore.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/QtPDFCore.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfApp.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfApp.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfViewer.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfViewer.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfWidget.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfWidget.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfWidgetPrint.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/XpdfWidgetPrint.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/back.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/findNext.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/findPrevious.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/findSettings.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitPage.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitPageOn.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitWidth.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/fitWidthOn.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/forward.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/icons.qrc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err0.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err1.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err2.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err3.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err4.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err5.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err6.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon-err7.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon0.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon1.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon2.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon3.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon4.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon5.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon6.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/indicator-icon7.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/selectModeBlock.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/selectModeLinear.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/toggleSidebar.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf-icon.ico (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf-icon.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/xpdf.rc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/zoomIn.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf-qt/zoomOut.svg (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/AcroForm.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/AcroForm.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Annot.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Annot.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Array.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Array.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/BuiltinFont.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/BuiltinFont.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/BuiltinFontTables.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/BuiltinFontTables.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CMakeLists.txt (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CMap.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CMap.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Catalog.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Catalog.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CharCodeToUnicode.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CharCodeToUnicode.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CharTypes.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/CompactFontTables.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Decrypt.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Decrypt.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Dict.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Dict.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/DisplayState.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/DisplayState.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Error.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Error.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/ErrorCodes.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/FontEncodingTables.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/FontEncodingTables.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Function.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Function.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Gfx.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Gfx.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxFont.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxFont.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxState.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/GfxState.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/GlobalParams.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/GlobalParams.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/HTMLGen.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/HTMLGen.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/ImageOutputDev.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/ImageOutputDev.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/JArithmeticDecoder.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/JArithmeticDecoder.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/JBIG2Stream.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/JBIG2Stream.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/JPXStream.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/JPXStream.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Lexer.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Lexer.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Link.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Link.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/LocalParams.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/LocalParams.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/NameToCharCode.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/NameToCharCode.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/NameToUnicodeTable.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Object.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Object.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/OptionalContent.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/OptionalContent.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Outline.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Outline.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/OutputDev.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/OutputDev.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDF417Barcode.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDF417Barcode.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFCore.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFCore.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDoc.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDoc.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDocEncoding.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PDFDocEncoding.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSOutputDev.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSOutputDev.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSTokenizer.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PSTokenizer.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Page.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Page.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Parser.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Parser.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PreScanOutputDev.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/PreScanOutputDev.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/SecurityHandler.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/SecurityHandler.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/ShadingImage.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/ShadingImage.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/SplashOutputDev.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/SplashOutputDev.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Stream-CCITT.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Stream.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Stream.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextOutputDev.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextOutputDev.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextString.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TextString.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCache.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCache.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCompositor.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileCompositor.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileMap.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/TileMap.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UTF8.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UTF8.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeMap.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeMap.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeMapTables.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeRemapping.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeRemapping.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeTypeTable.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/UnicodeTypeTable.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/WebFont.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/WebFont.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/XFAScanner.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/XFAScanner.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/XRef.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/XRef.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Zoox.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/Zoox.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/config.h (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdfdetach.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdffonts.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdfimages.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdfinfo.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftohtml.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftopng.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftoppm.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftops.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/pdftotext.cc (100%) rename src/{xpdf-4.04 => xpdf-4.06}/xpdf/winLongPath.exe.manifest (100%) diff --git a/src/xpdf-4.04/ANNOUNCE b/src/xpdf-4.06/ANNOUNCE similarity index 100% rename from src/xpdf-4.04/ANNOUNCE rename to src/xpdf-4.06/ANNOUNCE diff --git a/src/xpdf-4.04/CHANGES b/src/xpdf-4.06/CHANGES similarity index 100% rename from src/xpdf-4.04/CHANGES rename to src/xpdf-4.06/CHANGES diff --git a/src/xpdf-4.04/CMakeLists.txt b/src/xpdf-4.06/CMakeLists.txt similarity index 100% rename from src/xpdf-4.04/CMakeLists.txt rename to src/xpdf-4.06/CMakeLists.txt diff --git a/src/xpdf-4.04/COPYING b/src/xpdf-4.06/COPYING similarity index 100% rename from src/xpdf-4.04/COPYING rename to src/xpdf-4.06/COPYING diff --git a/src/xpdf-4.04/COPYING3 b/src/xpdf-4.06/COPYING3 similarity index 100% rename from src/xpdf-4.04/COPYING3 rename to src/xpdf-4.06/COPYING3 diff --git a/src/xpdf-4.04/INSTALL b/src/xpdf-4.06/INSTALL similarity index 100% rename from src/xpdf-4.04/INSTALL rename to src/xpdf-4.06/INSTALL diff --git a/src/xpdf-4.04/README b/src/xpdf-4.06/README similarity index 100% rename from src/xpdf-4.04/README rename to src/xpdf-4.06/README diff --git a/src/xpdf-4.04/aconf.h b/src/xpdf-4.06/aconf.h similarity index 100% rename from src/xpdf-4.04/aconf.h rename to src/xpdf-4.06/aconf.h diff --git a/src/xpdf-4.04/aconf.h.in b/src/xpdf-4.06/aconf.h.in similarity index 100% rename from src/xpdf-4.04/aconf.h.in rename to src/xpdf-4.06/aconf.h.in diff --git a/src/xpdf-4.04/cmake-config.txt b/src/xpdf-4.06/cmake-config.txt similarity index 100% rename from src/xpdf-4.04/cmake-config.txt rename to src/xpdf-4.06/cmake-config.txt diff --git a/src/xpdf-4.04/doc/pdfdetach.1 b/src/xpdf-4.06/doc/pdfdetach.1 similarity index 100% rename from src/xpdf-4.04/doc/pdfdetach.1 rename to src/xpdf-4.06/doc/pdfdetach.1 diff --git a/src/xpdf-4.04/doc/pdfdetach.cat b/src/xpdf-4.06/doc/pdfdetach.cat similarity index 100% rename from src/xpdf-4.04/doc/pdfdetach.cat rename to src/xpdf-4.06/doc/pdfdetach.cat diff --git a/src/xpdf-4.04/doc/pdffonts.1 b/src/xpdf-4.06/doc/pdffonts.1 similarity index 100% rename from src/xpdf-4.04/doc/pdffonts.1 rename to src/xpdf-4.06/doc/pdffonts.1 diff --git a/src/xpdf-4.04/doc/pdffonts.cat b/src/xpdf-4.06/doc/pdffonts.cat similarity index 100% rename from src/xpdf-4.04/doc/pdffonts.cat rename to src/xpdf-4.06/doc/pdffonts.cat diff --git a/src/xpdf-4.04/doc/pdfimages.1 b/src/xpdf-4.06/doc/pdfimages.1 similarity index 100% rename from src/xpdf-4.04/doc/pdfimages.1 rename to src/xpdf-4.06/doc/pdfimages.1 diff --git a/src/xpdf-4.04/doc/pdfimages.cat b/src/xpdf-4.06/doc/pdfimages.cat similarity index 100% rename from src/xpdf-4.04/doc/pdfimages.cat rename to src/xpdf-4.06/doc/pdfimages.cat diff --git a/src/xpdf-4.04/doc/pdfinfo.1 b/src/xpdf-4.06/doc/pdfinfo.1 similarity index 100% rename from src/xpdf-4.04/doc/pdfinfo.1 rename to src/xpdf-4.06/doc/pdfinfo.1 diff --git a/src/xpdf-4.04/doc/pdfinfo.cat b/src/xpdf-4.06/doc/pdfinfo.cat similarity index 100% rename from src/xpdf-4.04/doc/pdfinfo.cat rename to src/xpdf-4.06/doc/pdfinfo.cat diff --git a/src/xpdf-4.04/doc/pdftohtml.1 b/src/xpdf-4.06/doc/pdftohtml.1 similarity index 100% rename from src/xpdf-4.04/doc/pdftohtml.1 rename to src/xpdf-4.06/doc/pdftohtml.1 diff --git a/src/xpdf-4.04/doc/pdftohtml.cat b/src/xpdf-4.06/doc/pdftohtml.cat similarity index 100% rename from src/xpdf-4.04/doc/pdftohtml.cat rename to src/xpdf-4.06/doc/pdftohtml.cat diff --git a/src/xpdf-4.04/doc/pdftopng.1 b/src/xpdf-4.06/doc/pdftopng.1 similarity index 100% rename from src/xpdf-4.04/doc/pdftopng.1 rename to src/xpdf-4.06/doc/pdftopng.1 diff --git a/src/xpdf-4.04/doc/pdftopng.cat b/src/xpdf-4.06/doc/pdftopng.cat similarity index 100% rename from src/xpdf-4.04/doc/pdftopng.cat rename to src/xpdf-4.06/doc/pdftopng.cat diff --git a/src/xpdf-4.04/doc/pdftoppm.1 b/src/xpdf-4.06/doc/pdftoppm.1 similarity index 100% rename from src/xpdf-4.04/doc/pdftoppm.1 rename to src/xpdf-4.06/doc/pdftoppm.1 diff --git a/src/xpdf-4.04/doc/pdftoppm.cat b/src/xpdf-4.06/doc/pdftoppm.cat similarity index 100% rename from src/xpdf-4.04/doc/pdftoppm.cat rename to src/xpdf-4.06/doc/pdftoppm.cat diff --git a/src/xpdf-4.04/doc/pdftops.1 b/src/xpdf-4.06/doc/pdftops.1 similarity index 100% rename from src/xpdf-4.04/doc/pdftops.1 rename to src/xpdf-4.06/doc/pdftops.1 diff --git a/src/xpdf-4.04/doc/pdftops.cat b/src/xpdf-4.06/doc/pdftops.cat similarity index 100% rename from src/xpdf-4.04/doc/pdftops.cat rename to src/xpdf-4.06/doc/pdftops.cat diff --git a/src/xpdf-4.04/doc/pdftotext.1 b/src/xpdf-4.06/doc/pdftotext.1 similarity index 100% rename from src/xpdf-4.04/doc/pdftotext.1 rename to src/xpdf-4.06/doc/pdftotext.1 diff --git a/src/xpdf-4.04/doc/pdftotext.cat b/src/xpdf-4.06/doc/pdftotext.cat similarity index 100% rename from src/xpdf-4.04/doc/pdftotext.cat rename to src/xpdf-4.06/doc/pdftotext.cat diff --git a/src/xpdf-4.04/doc/sample-xpdfrc b/src/xpdf-4.06/doc/sample-xpdfrc similarity index 100% rename from src/xpdf-4.04/doc/sample-xpdfrc rename to src/xpdf-4.06/doc/sample-xpdfrc diff --git a/src/xpdf-4.04/doc/xpdf.1 b/src/xpdf-4.06/doc/xpdf.1 similarity index 100% rename from src/xpdf-4.04/doc/xpdf.1 rename to src/xpdf-4.06/doc/xpdf.1 diff --git a/src/xpdf-4.04/doc/xpdf.cat b/src/xpdf-4.06/doc/xpdf.cat similarity index 100% rename from src/xpdf-4.04/doc/xpdf.cat rename to src/xpdf-4.06/doc/xpdf.cat diff --git a/src/xpdf-4.04/doc/xpdfrc.5 b/src/xpdf-4.06/doc/xpdfrc.5 similarity index 100% rename from src/xpdf-4.04/doc/xpdfrc.5 rename to src/xpdf-4.06/doc/xpdfrc.5 diff --git a/src/xpdf-4.04/doc/xpdfrc.cat b/src/xpdf-4.06/doc/xpdfrc.cat similarity index 100% rename from src/xpdf-4.04/doc/xpdfrc.cat rename to src/xpdf-4.06/doc/xpdfrc.cat diff --git a/src/xpdf-4.04/fofi/CMakeLists.txt b/src/xpdf-4.06/fofi/CMakeLists.txt similarity index 100% rename from src/xpdf-4.04/fofi/CMakeLists.txt rename to src/xpdf-4.06/fofi/CMakeLists.txt diff --git a/src/xpdf-4.04/fofi/FoFiBase.cc b/src/xpdf-4.06/fofi/FoFiBase.cc similarity index 100% rename from src/xpdf-4.04/fofi/FoFiBase.cc rename to src/xpdf-4.06/fofi/FoFiBase.cc diff --git a/src/xpdf-4.04/fofi/FoFiBase.h b/src/xpdf-4.06/fofi/FoFiBase.h similarity index 100% rename from src/xpdf-4.04/fofi/FoFiBase.h rename to src/xpdf-4.06/fofi/FoFiBase.h diff --git a/src/xpdf-4.04/fofi/FoFiEncodings.cc b/src/xpdf-4.06/fofi/FoFiEncodings.cc similarity index 100% rename from src/xpdf-4.04/fofi/FoFiEncodings.cc rename to src/xpdf-4.06/fofi/FoFiEncodings.cc diff --git a/src/xpdf-4.04/fofi/FoFiEncodings.h b/src/xpdf-4.06/fofi/FoFiEncodings.h similarity index 100% rename from src/xpdf-4.04/fofi/FoFiEncodings.h rename to src/xpdf-4.06/fofi/FoFiEncodings.h diff --git a/src/xpdf-4.04/fofi/FoFiIdentifier.cc b/src/xpdf-4.06/fofi/FoFiIdentifier.cc similarity index 100% rename from src/xpdf-4.04/fofi/FoFiIdentifier.cc rename to src/xpdf-4.06/fofi/FoFiIdentifier.cc diff --git a/src/xpdf-4.04/fofi/FoFiIdentifier.h b/src/xpdf-4.06/fofi/FoFiIdentifier.h similarity index 100% rename from src/xpdf-4.04/fofi/FoFiIdentifier.h rename to src/xpdf-4.06/fofi/FoFiIdentifier.h diff --git a/src/xpdf-4.04/fofi/FoFiTrueType.cc b/src/xpdf-4.06/fofi/FoFiTrueType.cc similarity index 100% rename from src/xpdf-4.04/fofi/FoFiTrueType.cc rename to src/xpdf-4.06/fofi/FoFiTrueType.cc diff --git a/src/xpdf-4.04/fofi/FoFiTrueType.h b/src/xpdf-4.06/fofi/FoFiTrueType.h similarity index 100% rename from src/xpdf-4.04/fofi/FoFiTrueType.h rename to src/xpdf-4.06/fofi/FoFiTrueType.h diff --git a/src/xpdf-4.04/fofi/FoFiType1.cc b/src/xpdf-4.06/fofi/FoFiType1.cc similarity index 100% rename from src/xpdf-4.04/fofi/FoFiType1.cc rename to src/xpdf-4.06/fofi/FoFiType1.cc diff --git a/src/xpdf-4.04/fofi/FoFiType1.h b/src/xpdf-4.06/fofi/FoFiType1.h similarity index 100% rename from src/xpdf-4.04/fofi/FoFiType1.h rename to src/xpdf-4.06/fofi/FoFiType1.h diff --git a/src/xpdf-4.04/fofi/FoFiType1C.cc b/src/xpdf-4.06/fofi/FoFiType1C.cc similarity index 100% rename from src/xpdf-4.04/fofi/FoFiType1C.cc rename to src/xpdf-4.06/fofi/FoFiType1C.cc diff --git a/src/xpdf-4.04/fofi/FoFiType1C.h b/src/xpdf-4.06/fofi/FoFiType1C.h similarity index 100% rename from src/xpdf-4.04/fofi/FoFiType1C.h rename to src/xpdf-4.06/fofi/FoFiType1C.h diff --git a/src/xpdf-4.04/goo/CMakeLists.txt b/src/xpdf-4.06/goo/CMakeLists.txt similarity index 100% rename from src/xpdf-4.04/goo/CMakeLists.txt rename to src/xpdf-4.06/goo/CMakeLists.txt diff --git a/src/xpdf-4.04/goo/FixedPoint.cc b/src/xpdf-4.06/goo/FixedPoint.cc similarity index 100% rename from src/xpdf-4.04/goo/FixedPoint.cc rename to src/xpdf-4.06/goo/FixedPoint.cc diff --git a/src/xpdf-4.04/goo/FixedPoint.h b/src/xpdf-4.06/goo/FixedPoint.h similarity index 100% rename from src/xpdf-4.04/goo/FixedPoint.h rename to src/xpdf-4.06/goo/FixedPoint.h diff --git a/src/xpdf-4.04/goo/GHash.cc b/src/xpdf-4.06/goo/GHash.cc similarity index 100% rename from src/xpdf-4.04/goo/GHash.cc rename to src/xpdf-4.06/goo/GHash.cc diff --git a/src/xpdf-4.04/goo/GHash.h b/src/xpdf-4.06/goo/GHash.h similarity index 100% rename from src/xpdf-4.04/goo/GHash.h rename to src/xpdf-4.06/goo/GHash.h diff --git a/src/xpdf-4.04/goo/GList.cc b/src/xpdf-4.06/goo/GList.cc similarity index 100% rename from src/xpdf-4.04/goo/GList.cc rename to src/xpdf-4.06/goo/GList.cc diff --git a/src/xpdf-4.04/goo/GList.h b/src/xpdf-4.06/goo/GList.h similarity index 100% rename from src/xpdf-4.04/goo/GList.h rename to src/xpdf-4.06/goo/GList.h diff --git a/src/xpdf-4.04/goo/GMutex.h b/src/xpdf-4.06/goo/GMutex.h similarity index 100% rename from src/xpdf-4.04/goo/GMutex.h rename to src/xpdf-4.06/goo/GMutex.h diff --git a/src/xpdf-4.04/goo/GString.cc b/src/xpdf-4.06/goo/GString.cc similarity index 100% rename from src/xpdf-4.04/goo/GString.cc rename to src/xpdf-4.06/goo/GString.cc diff --git a/src/xpdf-4.04/goo/GString.h b/src/xpdf-4.06/goo/GString.h similarity index 100% rename from src/xpdf-4.04/goo/GString.h rename to src/xpdf-4.06/goo/GString.h diff --git a/src/xpdf-4.04/goo/Trace.cc b/src/xpdf-4.06/goo/Trace.cc similarity index 100% rename from src/xpdf-4.04/goo/Trace.cc rename to src/xpdf-4.06/goo/Trace.cc diff --git a/src/xpdf-4.04/goo/Trace.h b/src/xpdf-4.06/goo/Trace.h similarity index 100% rename from src/xpdf-4.04/goo/Trace.h rename to src/xpdf-4.06/goo/Trace.h diff --git a/src/xpdf-4.04/goo/gfile.cc b/src/xpdf-4.06/goo/gfile.cc similarity index 100% rename from src/xpdf-4.04/goo/gfile.cc rename to src/xpdf-4.06/goo/gfile.cc diff --git a/src/xpdf-4.04/goo/gfile.h b/src/xpdf-4.06/goo/gfile.h similarity index 100% rename from src/xpdf-4.04/goo/gfile.h rename to src/xpdf-4.06/goo/gfile.h diff --git a/src/xpdf-4.04/goo/gmem.cc b/src/xpdf-4.06/goo/gmem.cc similarity index 100% rename from src/xpdf-4.04/goo/gmem.cc rename to src/xpdf-4.06/goo/gmem.cc diff --git a/src/xpdf-4.04/goo/gmem.h b/src/xpdf-4.06/goo/gmem.h similarity index 100% rename from src/xpdf-4.04/goo/gmem.h rename to src/xpdf-4.06/goo/gmem.h diff --git a/src/xpdf-4.04/goo/gmempp.cc b/src/xpdf-4.06/goo/gmempp.cc similarity index 100% rename from src/xpdf-4.04/goo/gmempp.cc rename to src/xpdf-4.06/goo/gmempp.cc diff --git a/src/xpdf-4.04/goo/gmempp.h b/src/xpdf-4.06/goo/gmempp.h similarity index 100% rename from src/xpdf-4.04/goo/gmempp.h rename to src/xpdf-4.06/goo/gmempp.h diff --git a/src/xpdf-4.04/goo/gtypes.h b/src/xpdf-4.06/goo/gtypes.h similarity index 100% rename from src/xpdf-4.04/goo/gtypes.h rename to src/xpdf-4.06/goo/gtypes.h diff --git a/src/xpdf-4.04/goo/parseargs.c b/src/xpdf-4.06/goo/parseargs.c similarity index 100% rename from src/xpdf-4.04/goo/parseargs.c rename to src/xpdf-4.06/goo/parseargs.c diff --git a/src/xpdf-4.04/goo/parseargs.h b/src/xpdf-4.06/goo/parseargs.h similarity index 100% rename from src/xpdf-4.04/goo/parseargs.h rename to src/xpdf-4.06/goo/parseargs.h diff --git a/src/xpdf-4.04/splash/CMakeLists.txt b/src/xpdf-4.06/splash/CMakeLists.txt similarity index 100% rename from src/xpdf-4.04/splash/CMakeLists.txt rename to src/xpdf-4.06/splash/CMakeLists.txt diff --git a/src/xpdf-4.04/splash/Splash.cc b/src/xpdf-4.06/splash/Splash.cc similarity index 100% rename from src/xpdf-4.04/splash/Splash.cc rename to src/xpdf-4.06/splash/Splash.cc diff --git a/src/xpdf-4.04/splash/Splash.h b/src/xpdf-4.06/splash/Splash.h similarity index 100% rename from src/xpdf-4.04/splash/Splash.h rename to src/xpdf-4.06/splash/Splash.h diff --git a/src/xpdf-4.04/splash/SplashBitmap.cc b/src/xpdf-4.06/splash/SplashBitmap.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashBitmap.cc rename to src/xpdf-4.06/splash/SplashBitmap.cc diff --git a/src/xpdf-4.04/splash/SplashBitmap.h b/src/xpdf-4.06/splash/SplashBitmap.h similarity index 100% rename from src/xpdf-4.04/splash/SplashBitmap.h rename to src/xpdf-4.06/splash/SplashBitmap.h diff --git a/src/xpdf-4.04/splash/SplashClip.cc b/src/xpdf-4.06/splash/SplashClip.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashClip.cc rename to src/xpdf-4.06/splash/SplashClip.cc diff --git a/src/xpdf-4.04/splash/SplashClip.h b/src/xpdf-4.06/splash/SplashClip.h similarity index 100% rename from src/xpdf-4.04/splash/SplashClip.h rename to src/xpdf-4.06/splash/SplashClip.h diff --git a/src/xpdf-4.04/splash/SplashErrorCodes.h b/src/xpdf-4.06/splash/SplashErrorCodes.h similarity index 100% rename from src/xpdf-4.04/splash/SplashErrorCodes.h rename to src/xpdf-4.06/splash/SplashErrorCodes.h diff --git a/src/xpdf-4.04/splash/SplashFTFont.cc b/src/xpdf-4.06/splash/SplashFTFont.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFTFont.cc rename to src/xpdf-4.06/splash/SplashFTFont.cc diff --git a/src/xpdf-4.04/splash/SplashFTFont.h b/src/xpdf-4.06/splash/SplashFTFont.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFTFont.h rename to src/xpdf-4.06/splash/SplashFTFont.h diff --git a/src/xpdf-4.04/splash/SplashFTFontEngine.cc b/src/xpdf-4.06/splash/SplashFTFontEngine.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFTFontEngine.cc rename to src/xpdf-4.06/splash/SplashFTFontEngine.cc diff --git a/src/xpdf-4.04/splash/SplashFTFontEngine.h b/src/xpdf-4.06/splash/SplashFTFontEngine.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFTFontEngine.h rename to src/xpdf-4.06/splash/SplashFTFontEngine.h diff --git a/src/xpdf-4.04/splash/SplashFTFontFile.cc b/src/xpdf-4.06/splash/SplashFTFontFile.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFTFontFile.cc rename to src/xpdf-4.06/splash/SplashFTFontFile.cc diff --git a/src/xpdf-4.04/splash/SplashFTFontFile.h b/src/xpdf-4.06/splash/SplashFTFontFile.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFTFontFile.h rename to src/xpdf-4.06/splash/SplashFTFontFile.h diff --git a/src/xpdf-4.04/splash/SplashFont.cc b/src/xpdf-4.06/splash/SplashFont.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFont.cc rename to src/xpdf-4.06/splash/SplashFont.cc diff --git a/src/xpdf-4.04/splash/SplashFont.h b/src/xpdf-4.06/splash/SplashFont.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFont.h rename to src/xpdf-4.06/splash/SplashFont.h diff --git a/src/xpdf-4.04/splash/SplashFontEngine.cc b/src/xpdf-4.06/splash/SplashFontEngine.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFontEngine.cc rename to src/xpdf-4.06/splash/SplashFontEngine.cc diff --git a/src/xpdf-4.04/splash/SplashFontEngine.h b/src/xpdf-4.06/splash/SplashFontEngine.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFontEngine.h rename to src/xpdf-4.06/splash/SplashFontEngine.h diff --git a/src/xpdf-4.04/splash/SplashFontFile.cc b/src/xpdf-4.06/splash/SplashFontFile.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFontFile.cc rename to src/xpdf-4.06/splash/SplashFontFile.cc diff --git a/src/xpdf-4.04/splash/SplashFontFile.h b/src/xpdf-4.06/splash/SplashFontFile.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFontFile.h rename to src/xpdf-4.06/splash/SplashFontFile.h diff --git a/src/xpdf-4.04/splash/SplashFontFileID.cc b/src/xpdf-4.06/splash/SplashFontFileID.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashFontFileID.cc rename to src/xpdf-4.06/splash/SplashFontFileID.cc diff --git a/src/xpdf-4.04/splash/SplashFontFileID.h b/src/xpdf-4.06/splash/SplashFontFileID.h similarity index 100% rename from src/xpdf-4.04/splash/SplashFontFileID.h rename to src/xpdf-4.06/splash/SplashFontFileID.h diff --git a/src/xpdf-4.04/splash/SplashGlyphBitmap.h b/src/xpdf-4.06/splash/SplashGlyphBitmap.h similarity index 100% rename from src/xpdf-4.04/splash/SplashGlyphBitmap.h rename to src/xpdf-4.06/splash/SplashGlyphBitmap.h diff --git a/src/xpdf-4.04/splash/SplashMath.h b/src/xpdf-4.06/splash/SplashMath.h similarity index 100% rename from src/xpdf-4.04/splash/SplashMath.h rename to src/xpdf-4.06/splash/SplashMath.h diff --git a/src/xpdf-4.04/splash/SplashPath.cc b/src/xpdf-4.06/splash/SplashPath.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashPath.cc rename to src/xpdf-4.06/splash/SplashPath.cc diff --git a/src/xpdf-4.04/splash/SplashPath.h b/src/xpdf-4.06/splash/SplashPath.h similarity index 100% rename from src/xpdf-4.04/splash/SplashPath.h rename to src/xpdf-4.06/splash/SplashPath.h diff --git a/src/xpdf-4.04/splash/SplashPattern.cc b/src/xpdf-4.06/splash/SplashPattern.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashPattern.cc rename to src/xpdf-4.06/splash/SplashPattern.cc diff --git a/src/xpdf-4.04/splash/SplashPattern.h b/src/xpdf-4.06/splash/SplashPattern.h similarity index 100% rename from src/xpdf-4.04/splash/SplashPattern.h rename to src/xpdf-4.06/splash/SplashPattern.h diff --git a/src/xpdf-4.04/splash/SplashScreen.cc b/src/xpdf-4.06/splash/SplashScreen.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashScreen.cc rename to src/xpdf-4.06/splash/SplashScreen.cc diff --git a/src/xpdf-4.04/splash/SplashScreen.h b/src/xpdf-4.06/splash/SplashScreen.h similarity index 100% rename from src/xpdf-4.04/splash/SplashScreen.h rename to src/xpdf-4.06/splash/SplashScreen.h diff --git a/src/xpdf-4.04/splash/SplashState.cc b/src/xpdf-4.06/splash/SplashState.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashState.cc rename to src/xpdf-4.06/splash/SplashState.cc diff --git a/src/xpdf-4.04/splash/SplashState.h b/src/xpdf-4.06/splash/SplashState.h similarity index 100% rename from src/xpdf-4.04/splash/SplashState.h rename to src/xpdf-4.06/splash/SplashState.h diff --git a/src/xpdf-4.04/splash/SplashTypes.h b/src/xpdf-4.06/splash/SplashTypes.h similarity index 100% rename from src/xpdf-4.04/splash/SplashTypes.h rename to src/xpdf-4.06/splash/SplashTypes.h diff --git a/src/xpdf-4.04/splash/SplashXPath.cc b/src/xpdf-4.06/splash/SplashXPath.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashXPath.cc rename to src/xpdf-4.06/splash/SplashXPath.cc diff --git a/src/xpdf-4.04/splash/SplashXPath.h b/src/xpdf-4.06/splash/SplashXPath.h similarity index 100% rename from src/xpdf-4.04/splash/SplashXPath.h rename to src/xpdf-4.06/splash/SplashXPath.h diff --git a/src/xpdf-4.04/splash/SplashXPathScanner.cc b/src/xpdf-4.06/splash/SplashXPathScanner.cc similarity index 100% rename from src/xpdf-4.04/splash/SplashXPathScanner.cc rename to src/xpdf-4.06/splash/SplashXPathScanner.cc diff --git a/src/xpdf-4.04/splash/SplashXPathScanner.h b/src/xpdf-4.06/splash/SplashXPathScanner.h similarity index 100% rename from src/xpdf-4.04/splash/SplashXPathScanner.h rename to src/xpdf-4.06/splash/SplashXPathScanner.h diff --git a/src/xpdf-4.04/xpdf-qt/CMakeLists.txt b/src/xpdf-4.06/xpdf-qt/CMakeLists.txt similarity index 100% rename from src/xpdf-4.04/xpdf-qt/CMakeLists.txt rename to src/xpdf-4.06/xpdf-qt/CMakeLists.txt diff --git a/src/xpdf-4.04/xpdf-qt/QtPDFCore.cc b/src/xpdf-4.06/xpdf-qt/QtPDFCore.cc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/QtPDFCore.cc rename to src/xpdf-4.06/xpdf-qt/QtPDFCore.cc diff --git a/src/xpdf-4.04/xpdf-qt/QtPDFCore.h b/src/xpdf-4.06/xpdf-qt/QtPDFCore.h similarity index 100% rename from src/xpdf-4.04/xpdf-qt/QtPDFCore.h rename to src/xpdf-4.06/xpdf-qt/QtPDFCore.h diff --git a/src/xpdf-4.04/xpdf-qt/XpdfApp.cc b/src/xpdf-4.06/xpdf-qt/XpdfApp.cc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfApp.cc rename to src/xpdf-4.06/xpdf-qt/XpdfApp.cc diff --git a/src/xpdf-4.04/xpdf-qt/XpdfApp.h b/src/xpdf-4.06/xpdf-qt/XpdfApp.h similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfApp.h rename to src/xpdf-4.06/xpdf-qt/XpdfApp.h diff --git a/src/xpdf-4.04/xpdf-qt/XpdfViewer.cc b/src/xpdf-4.06/xpdf-qt/XpdfViewer.cc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfViewer.cc rename to src/xpdf-4.06/xpdf-qt/XpdfViewer.cc diff --git a/src/xpdf-4.04/xpdf-qt/XpdfViewer.h b/src/xpdf-4.06/xpdf-qt/XpdfViewer.h similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfViewer.h rename to src/xpdf-4.06/xpdf-qt/XpdfViewer.h diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidget.cc b/src/xpdf-4.06/xpdf-qt/XpdfWidget.cc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfWidget.cc rename to src/xpdf-4.06/xpdf-qt/XpdfWidget.cc diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidget.h b/src/xpdf-4.06/xpdf-qt/XpdfWidget.h similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfWidget.h rename to src/xpdf-4.06/xpdf-qt/XpdfWidget.h diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc b/src/xpdf-4.06/xpdf-qt/XpdfWidgetPrint.cc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.cc rename to src/xpdf-4.06/xpdf-qt/XpdfWidgetPrint.cc diff --git a/src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.h b/src/xpdf-4.06/xpdf-qt/XpdfWidgetPrint.h similarity index 100% rename from src/xpdf-4.04/xpdf-qt/XpdfWidgetPrint.h rename to src/xpdf-4.06/xpdf-qt/XpdfWidgetPrint.h diff --git a/src/xpdf-4.04/xpdf-qt/back.svg b/src/xpdf-4.06/xpdf-qt/back.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/back.svg rename to src/xpdf-4.06/xpdf-qt/back.svg diff --git a/src/xpdf-4.04/xpdf-qt/findNext.svg b/src/xpdf-4.06/xpdf-qt/findNext.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/findNext.svg rename to src/xpdf-4.06/xpdf-qt/findNext.svg diff --git a/src/xpdf-4.04/xpdf-qt/findPrevious.svg b/src/xpdf-4.06/xpdf-qt/findPrevious.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/findPrevious.svg rename to src/xpdf-4.06/xpdf-qt/findPrevious.svg diff --git a/src/xpdf-4.04/xpdf-qt/findSettings.svg b/src/xpdf-4.06/xpdf-qt/findSettings.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/findSettings.svg rename to src/xpdf-4.06/xpdf-qt/findSettings.svg diff --git a/src/xpdf-4.04/xpdf-qt/fitPage.svg b/src/xpdf-4.06/xpdf-qt/fitPage.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/fitPage.svg rename to src/xpdf-4.06/xpdf-qt/fitPage.svg diff --git a/src/xpdf-4.04/xpdf-qt/fitPageOn.svg b/src/xpdf-4.06/xpdf-qt/fitPageOn.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/fitPageOn.svg rename to src/xpdf-4.06/xpdf-qt/fitPageOn.svg diff --git a/src/xpdf-4.04/xpdf-qt/fitWidth.svg b/src/xpdf-4.06/xpdf-qt/fitWidth.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/fitWidth.svg rename to src/xpdf-4.06/xpdf-qt/fitWidth.svg diff --git a/src/xpdf-4.04/xpdf-qt/fitWidthOn.svg b/src/xpdf-4.06/xpdf-qt/fitWidthOn.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/fitWidthOn.svg rename to src/xpdf-4.06/xpdf-qt/fitWidthOn.svg diff --git a/src/xpdf-4.04/xpdf-qt/forward.svg b/src/xpdf-4.06/xpdf-qt/forward.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/forward.svg rename to src/xpdf-4.06/xpdf-qt/forward.svg diff --git a/src/xpdf-4.04/xpdf-qt/icons.qrc b/src/xpdf-4.06/xpdf-qt/icons.qrc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/icons.qrc rename to src/xpdf-4.06/xpdf-qt/icons.qrc diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err0.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err0.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err0.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err0.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err1.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err1.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err1.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err1.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err2.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err2.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err2.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err2.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err3.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err3.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err3.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err3.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err4.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err4.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err4.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err4.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err5.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err5.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err5.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err5.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err6.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err6.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err6.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err6.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon-err7.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon-err7.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon-err7.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon-err7.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon0.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon0.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon0.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon0.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon1.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon1.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon1.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon1.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon2.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon2.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon2.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon2.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon3.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon3.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon3.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon3.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon4.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon4.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon4.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon4.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon5.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon5.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon5.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon5.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon6.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon6.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon6.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon6.svg diff --git a/src/xpdf-4.04/xpdf-qt/indicator-icon7.svg b/src/xpdf-4.06/xpdf-qt/indicator-icon7.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/indicator-icon7.svg rename to src/xpdf-4.06/xpdf-qt/indicator-icon7.svg diff --git a/src/xpdf-4.04/xpdf-qt/selectModeBlock.svg b/src/xpdf-4.06/xpdf-qt/selectModeBlock.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/selectModeBlock.svg rename to src/xpdf-4.06/xpdf-qt/selectModeBlock.svg diff --git a/src/xpdf-4.04/xpdf-qt/selectModeLinear.svg b/src/xpdf-4.06/xpdf-qt/selectModeLinear.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/selectModeLinear.svg rename to src/xpdf-4.06/xpdf-qt/selectModeLinear.svg diff --git a/src/xpdf-4.04/xpdf-qt/toggleSidebar.svg b/src/xpdf-4.06/xpdf-qt/toggleSidebar.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/toggleSidebar.svg rename to src/xpdf-4.06/xpdf-qt/toggleSidebar.svg diff --git a/src/xpdf-4.04/xpdf-qt/xpdf-icon.ico b/src/xpdf-4.06/xpdf-qt/xpdf-icon.ico similarity index 100% rename from src/xpdf-4.04/xpdf-qt/xpdf-icon.ico rename to src/xpdf-4.06/xpdf-qt/xpdf-icon.ico diff --git a/src/xpdf-4.04/xpdf-qt/xpdf-icon.svg b/src/xpdf-4.06/xpdf-qt/xpdf-icon.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/xpdf-icon.svg rename to src/xpdf-4.06/xpdf-qt/xpdf-icon.svg diff --git a/src/xpdf-4.04/xpdf-qt/xpdf.cc b/src/xpdf-4.06/xpdf-qt/xpdf.cc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/xpdf.cc rename to src/xpdf-4.06/xpdf-qt/xpdf.cc diff --git a/src/xpdf-4.04/xpdf-qt/xpdf.rc b/src/xpdf-4.06/xpdf-qt/xpdf.rc similarity index 100% rename from src/xpdf-4.04/xpdf-qt/xpdf.rc rename to src/xpdf-4.06/xpdf-qt/xpdf.rc diff --git a/src/xpdf-4.04/xpdf-qt/zoomIn.svg b/src/xpdf-4.06/xpdf-qt/zoomIn.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/zoomIn.svg rename to src/xpdf-4.06/xpdf-qt/zoomIn.svg diff --git a/src/xpdf-4.04/xpdf-qt/zoomOut.svg b/src/xpdf-4.06/xpdf-qt/zoomOut.svg similarity index 100% rename from src/xpdf-4.04/xpdf-qt/zoomOut.svg rename to src/xpdf-4.06/xpdf-qt/zoomOut.svg diff --git a/src/xpdf-4.04/xpdf/AcroForm.cc b/src/xpdf-4.06/xpdf/AcroForm.cc similarity index 100% rename from src/xpdf-4.04/xpdf/AcroForm.cc rename to src/xpdf-4.06/xpdf/AcroForm.cc diff --git a/src/xpdf-4.04/xpdf/AcroForm.h b/src/xpdf-4.06/xpdf/AcroForm.h similarity index 100% rename from src/xpdf-4.04/xpdf/AcroForm.h rename to src/xpdf-4.06/xpdf/AcroForm.h diff --git a/src/xpdf-4.04/xpdf/Annot.cc b/src/xpdf-4.06/xpdf/Annot.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Annot.cc rename to src/xpdf-4.06/xpdf/Annot.cc diff --git a/src/xpdf-4.04/xpdf/Annot.h b/src/xpdf-4.06/xpdf/Annot.h similarity index 100% rename from src/xpdf-4.04/xpdf/Annot.h rename to src/xpdf-4.06/xpdf/Annot.h diff --git a/src/xpdf-4.04/xpdf/Array.cc b/src/xpdf-4.06/xpdf/Array.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Array.cc rename to src/xpdf-4.06/xpdf/Array.cc diff --git a/src/xpdf-4.04/xpdf/Array.h b/src/xpdf-4.06/xpdf/Array.h similarity index 100% rename from src/xpdf-4.04/xpdf/Array.h rename to src/xpdf-4.06/xpdf/Array.h diff --git a/src/xpdf-4.04/xpdf/BuiltinFont.cc b/src/xpdf-4.06/xpdf/BuiltinFont.cc similarity index 100% rename from src/xpdf-4.04/xpdf/BuiltinFont.cc rename to src/xpdf-4.06/xpdf/BuiltinFont.cc diff --git a/src/xpdf-4.04/xpdf/BuiltinFont.h b/src/xpdf-4.06/xpdf/BuiltinFont.h similarity index 100% rename from src/xpdf-4.04/xpdf/BuiltinFont.h rename to src/xpdf-4.06/xpdf/BuiltinFont.h diff --git a/src/xpdf-4.04/xpdf/BuiltinFontTables.cc b/src/xpdf-4.06/xpdf/BuiltinFontTables.cc similarity index 100% rename from src/xpdf-4.04/xpdf/BuiltinFontTables.cc rename to src/xpdf-4.06/xpdf/BuiltinFontTables.cc diff --git a/src/xpdf-4.04/xpdf/BuiltinFontTables.h b/src/xpdf-4.06/xpdf/BuiltinFontTables.h similarity index 100% rename from src/xpdf-4.04/xpdf/BuiltinFontTables.h rename to src/xpdf-4.06/xpdf/BuiltinFontTables.h diff --git a/src/xpdf-4.04/xpdf/CMakeLists.txt b/src/xpdf-4.06/xpdf/CMakeLists.txt similarity index 100% rename from src/xpdf-4.04/xpdf/CMakeLists.txt rename to src/xpdf-4.06/xpdf/CMakeLists.txt diff --git a/src/xpdf-4.04/xpdf/CMap.cc b/src/xpdf-4.06/xpdf/CMap.cc similarity index 100% rename from src/xpdf-4.04/xpdf/CMap.cc rename to src/xpdf-4.06/xpdf/CMap.cc diff --git a/src/xpdf-4.04/xpdf/CMap.h b/src/xpdf-4.06/xpdf/CMap.h similarity index 100% rename from src/xpdf-4.04/xpdf/CMap.h rename to src/xpdf-4.06/xpdf/CMap.h diff --git a/src/xpdf-4.04/xpdf/Catalog.cc b/src/xpdf-4.06/xpdf/Catalog.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Catalog.cc rename to src/xpdf-4.06/xpdf/Catalog.cc diff --git a/src/xpdf-4.04/xpdf/Catalog.h b/src/xpdf-4.06/xpdf/Catalog.h similarity index 100% rename from src/xpdf-4.04/xpdf/Catalog.h rename to src/xpdf-4.06/xpdf/Catalog.h diff --git a/src/xpdf-4.04/xpdf/CharCodeToUnicode.cc b/src/xpdf-4.06/xpdf/CharCodeToUnicode.cc similarity index 100% rename from src/xpdf-4.04/xpdf/CharCodeToUnicode.cc rename to src/xpdf-4.06/xpdf/CharCodeToUnicode.cc diff --git a/src/xpdf-4.04/xpdf/CharCodeToUnicode.h b/src/xpdf-4.06/xpdf/CharCodeToUnicode.h similarity index 100% rename from src/xpdf-4.04/xpdf/CharCodeToUnicode.h rename to src/xpdf-4.06/xpdf/CharCodeToUnicode.h diff --git a/src/xpdf-4.04/xpdf/CharTypes.h b/src/xpdf-4.06/xpdf/CharTypes.h similarity index 100% rename from src/xpdf-4.04/xpdf/CharTypes.h rename to src/xpdf-4.06/xpdf/CharTypes.h diff --git a/src/xpdf-4.04/xpdf/CompactFontTables.h b/src/xpdf-4.06/xpdf/CompactFontTables.h similarity index 100% rename from src/xpdf-4.04/xpdf/CompactFontTables.h rename to src/xpdf-4.06/xpdf/CompactFontTables.h diff --git a/src/xpdf-4.04/xpdf/Decrypt.cc b/src/xpdf-4.06/xpdf/Decrypt.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Decrypt.cc rename to src/xpdf-4.06/xpdf/Decrypt.cc diff --git a/src/xpdf-4.04/xpdf/Decrypt.h b/src/xpdf-4.06/xpdf/Decrypt.h similarity index 100% rename from src/xpdf-4.04/xpdf/Decrypt.h rename to src/xpdf-4.06/xpdf/Decrypt.h diff --git a/src/xpdf-4.04/xpdf/Dict.cc b/src/xpdf-4.06/xpdf/Dict.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Dict.cc rename to src/xpdf-4.06/xpdf/Dict.cc diff --git a/src/xpdf-4.04/xpdf/Dict.h b/src/xpdf-4.06/xpdf/Dict.h similarity index 100% rename from src/xpdf-4.04/xpdf/Dict.h rename to src/xpdf-4.06/xpdf/Dict.h diff --git a/src/xpdf-4.04/xpdf/DisplayState.cc b/src/xpdf-4.06/xpdf/DisplayState.cc similarity index 100% rename from src/xpdf-4.04/xpdf/DisplayState.cc rename to src/xpdf-4.06/xpdf/DisplayState.cc diff --git a/src/xpdf-4.04/xpdf/DisplayState.h b/src/xpdf-4.06/xpdf/DisplayState.h similarity index 100% rename from src/xpdf-4.04/xpdf/DisplayState.h rename to src/xpdf-4.06/xpdf/DisplayState.h diff --git a/src/xpdf-4.04/xpdf/Error.cc b/src/xpdf-4.06/xpdf/Error.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Error.cc rename to src/xpdf-4.06/xpdf/Error.cc diff --git a/src/xpdf-4.04/xpdf/Error.h b/src/xpdf-4.06/xpdf/Error.h similarity index 100% rename from src/xpdf-4.04/xpdf/Error.h rename to src/xpdf-4.06/xpdf/Error.h diff --git a/src/xpdf-4.04/xpdf/ErrorCodes.h b/src/xpdf-4.06/xpdf/ErrorCodes.h similarity index 100% rename from src/xpdf-4.04/xpdf/ErrorCodes.h rename to src/xpdf-4.06/xpdf/ErrorCodes.h diff --git a/src/xpdf-4.04/xpdf/FontEncodingTables.cc b/src/xpdf-4.06/xpdf/FontEncodingTables.cc similarity index 100% rename from src/xpdf-4.04/xpdf/FontEncodingTables.cc rename to src/xpdf-4.06/xpdf/FontEncodingTables.cc diff --git a/src/xpdf-4.04/xpdf/FontEncodingTables.h b/src/xpdf-4.06/xpdf/FontEncodingTables.h similarity index 100% rename from src/xpdf-4.04/xpdf/FontEncodingTables.h rename to src/xpdf-4.06/xpdf/FontEncodingTables.h diff --git a/src/xpdf-4.04/xpdf/Function.cc b/src/xpdf-4.06/xpdf/Function.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Function.cc rename to src/xpdf-4.06/xpdf/Function.cc diff --git a/src/xpdf-4.04/xpdf/Function.h b/src/xpdf-4.06/xpdf/Function.h similarity index 100% rename from src/xpdf-4.04/xpdf/Function.h rename to src/xpdf-4.06/xpdf/Function.h diff --git a/src/xpdf-4.04/xpdf/Gfx.cc b/src/xpdf-4.06/xpdf/Gfx.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Gfx.cc rename to src/xpdf-4.06/xpdf/Gfx.cc diff --git a/src/xpdf-4.04/xpdf/Gfx.h b/src/xpdf-4.06/xpdf/Gfx.h similarity index 100% rename from src/xpdf-4.04/xpdf/Gfx.h rename to src/xpdf-4.06/xpdf/Gfx.h diff --git a/src/xpdf-4.04/xpdf/GfxFont.cc b/src/xpdf-4.06/xpdf/GfxFont.cc similarity index 100% rename from src/xpdf-4.04/xpdf/GfxFont.cc rename to src/xpdf-4.06/xpdf/GfxFont.cc diff --git a/src/xpdf-4.04/xpdf/GfxFont.h b/src/xpdf-4.06/xpdf/GfxFont.h similarity index 100% rename from src/xpdf-4.04/xpdf/GfxFont.h rename to src/xpdf-4.06/xpdf/GfxFont.h diff --git a/src/xpdf-4.04/xpdf/GfxState.cc b/src/xpdf-4.06/xpdf/GfxState.cc similarity index 100% rename from src/xpdf-4.04/xpdf/GfxState.cc rename to src/xpdf-4.06/xpdf/GfxState.cc diff --git a/src/xpdf-4.04/xpdf/GfxState.h b/src/xpdf-4.06/xpdf/GfxState.h similarity index 100% rename from src/xpdf-4.04/xpdf/GfxState.h rename to src/xpdf-4.06/xpdf/GfxState.h diff --git a/src/xpdf-4.04/xpdf/GlobalParams.cc b/src/xpdf-4.06/xpdf/GlobalParams.cc similarity index 100% rename from src/xpdf-4.04/xpdf/GlobalParams.cc rename to src/xpdf-4.06/xpdf/GlobalParams.cc diff --git a/src/xpdf-4.04/xpdf/GlobalParams.h b/src/xpdf-4.06/xpdf/GlobalParams.h similarity index 100% rename from src/xpdf-4.04/xpdf/GlobalParams.h rename to src/xpdf-4.06/xpdf/GlobalParams.h diff --git a/src/xpdf-4.04/xpdf/HTMLGen.cc b/src/xpdf-4.06/xpdf/HTMLGen.cc similarity index 100% rename from src/xpdf-4.04/xpdf/HTMLGen.cc rename to src/xpdf-4.06/xpdf/HTMLGen.cc diff --git a/src/xpdf-4.04/xpdf/HTMLGen.h b/src/xpdf-4.06/xpdf/HTMLGen.h similarity index 100% rename from src/xpdf-4.04/xpdf/HTMLGen.h rename to src/xpdf-4.06/xpdf/HTMLGen.h diff --git a/src/xpdf-4.04/xpdf/ImageOutputDev.cc b/src/xpdf-4.06/xpdf/ImageOutputDev.cc similarity index 100% rename from src/xpdf-4.04/xpdf/ImageOutputDev.cc rename to src/xpdf-4.06/xpdf/ImageOutputDev.cc diff --git a/src/xpdf-4.04/xpdf/ImageOutputDev.h b/src/xpdf-4.06/xpdf/ImageOutputDev.h similarity index 100% rename from src/xpdf-4.04/xpdf/ImageOutputDev.h rename to src/xpdf-4.06/xpdf/ImageOutputDev.h diff --git a/src/xpdf-4.04/xpdf/JArithmeticDecoder.cc b/src/xpdf-4.06/xpdf/JArithmeticDecoder.cc similarity index 100% rename from src/xpdf-4.04/xpdf/JArithmeticDecoder.cc rename to src/xpdf-4.06/xpdf/JArithmeticDecoder.cc diff --git a/src/xpdf-4.04/xpdf/JArithmeticDecoder.h b/src/xpdf-4.06/xpdf/JArithmeticDecoder.h similarity index 100% rename from src/xpdf-4.04/xpdf/JArithmeticDecoder.h rename to src/xpdf-4.06/xpdf/JArithmeticDecoder.h diff --git a/src/xpdf-4.04/xpdf/JBIG2Stream.cc b/src/xpdf-4.06/xpdf/JBIG2Stream.cc similarity index 100% rename from src/xpdf-4.04/xpdf/JBIG2Stream.cc rename to src/xpdf-4.06/xpdf/JBIG2Stream.cc diff --git a/src/xpdf-4.04/xpdf/JBIG2Stream.h b/src/xpdf-4.06/xpdf/JBIG2Stream.h similarity index 100% rename from src/xpdf-4.04/xpdf/JBIG2Stream.h rename to src/xpdf-4.06/xpdf/JBIG2Stream.h diff --git a/src/xpdf-4.04/xpdf/JPXStream.cc b/src/xpdf-4.06/xpdf/JPXStream.cc similarity index 100% rename from src/xpdf-4.04/xpdf/JPXStream.cc rename to src/xpdf-4.06/xpdf/JPXStream.cc diff --git a/src/xpdf-4.04/xpdf/JPXStream.h b/src/xpdf-4.06/xpdf/JPXStream.h similarity index 100% rename from src/xpdf-4.04/xpdf/JPXStream.h rename to src/xpdf-4.06/xpdf/JPXStream.h diff --git a/src/xpdf-4.04/xpdf/Lexer.cc b/src/xpdf-4.06/xpdf/Lexer.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Lexer.cc rename to src/xpdf-4.06/xpdf/Lexer.cc diff --git a/src/xpdf-4.04/xpdf/Lexer.h b/src/xpdf-4.06/xpdf/Lexer.h similarity index 100% rename from src/xpdf-4.04/xpdf/Lexer.h rename to src/xpdf-4.06/xpdf/Lexer.h diff --git a/src/xpdf-4.04/xpdf/Link.cc b/src/xpdf-4.06/xpdf/Link.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Link.cc rename to src/xpdf-4.06/xpdf/Link.cc diff --git a/src/xpdf-4.04/xpdf/Link.h b/src/xpdf-4.06/xpdf/Link.h similarity index 100% rename from src/xpdf-4.04/xpdf/Link.h rename to src/xpdf-4.06/xpdf/Link.h diff --git a/src/xpdf-4.04/xpdf/LocalParams.cc b/src/xpdf-4.06/xpdf/LocalParams.cc similarity index 100% rename from src/xpdf-4.04/xpdf/LocalParams.cc rename to src/xpdf-4.06/xpdf/LocalParams.cc diff --git a/src/xpdf-4.04/xpdf/LocalParams.h b/src/xpdf-4.06/xpdf/LocalParams.h similarity index 100% rename from src/xpdf-4.04/xpdf/LocalParams.h rename to src/xpdf-4.06/xpdf/LocalParams.h diff --git a/src/xpdf-4.04/xpdf/NameToCharCode.cc b/src/xpdf-4.06/xpdf/NameToCharCode.cc similarity index 100% rename from src/xpdf-4.04/xpdf/NameToCharCode.cc rename to src/xpdf-4.06/xpdf/NameToCharCode.cc diff --git a/src/xpdf-4.04/xpdf/NameToCharCode.h b/src/xpdf-4.06/xpdf/NameToCharCode.h similarity index 100% rename from src/xpdf-4.04/xpdf/NameToCharCode.h rename to src/xpdf-4.06/xpdf/NameToCharCode.h diff --git a/src/xpdf-4.04/xpdf/NameToUnicodeTable.h b/src/xpdf-4.06/xpdf/NameToUnicodeTable.h similarity index 100% rename from src/xpdf-4.04/xpdf/NameToUnicodeTable.h rename to src/xpdf-4.06/xpdf/NameToUnicodeTable.h diff --git a/src/xpdf-4.04/xpdf/Object.cc b/src/xpdf-4.06/xpdf/Object.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Object.cc rename to src/xpdf-4.06/xpdf/Object.cc diff --git a/src/xpdf-4.04/xpdf/Object.h b/src/xpdf-4.06/xpdf/Object.h similarity index 100% rename from src/xpdf-4.04/xpdf/Object.h rename to src/xpdf-4.06/xpdf/Object.h diff --git a/src/xpdf-4.04/xpdf/OptionalContent.cc b/src/xpdf-4.06/xpdf/OptionalContent.cc similarity index 100% rename from src/xpdf-4.04/xpdf/OptionalContent.cc rename to src/xpdf-4.06/xpdf/OptionalContent.cc diff --git a/src/xpdf-4.04/xpdf/OptionalContent.h b/src/xpdf-4.06/xpdf/OptionalContent.h similarity index 100% rename from src/xpdf-4.04/xpdf/OptionalContent.h rename to src/xpdf-4.06/xpdf/OptionalContent.h diff --git a/src/xpdf-4.04/xpdf/Outline.cc b/src/xpdf-4.06/xpdf/Outline.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Outline.cc rename to src/xpdf-4.06/xpdf/Outline.cc diff --git a/src/xpdf-4.04/xpdf/Outline.h b/src/xpdf-4.06/xpdf/Outline.h similarity index 100% rename from src/xpdf-4.04/xpdf/Outline.h rename to src/xpdf-4.06/xpdf/Outline.h diff --git a/src/xpdf-4.04/xpdf/OutputDev.cc b/src/xpdf-4.06/xpdf/OutputDev.cc similarity index 100% rename from src/xpdf-4.04/xpdf/OutputDev.cc rename to src/xpdf-4.06/xpdf/OutputDev.cc diff --git a/src/xpdf-4.04/xpdf/OutputDev.h b/src/xpdf-4.06/xpdf/OutputDev.h similarity index 100% rename from src/xpdf-4.04/xpdf/OutputDev.h rename to src/xpdf-4.06/xpdf/OutputDev.h diff --git a/src/xpdf-4.04/xpdf/PDF417Barcode.cc b/src/xpdf-4.06/xpdf/PDF417Barcode.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PDF417Barcode.cc rename to src/xpdf-4.06/xpdf/PDF417Barcode.cc diff --git a/src/xpdf-4.04/xpdf/PDF417Barcode.h b/src/xpdf-4.06/xpdf/PDF417Barcode.h similarity index 100% rename from src/xpdf-4.04/xpdf/PDF417Barcode.h rename to src/xpdf-4.06/xpdf/PDF417Barcode.h diff --git a/src/xpdf-4.04/xpdf/PDFCore.cc b/src/xpdf-4.06/xpdf/PDFCore.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PDFCore.cc rename to src/xpdf-4.06/xpdf/PDFCore.cc diff --git a/src/xpdf-4.04/xpdf/PDFCore.h b/src/xpdf-4.06/xpdf/PDFCore.h similarity index 100% rename from src/xpdf-4.04/xpdf/PDFCore.h rename to src/xpdf-4.06/xpdf/PDFCore.h diff --git a/src/xpdf-4.04/xpdf/PDFDoc.cc b/src/xpdf-4.06/xpdf/PDFDoc.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PDFDoc.cc rename to src/xpdf-4.06/xpdf/PDFDoc.cc diff --git a/src/xpdf-4.04/xpdf/PDFDoc.h b/src/xpdf-4.06/xpdf/PDFDoc.h similarity index 100% rename from src/xpdf-4.04/xpdf/PDFDoc.h rename to src/xpdf-4.06/xpdf/PDFDoc.h diff --git a/src/xpdf-4.04/xpdf/PDFDocEncoding.cc b/src/xpdf-4.06/xpdf/PDFDocEncoding.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PDFDocEncoding.cc rename to src/xpdf-4.06/xpdf/PDFDocEncoding.cc diff --git a/src/xpdf-4.04/xpdf/PDFDocEncoding.h b/src/xpdf-4.06/xpdf/PDFDocEncoding.h similarity index 100% rename from src/xpdf-4.04/xpdf/PDFDocEncoding.h rename to src/xpdf-4.06/xpdf/PDFDocEncoding.h diff --git a/src/xpdf-4.04/xpdf/PSOutputDev.cc b/src/xpdf-4.06/xpdf/PSOutputDev.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PSOutputDev.cc rename to src/xpdf-4.06/xpdf/PSOutputDev.cc diff --git a/src/xpdf-4.04/xpdf/PSOutputDev.h b/src/xpdf-4.06/xpdf/PSOutputDev.h similarity index 100% rename from src/xpdf-4.04/xpdf/PSOutputDev.h rename to src/xpdf-4.06/xpdf/PSOutputDev.h diff --git a/src/xpdf-4.04/xpdf/PSTokenizer.cc b/src/xpdf-4.06/xpdf/PSTokenizer.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PSTokenizer.cc rename to src/xpdf-4.06/xpdf/PSTokenizer.cc diff --git a/src/xpdf-4.04/xpdf/PSTokenizer.h b/src/xpdf-4.06/xpdf/PSTokenizer.h similarity index 100% rename from src/xpdf-4.04/xpdf/PSTokenizer.h rename to src/xpdf-4.06/xpdf/PSTokenizer.h diff --git a/src/xpdf-4.04/xpdf/Page.cc b/src/xpdf-4.06/xpdf/Page.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Page.cc rename to src/xpdf-4.06/xpdf/Page.cc diff --git a/src/xpdf-4.04/xpdf/Page.h b/src/xpdf-4.06/xpdf/Page.h similarity index 100% rename from src/xpdf-4.04/xpdf/Page.h rename to src/xpdf-4.06/xpdf/Page.h diff --git a/src/xpdf-4.04/xpdf/Parser.cc b/src/xpdf-4.06/xpdf/Parser.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Parser.cc rename to src/xpdf-4.06/xpdf/Parser.cc diff --git a/src/xpdf-4.04/xpdf/Parser.h b/src/xpdf-4.06/xpdf/Parser.h similarity index 100% rename from src/xpdf-4.04/xpdf/Parser.h rename to src/xpdf-4.06/xpdf/Parser.h diff --git a/src/xpdf-4.04/xpdf/PreScanOutputDev.cc b/src/xpdf-4.06/xpdf/PreScanOutputDev.cc similarity index 100% rename from src/xpdf-4.04/xpdf/PreScanOutputDev.cc rename to src/xpdf-4.06/xpdf/PreScanOutputDev.cc diff --git a/src/xpdf-4.04/xpdf/PreScanOutputDev.h b/src/xpdf-4.06/xpdf/PreScanOutputDev.h similarity index 100% rename from src/xpdf-4.04/xpdf/PreScanOutputDev.h rename to src/xpdf-4.06/xpdf/PreScanOutputDev.h diff --git a/src/xpdf-4.04/xpdf/SecurityHandler.cc b/src/xpdf-4.06/xpdf/SecurityHandler.cc similarity index 100% rename from src/xpdf-4.04/xpdf/SecurityHandler.cc rename to src/xpdf-4.06/xpdf/SecurityHandler.cc diff --git a/src/xpdf-4.04/xpdf/SecurityHandler.h b/src/xpdf-4.06/xpdf/SecurityHandler.h similarity index 100% rename from src/xpdf-4.04/xpdf/SecurityHandler.h rename to src/xpdf-4.06/xpdf/SecurityHandler.h diff --git a/src/xpdf-4.04/xpdf/ShadingImage.cc b/src/xpdf-4.06/xpdf/ShadingImage.cc similarity index 100% rename from src/xpdf-4.04/xpdf/ShadingImage.cc rename to src/xpdf-4.06/xpdf/ShadingImage.cc diff --git a/src/xpdf-4.04/xpdf/ShadingImage.h b/src/xpdf-4.06/xpdf/ShadingImage.h similarity index 100% rename from src/xpdf-4.04/xpdf/ShadingImage.h rename to src/xpdf-4.06/xpdf/ShadingImage.h diff --git a/src/xpdf-4.04/xpdf/SplashOutputDev.cc b/src/xpdf-4.06/xpdf/SplashOutputDev.cc similarity index 100% rename from src/xpdf-4.04/xpdf/SplashOutputDev.cc rename to src/xpdf-4.06/xpdf/SplashOutputDev.cc diff --git a/src/xpdf-4.04/xpdf/SplashOutputDev.h b/src/xpdf-4.06/xpdf/SplashOutputDev.h similarity index 100% rename from src/xpdf-4.04/xpdf/SplashOutputDev.h rename to src/xpdf-4.06/xpdf/SplashOutputDev.h diff --git a/src/xpdf-4.04/xpdf/Stream-CCITT.h b/src/xpdf-4.06/xpdf/Stream-CCITT.h similarity index 100% rename from src/xpdf-4.04/xpdf/Stream-CCITT.h rename to src/xpdf-4.06/xpdf/Stream-CCITT.h diff --git a/src/xpdf-4.04/xpdf/Stream.cc b/src/xpdf-4.06/xpdf/Stream.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Stream.cc rename to src/xpdf-4.06/xpdf/Stream.cc diff --git a/src/xpdf-4.04/xpdf/Stream.h b/src/xpdf-4.06/xpdf/Stream.h similarity index 100% rename from src/xpdf-4.04/xpdf/Stream.h rename to src/xpdf-4.06/xpdf/Stream.h diff --git a/src/xpdf-4.04/xpdf/TextOutputDev.cc b/src/xpdf-4.06/xpdf/TextOutputDev.cc similarity index 100% rename from src/xpdf-4.04/xpdf/TextOutputDev.cc rename to src/xpdf-4.06/xpdf/TextOutputDev.cc diff --git a/src/xpdf-4.04/xpdf/TextOutputDev.h b/src/xpdf-4.06/xpdf/TextOutputDev.h similarity index 100% rename from src/xpdf-4.04/xpdf/TextOutputDev.h rename to src/xpdf-4.06/xpdf/TextOutputDev.h diff --git a/src/xpdf-4.04/xpdf/TextString.cc b/src/xpdf-4.06/xpdf/TextString.cc similarity index 100% rename from src/xpdf-4.04/xpdf/TextString.cc rename to src/xpdf-4.06/xpdf/TextString.cc diff --git a/src/xpdf-4.04/xpdf/TextString.h b/src/xpdf-4.06/xpdf/TextString.h similarity index 100% rename from src/xpdf-4.04/xpdf/TextString.h rename to src/xpdf-4.06/xpdf/TextString.h diff --git a/src/xpdf-4.04/xpdf/TileCache.cc b/src/xpdf-4.06/xpdf/TileCache.cc similarity index 100% rename from src/xpdf-4.04/xpdf/TileCache.cc rename to src/xpdf-4.06/xpdf/TileCache.cc diff --git a/src/xpdf-4.04/xpdf/TileCache.h b/src/xpdf-4.06/xpdf/TileCache.h similarity index 100% rename from src/xpdf-4.04/xpdf/TileCache.h rename to src/xpdf-4.06/xpdf/TileCache.h diff --git a/src/xpdf-4.04/xpdf/TileCompositor.cc b/src/xpdf-4.06/xpdf/TileCompositor.cc similarity index 100% rename from src/xpdf-4.04/xpdf/TileCompositor.cc rename to src/xpdf-4.06/xpdf/TileCompositor.cc diff --git a/src/xpdf-4.04/xpdf/TileCompositor.h b/src/xpdf-4.06/xpdf/TileCompositor.h similarity index 100% rename from src/xpdf-4.04/xpdf/TileCompositor.h rename to src/xpdf-4.06/xpdf/TileCompositor.h diff --git a/src/xpdf-4.04/xpdf/TileMap.cc b/src/xpdf-4.06/xpdf/TileMap.cc similarity index 100% rename from src/xpdf-4.04/xpdf/TileMap.cc rename to src/xpdf-4.06/xpdf/TileMap.cc diff --git a/src/xpdf-4.04/xpdf/TileMap.h b/src/xpdf-4.06/xpdf/TileMap.h similarity index 100% rename from src/xpdf-4.04/xpdf/TileMap.h rename to src/xpdf-4.06/xpdf/TileMap.h diff --git a/src/xpdf-4.04/xpdf/UTF8.cc b/src/xpdf-4.06/xpdf/UTF8.cc similarity index 100% rename from src/xpdf-4.04/xpdf/UTF8.cc rename to src/xpdf-4.06/xpdf/UTF8.cc diff --git a/src/xpdf-4.04/xpdf/UTF8.h b/src/xpdf-4.06/xpdf/UTF8.h similarity index 100% rename from src/xpdf-4.04/xpdf/UTF8.h rename to src/xpdf-4.06/xpdf/UTF8.h diff --git a/src/xpdf-4.04/xpdf/UnicodeMap.cc b/src/xpdf-4.06/xpdf/UnicodeMap.cc similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeMap.cc rename to src/xpdf-4.06/xpdf/UnicodeMap.cc diff --git a/src/xpdf-4.04/xpdf/UnicodeMap.h b/src/xpdf-4.06/xpdf/UnicodeMap.h similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeMap.h rename to src/xpdf-4.06/xpdf/UnicodeMap.h diff --git a/src/xpdf-4.04/xpdf/UnicodeMapTables.h b/src/xpdf-4.06/xpdf/UnicodeMapTables.h similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeMapTables.h rename to src/xpdf-4.06/xpdf/UnicodeMapTables.h diff --git a/src/xpdf-4.04/xpdf/UnicodeRemapping.cc b/src/xpdf-4.06/xpdf/UnicodeRemapping.cc similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeRemapping.cc rename to src/xpdf-4.06/xpdf/UnicodeRemapping.cc diff --git a/src/xpdf-4.04/xpdf/UnicodeRemapping.h b/src/xpdf-4.06/xpdf/UnicodeRemapping.h similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeRemapping.h rename to src/xpdf-4.06/xpdf/UnicodeRemapping.h diff --git a/src/xpdf-4.04/xpdf/UnicodeTypeTable.cc b/src/xpdf-4.06/xpdf/UnicodeTypeTable.cc similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeTypeTable.cc rename to src/xpdf-4.06/xpdf/UnicodeTypeTable.cc diff --git a/src/xpdf-4.04/xpdf/UnicodeTypeTable.h b/src/xpdf-4.06/xpdf/UnicodeTypeTable.h similarity index 100% rename from src/xpdf-4.04/xpdf/UnicodeTypeTable.h rename to src/xpdf-4.06/xpdf/UnicodeTypeTable.h diff --git a/src/xpdf-4.04/xpdf/WebFont.cc b/src/xpdf-4.06/xpdf/WebFont.cc similarity index 100% rename from src/xpdf-4.04/xpdf/WebFont.cc rename to src/xpdf-4.06/xpdf/WebFont.cc diff --git a/src/xpdf-4.04/xpdf/WebFont.h b/src/xpdf-4.06/xpdf/WebFont.h similarity index 100% rename from src/xpdf-4.04/xpdf/WebFont.h rename to src/xpdf-4.06/xpdf/WebFont.h diff --git a/src/xpdf-4.04/xpdf/XFAScanner.cc b/src/xpdf-4.06/xpdf/XFAScanner.cc similarity index 100% rename from src/xpdf-4.04/xpdf/XFAScanner.cc rename to src/xpdf-4.06/xpdf/XFAScanner.cc diff --git a/src/xpdf-4.04/xpdf/XFAScanner.h b/src/xpdf-4.06/xpdf/XFAScanner.h similarity index 100% rename from src/xpdf-4.04/xpdf/XFAScanner.h rename to src/xpdf-4.06/xpdf/XFAScanner.h diff --git a/src/xpdf-4.04/xpdf/XRef.cc b/src/xpdf-4.06/xpdf/XRef.cc similarity index 100% rename from src/xpdf-4.04/xpdf/XRef.cc rename to src/xpdf-4.06/xpdf/XRef.cc diff --git a/src/xpdf-4.04/xpdf/XRef.h b/src/xpdf-4.06/xpdf/XRef.h similarity index 100% rename from src/xpdf-4.04/xpdf/XRef.h rename to src/xpdf-4.06/xpdf/XRef.h diff --git a/src/xpdf-4.04/xpdf/Zoox.cc b/src/xpdf-4.06/xpdf/Zoox.cc similarity index 100% rename from src/xpdf-4.04/xpdf/Zoox.cc rename to src/xpdf-4.06/xpdf/Zoox.cc diff --git a/src/xpdf-4.04/xpdf/Zoox.h b/src/xpdf-4.06/xpdf/Zoox.h similarity index 100% rename from src/xpdf-4.04/xpdf/Zoox.h rename to src/xpdf-4.06/xpdf/Zoox.h diff --git a/src/xpdf-4.04/xpdf/config.h b/src/xpdf-4.06/xpdf/config.h similarity index 100% rename from src/xpdf-4.04/xpdf/config.h rename to src/xpdf-4.06/xpdf/config.h diff --git a/src/xpdf-4.04/xpdf/pdfdetach.cc b/src/xpdf-4.06/xpdf/pdfdetach.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdfdetach.cc rename to src/xpdf-4.06/xpdf/pdfdetach.cc diff --git a/src/xpdf-4.04/xpdf/pdffonts.cc b/src/xpdf-4.06/xpdf/pdffonts.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdffonts.cc rename to src/xpdf-4.06/xpdf/pdffonts.cc diff --git a/src/xpdf-4.04/xpdf/pdfimages.cc b/src/xpdf-4.06/xpdf/pdfimages.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdfimages.cc rename to src/xpdf-4.06/xpdf/pdfimages.cc diff --git a/src/xpdf-4.04/xpdf/pdfinfo.cc b/src/xpdf-4.06/xpdf/pdfinfo.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdfinfo.cc rename to src/xpdf-4.06/xpdf/pdfinfo.cc diff --git a/src/xpdf-4.04/xpdf/pdftohtml.cc b/src/xpdf-4.06/xpdf/pdftohtml.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdftohtml.cc rename to src/xpdf-4.06/xpdf/pdftohtml.cc diff --git a/src/xpdf-4.04/xpdf/pdftopng.cc b/src/xpdf-4.06/xpdf/pdftopng.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdftopng.cc rename to src/xpdf-4.06/xpdf/pdftopng.cc diff --git a/src/xpdf-4.04/xpdf/pdftoppm.cc b/src/xpdf-4.06/xpdf/pdftoppm.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdftoppm.cc rename to src/xpdf-4.06/xpdf/pdftoppm.cc diff --git a/src/xpdf-4.04/xpdf/pdftops.cc b/src/xpdf-4.06/xpdf/pdftops.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdftops.cc rename to src/xpdf-4.06/xpdf/pdftops.cc diff --git a/src/xpdf-4.04/xpdf/pdftotext.cc b/src/xpdf-4.06/xpdf/pdftotext.cc similarity index 100% rename from src/xpdf-4.04/xpdf/pdftotext.cc rename to src/xpdf-4.06/xpdf/pdftotext.cc diff --git a/src/xpdf-4.04/xpdf/winLongPath.exe.manifest b/src/xpdf-4.06/xpdf/winLongPath.exe.manifest similarity index 100% rename from src/xpdf-4.04/xpdf/winLongPath.exe.manifest rename to src/xpdf-4.06/xpdf/winLongPath.exe.manifest From 84a4ccf981aa08de1ab5213f004c8f071d05865f Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 13:29:37 +0200 Subject: [PATCH 09/10] Update to match new function signatures --- MANIFEST.in | 6 +++--- Makefile | 4 ++-- setup.py | 12 +++++++----- src/xpydf/ImageDataDev.h | 18 +++++++++++++----- src/xpydf/ImageInfoDev.h | 11 +++++++++-- src/xpydf/PdfLoader.cc | 12 ++++++------ 6 files changed, 40 insertions(+), 23 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 63b1167..7dc74b3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,7 +6,7 @@ include src/freetype/include/freetype/config/*.h include src/freetype/include/freetype/internal/*.h include src/freetype/include/freetype/internal/*/*.h include src/xpydf/* -include src/xpdf-4.04/** -include src/xpdf-4.04/**/*.cc -include src/xpdf-4.04/**/*.h +include src/xpdf-4.06/** +include src/xpdf-4.06/**/*.cc +include src/xpdf-4.06/**/*.h include src/xpydf/*.pyi diff --git a/Makefile b/Makefile index 97eb59d..e3099d4 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,16 @@ PROGNAME = a.out OBJDIR = obj/ +XDIR = src/xpdf-4.06/ CC = g++ -std=c++17 C = gcc -pedantic -std=c99 WARNFLAGS = -Wall # -Wno-deprecated-declarations -Wno-writable-strings -CCFLAGS = -O3 $(WARNFLAGS) -MD -Isrc/xpdf-4.04 -Isrc/xpdf-4.04/goo -Isrc/xpdf-4.04/splash -Isrc/xpdf-4.04/xpdf -Isrc/xpdf-4.04/fofi -I/usr/local/include -Isrc/freetype/include -Isrc/freetype/include/freetype +CCFLAGS = -O3 $(WARNFLAGS) -MD -I$(XDIR) -I$(XDIR)/goo -I$(XDIR)/splash -I$(XDIR)/xpdf -I$(XDIR)/fofi -I/usr/local/include -Isrc/freetype/include -Isrc/freetype/include/freetype CFLAGS = -O3 $(WARNFLAGS) -MD -pthread -DFT_CONFIG_CONFIG_H="" -DFT_CONFIG_MODULES_H="" -DFT_CONFIG_OPTIONS_H="" -DFT2_BUILD_LIBRARY -Isrc/freetype/include -Isrc/freetype/include/freetype -Isrc/freetype/include/freetype/config -Isrc/freetype/include/freetype/internal PYDIR = src/xpydf/ -XDIR = src/xpdf-4.04/ SPLASH_DIR = $(XDIR)splash/ FOFI_DIR = $(XDIR)fofi/ GOO_DIR = $(XDIR)goo/ diff --git a/setup.py b/setup.py index aa6e687..44f1815 100644 --- a/setup.py +++ b/setup.py @@ -6,11 +6,13 @@ from setuptools.command.build_ext import build_ext from setuptools import Extension, setup +xpdf_src_dir = "src/xpdf-4.06" + python_dir = Path("src/xpydf") -xpdf_dir = Path("src/xpdf-4.04/xpdf") -splash_dir = Path("src/xpdf-4.04/splash") -fofi_dir = Path("src/xpdf-4.04/fofi") -goo_dir = Path("src/xpdf-4.04/goo") +xpdf_dir = Path(f"{xpdf_src_dir}/xpdf") +splash_dir = Path(f"{xpdf_src_dir}/splash") +fofi_dir = Path(f"{xpdf_src_dir}/fofi") +goo_dir = Path(f"{xpdf_src_dir}/goo") python_src = glob(str(python_dir / "*.cc")) splash_src = glob(str(splash_dir / "*.cc")) @@ -137,7 +139,7 @@ "cXpdfPython", sources = python_src + xpdf_src + splash_src + goo_src + fofi_src + freetype_sources, include_dirs = [ - "src/xpdf-4.04", + str(xpdf_src_dir), str(xpdf_dir), str(fofi_dir), str(splash_dir), diff --git a/src/xpydf/ImageDataDev.h b/src/xpydf/ImageDataDev.h index f16a789..2e5b9f2 100644 --- a/src/xpydf/ImageDataDev.h +++ b/src/xpydf/ImageDataDev.h @@ -20,11 +20,19 @@ typedef struct Image { class ImageDataDev: public ImageOutputDev { public: - ImageDataDev(char *fileRootA, GBool dumpJPEGA, GBool dumpRawA, - GBool listA, std::vector *imagesA) : ImageOutputDev(fileRootA, dumpJPEGA, dumpRawA, listA) { - imgNum = 0; - images = imagesA; - }; + ImageDataDev( + char *fileRootA, + GBool dumpJPEGA, + GBool dumpJPXA, + GBool dumpRawA, + GBool uniqueA, + GBool listA, + GBool listOnlyA, + std::vector *imagesA + ) : ImageOutputDev(fileRootA, dumpJPEGA, dumpJPXA, dumpRawA, uniqueA, listA, listOnlyA) { + imgNum = 0; + images = imagesA; + }; virtual void startPage(int pageNum, GfxState *state); diff --git a/src/xpydf/ImageInfoDev.h b/src/xpydf/ImageInfoDev.h index 51d0619..61f279b 100644 --- a/src/xpydf/ImageInfoDev.h +++ b/src/xpydf/ImageInfoDev.h @@ -16,8 +16,15 @@ typedef struct ImageInfo { class ImageInfoDev: public ImageOutputDev { public: - ImageInfoDev(char *fileRootA, GBool dumpJPEGA, GBool dumpRawA, - GBool listA) : ImageOutputDev(fileRootA, dumpJPEGA, dumpRawA, listA) {}; + ImageInfoDev( + char *fileRootA, + GBool dumpJPEGA, + GBool dumpJPXA, + GBool dumpRawA, + GBool uniqueA, + GBool listA, + GBool listOnlyA + ) : ImageOutputDev(fileRootA, dumpJPEGA, dumpJPXA, dumpRawA, uniqueA, listA, listOnlyA) {}; virtual void startPage(int pageNum, GfxState *state); diff --git a/src/xpydf/PdfLoader.cc b/src/xpydf/PdfLoader.cc index e3a248e..c915de6 100644 --- a/src/xpydf/PdfLoader.cc +++ b/src/xpydf/PdfLoader.cc @@ -119,7 +119,7 @@ std::vector PdfLoader::extractText() { if (textOut->isOk()) { for (int page = firstPage; page <= lastPage; page++) { stream->str(""); - doc->displayPages(textOut, page, page, 72, 72, 0, gFalse, gTrue, gFalse); + doc->displayPages(textOut, NULL, page, page, 72, 72, 0, gFalse, gTrue, gFalse); pages.push_back(stream->str()); } } @@ -147,7 +147,7 @@ std::vector PdfLoader::extractPageInfo() { firstPage = 1; lastPage = doc->getNumPages(); - imageOut = new ImageInfoDev(dummyFile, gFalse, gFalse, gTrue); + imageOut = new ImageInfoDev(dummyFile, gFalse, gFalse, gFalse, gFalse, gTrue, gFalse); if (imageOut->isOk()) { for (int page = firstPage; page <= lastPage; page++) { @@ -156,7 +156,7 @@ std::vector PdfLoader::extractPageInfo() { double page_width = box->x2 - box->x1; double page_height = box->y2 - box->y1; - doc->displayPages(imageOut, page, page, 72, 72, 0, gFalse, gTrue, gFalse); + doc->displayPages(imageOut, NULL, page, page, 72, 72, 0, gFalse, gTrue, gFalse); std::vector images(imageOut->images); pagesInfo.push_back(PageImageInfo{ @@ -187,10 +187,10 @@ std::vector PdfLoader::extractImages(int pageNum) { goto err; } - imageOut = new ImageDataDev(dummyFile, gFalse, gFalse, gTrue, &images); + imageOut = new ImageDataDev(dummyFile, gFalse, gFalse, gFalse, gFalse, gTrue, gFalse, &images); if (imageOut->isOk()) { - doc->displayPages(imageOut, pageNum, pageNum, 72, 72, 0, gFalse, gTrue, gFalse); + doc->displayPages(imageOut, NULL, pageNum, pageNum, 72, 72, 0, gFalse, gTrue, gFalse); } delete imageOut; @@ -222,7 +222,7 @@ Image PdfLoader::pageToImage(int pageNum, int dpi) { splashOut->startDoc(doc->getXRef()); - doc->displayPages(splashOut, pageNum, pageNum, dpi, dpi, 0, gFalse, gTrue, gFalse); + doc->displayPages(splashOut, NULL, pageNum, pageNum, dpi, dpi, 0, gFalse, gTrue, gFalse); bitmap = splashOut->getBitmap(); pageImage = { From 616c3ca522d966bebde87fff25b27d7331b8a40d Mon Sep 17 00:00:00 2001 From: Matthijs Wesseling Date: Wed, 1 Apr 2026 13:36:16 +0200 Subject: [PATCH 10/10] Update docs --- src/xpdf-4.06/ANNOUNCE | 34 ++++-- src/xpdf-4.06/CHANGES | 205 +++++++++++++++++++++++++++++++++ src/xpdf-4.06/CMakeLists.txt | 2 +- src/xpdf-4.06/INSTALL | 29 +++-- src/xpdf-4.06/README | 6 +- src/xpdf-4.06/cmake-config.txt | 66 ++++------- 6 files changed, 279 insertions(+), 63 deletions(-) diff --git a/src/xpdf-4.06/ANNOUNCE b/src/xpdf-4.06/ANNOUNCE index c20dcaf..c14a473 100644 --- a/src/xpdf-4.06/ANNOUNCE +++ b/src/xpdf-4.06/ANNOUNCE @@ -1,4 +1,4 @@ -Subject: ANNOUNCE: Xpdf 4.04 - a PDF viewer and related tools +Subject: ANNOUNCE: Xpdf 4.06 - a PDF viewer and related tools Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the open source Portable Document Format (PDF) viewer. The Xpdf project @@ -10,16 +10,32 @@ non-graphical components (pdftops, pdftotext, etc.) run on Linux, Unix, Windows, MacOSX, and pretty much any other system with a decent C++ compiler. -4.04 is primarily a bug fix release. There are some new features: +4.06 is primarily a bug fix release. There are some new features: -* XpdfReader improvements: - - Implemented selection extension via shift-click, and word/line - selection via double/triple click. - - Added default bindings for ctrl-mousewheel-up/down to zoom in/out. - - Added a help menu item that shows all of the key bindings. +* New command line options/features: + - Added the '-listonly' flag to pdfimages. + - Added the '-u' option to pdfimages. + - Added the '-J' option to pdfimages to dump JPEG 2000 images. + - Modified pdftohtml to generate a nicer index page; add the + '-noframe' option to generate the previous-style index page. + +* New configuration options: + - Added the 'initialMaximized' xpdfrc setting. + - Added the 'discardCoveredText' xpdfrc setting. + - Added the 'preferXFAFieldValues' xpdfrc setting. -* Various new command line options for pdftotext, pdftohtml, pdftoppm, - pdftopng, and xpdf. +* XpdfReader improvements: + - Added the reverseVideoMode, normalVideoMode, and toggleVideoMode + commands; added the view -> reverse video menu item. + - Added a '%t' escape to include the currently selected text in the + argument to xpdf's 'run' command. + - Use the XDG config and state file directories on Linux. + - Added a file:close menu item to Xpdf. + +* Misc changes: + - Changed the default from Level 2 to Level 3 PostScript. + - Added support to pdftohtml for internal links (i.e., links to + pages in the same document). See the `CHANGES' file for a complete list of changes. diff --git a/src/xpdf-4.06/CHANGES b/src/xpdf-4.06/CHANGES index 564aff3..2ecce38 100644 --- a/src/xpdf-4.06/CHANGES +++ b/src/xpdf-4.06/CHANGES @@ -2810,3 +2810,208 @@ Added an integer overflow check in JPXStream. (JPXStream issue) The DCT (JPEG) decoder was allowing the 'interleaved' flag to be changed after the first scan of the image. (CVE-2022-24106) [Thanks to Shin Ando @ Ricera Security for the bug report.] + +4.05 (2024-feb-08) +------------------ +Added the '-overwrite' option to pdftohtml. +Added the 'ignoreWrongSizeToUnicode' xpdfrc setting. +Added the loadSession and saveSession commands, and the 'Load last + session' menu item. +Added code to automatically save and restore the xpdf session under + control of a session manager. This has not been thoroughly tested + yet. +Added the zoomScaleFactor xpdfrc setting. +Added the zoomValues xpdfrc setting. +Added a 'smart case' option for search in xpdf. +Added the '-custom' flag to pdfinfo. +Added a color/gray/mono switch to the 'save image' dialog. +Added the separateRotatedText xpdfrc setting. +Added the '-meta' flag to pdftohtml. +Added the allowLinksToChangeZoom xpdfrc setting. +Added the 'uses JavaScript' output to pdfinfo. +Implemented pattern stroking of text. Also fixed the various + combinations of filling/stroking with color/pattern + clipping, some + of which weren't being handled correctly. +Pdftops now (re)compresses any uncompressed or RLE-compressed images. +On an out-of-memory error, the command line tools now exit with an + "out of memory" message, rather than an exception message. +Add code to pdfimages to extract images from tiling patterns. +Pdftops can now embed external 8-bit OpenType CFF fonts. +Fixed a corner case in the text extractor related to characters drawn + at extremely large coordinates. [Thanks to elvadisas for the bug + report.] +Fixed an integer overflow in the transparency group code. [Thanks to + elvadisas for the bug report.] +Modify Annots::Annots() to skip annotations that have been turned into + AcroFormFields -- invalid Widget-type annots will now be rendered as + annots. +Added a missing integer overflow check in the JBIG2 decoder. [Thanks + to sangjun for the bug report.] +Added some sanity checks to the JBIG2 decoder. [Thanks to sangjun and + ycdxsb for the bug reports.] +Tiling patterns that use non-Normal blend modes can't be cached. +Fixed a bitmap size sanity check in the JBIG2 decoder. [Thanks to Han + Zheng (NCNIPC of China, Hexhive), for the bug report.] +Fixed a missing bounds check in FoFiType1C::convertToOpenType (used in + pdftohtml). [Thanks to cyth for the bug report.] +Fixed a use-after-free bug in pdftohtml. [Thanks to FeRDNYC for the + bug report.] +Merged aconf2.h into aconf.h; corrected the cmake config settings for + paths; added the BASE14_FONT_DIR config option. [Thanks to FeRDNYC + for the suggestions.] +Fixed a missing check for a zero-length index in the CFF (Type1C) font + parser. [Thanks to Yuhang Huang (NCNIPC of China), Han Zheng + (NCNIPC of China, Hexhive), Wanying Cao, Jiayu Zhao (NCNIPC of + China) for the bug report.] +Add an object loop check to Catalog::countPageTree(). +The DCT decoder wasn't checking for an SOF before the first SOS. + [Thanks to cyth for the bug report.] +The inline image decoder was skipping to end-of-stream in the wrong + stream object. [Thanks to cyth for the bug report.] +Fixed a bug in the JPEG 2000 decoder when nLayers > 1 and the + 'termination on each coding pass' flag is set. +Removed the #pragma interface/implementation stuff (which is outdated + and useless at this point). +Fixed a bug in the ICCBased color space parser that was allowing the + number of components to be zero. (CVE-2023-2662) [Thanks to + huckleberry for the bug report.] +Added checks for PDF object loops in AcroForm::scanField() + (CVE-2018-7453, CVE-2018-16369, CVE-2022-36561, CVE-2022-41844), + Catalog::readPageLabelTree2() (CVE-2023-2663), and + Catalog::readEmbeddedFileTree() (CVE-2023-2664). +The zero-width character problem can also happen if the page size is + very large -- that needs to be limited too, the same way as + character position coordinates. (CVE-2023-3044) [Thanks to jlinliu + for the bug report.] +Add some missing bounds check code in DCTStream. [Thanks to Jiahao + Liu for the bug report.] +Fix a deadlock when an object stream's length field is contained in + another object stream. (CVE-2023-3436) [Thanks to Jiahao Liu for + the bug report.] +Correctly handle tiling patterns with negative step values. +Ignore overprint in soft masks (to match Adobe's behavior). + +4.06 (2025-nov-14) +------------------ +Added the reverseVideoMode, normalVideoMode, and toggleVideoMode + commands; added the view -> reverse video menu item. +Added a '%t' escape to include the currently selected text in the + argument to xpdf's 'run' command. +Added the '-listonly' flag to pdfimages. +Changed the default from Level 2 to Level 3 PostScript. +Use the XDG config and state file directories on Linux. This means + that ~/.config/xpdf/xpdfrc will be checked first, but ~/.xpdfrc will + still be checked. The session and pages file will *only* be used if + they are in ~/.local/state/xpdf/session and + ~/.local/state/xpdf/pages. (XDG support can be disabled at compile + time with 'cmake -DUSE_XDG=OFF'.) +Added the '-u' option to pdfimages. +Added the 'initialMaximized' xpdfrc setting. +Added the 'discardCoveredText' xpdfrc setting. +Added a file:close menu item to Xpdf. +Added the 'preferXFAFieldValues' xpdfrc setting. +Added the '-J' option to pdfimages to dump JPEG 2000 images. +Modified pdftohtml to generate a nicer index page; add the '-noframe' + option to generate the previous-style index page. +Added support to pdftohtml for internal links (i.e., links to pages in + the same document). +Tweaked the antialiasing code to make the output look a little + lighter, and hopefully nicer. +The command line tools should print version info ('pdftotext -v' etc) + to stdout, not stderr. +Added support for AIS (alpha is shape) for soft masked images drawn in + knockout transparency groups. +Tweaked the code that determines a font's ascent metric, trying (yet + again) to make it a little more robust to bogus values in the + FontDescriptor. +On Linux systems (and anything else that uses fontconfig) look for the + Base-14 fonts under the newer Nimbus names via fontconfig (in + addition to checking for the older gs font names in 'standard' + directories). +Pdftohtml now treats text drawn before a full-page fill as invisible. +Added Thai.unicodeRemap to the Thai language support packge: it maps + old Microsoft private use area Thai diacritics to correct Unicode + values. +Tweak the way invisible (OCR) text is handled in the output from + pdftohtml. +Tweaked the appearance of the tab pane in the sidebar. +Fixed a missing bounds check (not exploitable) in + GfxFont::readFontDescriptor(). [Thanks to Sangbin Kim for the bug + report.] +Don't allow negative object or generation numbers in indirect + references. (CVE-2024-2971) [Thanks to Song Jiaxuan (Huazhong + University of Science and Technology) for the bug report.] +Extended the XRef/Parser object loop detector to catch loops that + involve object streams. (CVE-2024-3247) [Thanks to Zhijie Zhang, + from Institute of Information Engineering, Chinese Academy of + Sciences for the bug report.] +Extended the Catalog::readFileAttachmentAnnots object loop detector to + handle another case. (CVE-2024-3248) [Thanks to Wang Dawei and Zhou + Geng, from Zhongguancun Laboratory for the bug report.] +Added a missing zero check to the size argument in + UnicodeRemapping::map(). (CVE-2024-3900) [Thanks to Sangbin Kim, + from Korea University Sejong campus for the bug report.] +Fixed a bounds check in FoFiType1::parse() that was being optimized + away by modern compilers. (CVE-2024-4141) [Thanks to Wu JieCong for + the bug report.] +If the XRefStm link in the trailer is invalid, just ignore it rather + than triggering the repair code. +Extended the resource object loop detector in PSOutputDev to handle + another case. (CVE-2024-4568) [Thanks to Ximing Fan, from School of + Cyber Science and Engineering, Sichuan University, China for the bug + report.] +Fixed a missing object type check that could lead to an out-of-bounds + array write in Annots::loadFormFieldRefs(). (CVE-2024-4976) [Thanks + to Vladislav Shevchenko (HSE university, Moscow) for the bug + report.] +Increased the size of the inter-packet data buffer for the arithmetic + decoder used by the JPX decoder. +Added another object loop check for patterns. (CVE-2024-7866) [Thanks + to xiaobaozidi for the bug report.] +Check for unreasoanbly large page box coordinates, to avoid integer + overflows. (CVE-2024-7867) [Thanks to xiaobaozidi for the bug + report.] +DCTStream::getBlock() was missing a check for the case where + DCTStream::prepare() failed due to invalid headers. (CVE-2024-7868) + [Thanks to KMFL for the bug report.] +Added a check for the case where a stream has a large number of + invalid filters, which was causing a stack overflow. [Thanks to + Michael Lynch of mtlynch.io for the bug report.] +Fixed a bug in WebFont.cc that caused a read of one element past the + end of an array. [Thanks to Mohammad Hussam Alzeyyat / mhzcyber for + the bug report.] +Added a missing mutex to protect the Annots object when using + multithreaded rendering in Xpdf. +Fixed incorrect integer overflow checking in + PostScriptFunction::exec(), which led to an out-of-bounds array + write. (CVE-2025-2574) [Thanks to Erik Viken for the bug report.] +Fixed the object loop check in AcroForm::scanField(). [Thanks to Erik + Viken for the bug report.] +Fixed the object loop check in Catalog::readPageLabelTree2(). [Thanks + to Erik Viken for the bug report.] +Added a missing bounds check in JBIG2Stream::readHalftoneRegionSeg(). + [Thanks to Erik Viken for the bug report.] +Added a missing parsed value check in + GfxGouraudTriangleShading::parse(). (CVE-2025-3154) [Thanks to Erik + Viken for the bug report.] +Added a cache for the tiling pattern tile, to handle the case where + the same tiling pattern is used multiple times in different fill + operations. +Ignore a bogus encoding for non-embedded Symbol and ZapfDingbats + fonts. +Fixed an signed/unsigned conversion problem in Splash::fillChar(). + [Thanks to Erik Viken for the bug report.] +Fixed the object loop check in Catalog::countPageTree(). [Thanks to + Gipoco for the bug report.] +Added some checking for the annotation matrix in Gfx::drawAnnot(). + [Thanks to Sofia Aberegg for the bug report.] +Removed Qt4 support from the cmake scripts. Xpdf has required Qt5/6 + for a while, but the cmake scripts weren't properly updated. +Added an object loop check for CMaps. (CVE-2025-11896) [Thanks + to landw (GitHub: Landw-hub) for the bug report.] +Fixed two uninitialized fields in StandardSecurityHandler - this is + not an exploitable bug. [Thanks to Aldo Ristori (GitHub: Kaldreic) + for the bug report.] +Fixed an unitialized value bug in JBIG2Stream::readSymbolDictSeg - + this is not an exploitable bug. [Thanks to Aldo Ristori (GitHub: + Kaldreic) for the bug report.] diff --git a/src/xpdf-4.06/CMakeLists.txt b/src/xpdf-4.06/CMakeLists.txt index 90cefe3..3227d42 100644 --- a/src/xpdf-4.06/CMakeLists.txt +++ b/src/xpdf-4.06/CMakeLists.txt @@ -8,7 +8,7 @@ # #======================================================================== -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.10) project(xpdf) diff --git a/src/xpdf-4.06/INSTALL b/src/xpdf-4.06/INSTALL index 57ff61f..b192527 100644 --- a/src/xpdf-4.06/INSTALL +++ b/src/xpdf-4.06/INSTALL @@ -1,11 +1,11 @@ Xpdf ==== -version 4.04 -2022-apr-18 +version 4.06 +2025-nov-14 The Xpdf software and documentation are -copyright 1996-2022 Glyph & Cog, LLC. +copyright 1996-2025 Glyph & Cog, LLC. Email: xpdf@xpdfreader.com WWW: http://www.xpdfreader.com/ @@ -34,8 +34,8 @@ different systems. - CMake 2.8.8 or newer - FreeType 2.0.5 or newer - Qt 5.x or 6.x (for xpdf only) - - libpng (for pdftoppm and pdftohtml) - - zlib (for pdftoppm and pdftohtml) + - libpng (for pdftopng and pdftohtml) + - zlib (for pdftopng and pdftohtml) If Qt isn't found, the GUI viewer (xpdf) won't be built, but the command line tools will still be built. @@ -112,6 +112,10 @@ different systems. -DXPDFWIDGET_PRINTING=OFF Disable printing support. + -DUSE_XDG=ON + Enables use of the XDG directories for config and state files. + This defaults to ON for Linux, and OFF for everything else. + -DSYSTEM_XPDFRC="/etc/xpdfrc" Look for a system-wide xpdfrc config file in this directory. @@ -119,9 +123,15 @@ different systems. The ${DATADIR} variable in xpdfrc config files will expand to this string. - -DCMAKE_DISABLE_FIND_PACKAGE_Qt4=1 + -DBASE14_FONT_DIR="/usr/share/fonts/type1" + By default, Xpdf will look for the URW Type 1 fonts in several + quasi-standard directories on Linux/Mac systems. This option + adds another directory to that search path. On Windows, this + does the same thing, except for the system TrueType fonts. + -DCMAKE_DISABLE_FIND_PACKAGE_Qt5Widgets=1 - Do not search for the Qt4/Qt5 libraries. This will disable + -DCMAKE_DISABLE_FIND_PACKAGE_Qt6Widgets=1 + Do not search for the Qt5/Qt6 libraries. This will disable building the GUI viewer (xpdf). Cmake will look for a "qmake" binary -- make sure the first qmake binary on your executable search path matches the desired version of Qt. @@ -141,6 +151,11 @@ different systems. Set the man directory, relative to CMAKE_INSTALL_PREFIX (typically "man" or "share/man"). + -DCMAKE_CXX_FLAGS="... -DDISABLE_SESSION_MANAGEMENT" + Disable the session manager interface, i.e., do not + automatically save and restore sessions under control of the + session manager. + * Build: make diff --git a/src/xpdf-4.06/README b/src/xpdf-4.06/README index 026460d..ad39741 100644 --- a/src/xpdf-4.06/README +++ b/src/xpdf-4.06/README @@ -1,11 +1,11 @@ Xpdf ==== -version 4.04 -2022-apr-18 +version 4.06 +2025-nov-14 The Xpdf software and documentation are -copyright 1996-2022 Glyph & Cog, LLC. +copyright 1996-2025 Glyph & Cog, LLC. Email: xpdf@xpdfreader.com WWW: http://www.xpdfreader.com/ diff --git a/src/xpdf-4.06/cmake-config.txt b/src/xpdf-4.06/cmake-config.txt index f9339b9..189e988 100644 --- a/src/xpdf-4.06/cmake-config.txt +++ b/src/xpdf-4.06/cmake-config.txt @@ -13,9 +13,6 @@ if (POLICY CMP0074) endif () if (APPLE) - if (POLICY CMP0042) - cmake_policy(SET CMP0042 NEW) - endif () set(CMAKE_MACOSX_RPATH 1) endif () @@ -24,6 +21,7 @@ include(CheckCXXSourceCompiles) include(GNUInstallDirs) enable_language(CXX) +set(CMAKE_CXX_STANDARD 11) #--- add a 'Profiling' build mode if (CMAKE_GENERATOR STREQUAL "Unix Makefiles") @@ -92,23 +90,21 @@ option(USE_EXCEPTIONS "use C++ exceptions" ON) option(USE_FIXEDPOINT "use fixed point (instead of floating point) arithmetic" OFF) option(SPLASH_CMYK "include support for CMYK rasterization" OFF) option(NO_FONTCONFIG "disable support for libfontconfig" OFF) -option(SYSTEM_XPDFRC "full path for system-wide xpdfrc file" "") -if (SYSTEM_XPDFRC) - set(SYSTEM_XPDFRC_DEFINE "#define SYSTEM_XPDFRC \"${SYSTEM_XPDFRC}\"") -else () - set(SYSTEM_XPDFRC_DEFINE "/* #undef SYSTEM_XPDFRC */") -endif () -option(XPDFRC_DATADIR "directory to use for the DATADIR xpdfrc variable" "") -if (XPDFRC_DATADIR) - set(XPDFRC_DATADIR_DEFINE "#define XPDFRC_DATADIR \"${XPDFRC_DATADIR}\"") -else () - set(XPDFRC_DATADIR_DEFINE "/* #undef XPDFRC_DATADIR */") -endif () if (WIN32) option(XPDFWIDGET_PRINTING "include printing support in XpdfWidget" OFF) else () option(XPDFWIDGET_PRINTING "include printing support in XpdfWidget" ON) endif () +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + option(USE_XDG "use XDG paths for config and state files" ON) +else () + option(USE_XDG "use XDG paths for config and state files" OFF) +endif () + +#--- paths +set(SYSTEM_XPDFRC "${SYSTEM_XPDFRC}" CACHE FILEPATH "full path for system-wide xpdfrc file") +set(XPDFRC_DATADIR "${XPDFRC_DATADIR}" CACHE PATH "directory to use for the DATADIR xpdfrc variable") +set(BASE14_FONT_DIR "${BASE14_FONT_DIR}" CACHE PATH "directory where the Base14 fonts are installed") #--- check for various library functions check_function_exists(mkstemp HAVE_MKSTEMP) @@ -208,25 +204,25 @@ find_package(PNG) find_package(Qt6Widgets QUIET) if (Qt6Widgets_FOUND) find_package(Qt6Network) + find_package(Qt6Concurrent) find_package(Qt6PrintSupport) else () find_package(Qt5Widgets QUIET) if (Qt5Widgets_FOUND) find_package(Qt5Network) + find_package(Qt5Concurrent) find_package(Qt5PrintSupport) - else () - find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork) endif () endif () if (Qt5Widgets_FOUND) message(STATUS "Qt5 found") if (XPDFWIDGET_PRINTING) - set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5PrintSupport_INCLUDE_DIRS}") - set(QT_DEFINITIONS "${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS} ${Qt5PrintSupport_DEFINITIONS}") + set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5Concurrent_INCLUDE_DIRS} ${Qt5PrintSupport_INCLUDE_DIRS}") + set(QT_DEFINITIONS "${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS} ${Qt5Concurrent_DEFINITIONS} ${Qt5PrintSupport_DEFINITIONS}") set(QT_LIBRARIES Qt5::Widgets Qt5::Network Qt5::PrintSupport) else () - set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}") - set(QT_DEFINITIONS "${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS}") + set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5Concurrent_INCLUDE_DIRS}") + set(QT_DEFINITIONS "${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS} ${Qt5Concurrent_DEFINITIONS}") set(QT_LIBRARIES Qt5::Widgets Qt5::Network) endif () if (XPDFWIDGET_PRINTING) @@ -248,13 +244,13 @@ if (Qt5Widgets_FOUND) elseif (Qt6Widgets_FOUND) message(STATUS "Qt6 found") if (XPDFWIDGET_PRINTING) - set(QT_INCLUDES "${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS} ${Qt6PrintSupport_INCLUDE_DIRS}") - set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6PrintSupport_DEFINITIONS}") - set(QT_LIBRARIES Qt6::Widgets Qt6::Network Qt6::PrintSupport) + set(QT_INCLUDES ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS} ${Qt6Concurrent_INCLUDE_DIRS} ${Qt6PrintSupport_INCLUDE_DIRS}) + set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6Concurrent_DEFINITIONS} ${Qt6PrintSupport_DEFINITIONS}") + set(QT_LIBRARIES Qt6::Widgets Qt6::Network Qt6::Concurrent Qt6::PrintSupport) else () - set(QT_INCLUDES "${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS}") - set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS}") - set(QT_LIBRARIES Qt6::Widgets Qt6::Network) + set(QT_INCLUDES ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS} ${Qt6Concurrent_INCLUDE_DIRS}) + set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6Concurrent_DEFINITIONS}") + set(QT_LIBRARIES Qt6::Widgets Qt6::Network Qt6::Concurrent) endif () if (XPDFWIDGET_PRINTING) if (APPLE) @@ -272,22 +268,6 @@ elseif (Qt6Widgets_FOUND) endif () # remove "-fPIE" here because we added "-fPIC" above string(REPLACE "-fPIE" "" QT_CFLAGS "${Qt6Widgets_EXECUTABLE_COMPILE_FLAGS}") -elseif (QT4_FOUND) - message(STATUS "Qt4 found") - if (XPDFWIDGET_PRINTING) - if (APPLE) - set(EXTRA_QT_LIBRARIES "-framework ApplicationServices") - elseif (UNIX) - find_package(Cups) - if (CUPS_FOUND) - set(EXTRA_QT_LIBRARIES ${CUPS_LIBRARIES}) - else () - set (XPDFWIDGET_PRINTING OFF) - endif () - else () - set(EXTRA_QT_LIBRARIES "") - endif () - endif () else () message(STATUS "No Qt library found") endif ()