summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2019-09-29 10:00:12 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2019-09-29 10:00:12 +0000
commit268dff1b06a01bd6be5f1ae08216c0beff08336c (patch)
treec8f90365823a9711e674704157dff65babb709b9 /Build/source/libs/xpdf/xpdf-src/xpdf
parentee6ffc65c0eb84ded1fc7d19eeb90a87541f896d (diff)
xpdf 4.02
git-svn-id: svn://tug.org/texlive/trunk@52203 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc16
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc2
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt55
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc367
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h20
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc97
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Function.h14
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc184
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h2
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc79
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h17
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc82
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h11
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc271
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h16
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc173
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h19
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc45
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h3
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc58
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h15
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc14
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc55
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h6
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc30
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/PDFDocEncoding.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc42
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc220
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h2
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc109
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h47
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc273
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h7
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc2
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc15
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/UTF8.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc384
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h69
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.cc116
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.h7
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/config.h14
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc12
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc3
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc16
46 files changed, 2398 insertions, 595 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc
index 1d312e97428..c7f30405483 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc
@@ -1542,10 +1542,11 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict,
fontSize = atof(tok->getCString());
} else {
error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string");
- fontSize = 10;
+ fontSize = 0;
if (!daToks) {
daToks = new GList();
}
+ tfPos = daToks->getLength();
daToks->append(new GString("/xpdf_default_font"));
daToks->append(new GString("10"));
daToks->append(new GString("Tf"));
@@ -1583,7 +1584,7 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict,
// compute font autosize
if (fontSize == 0) {
- for (fontSize = 20; fontSize > 1; --fontSize) {
+ for (fontSize = 10; fontSize > 1; --fontSize) {
y = dy - 3;
w2 = 0;
i = 0;
@@ -1596,7 +1597,7 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict,
y -= fontSize;
}
// approximate the descender for the last line
- if (y >= 0.33 * fontSize) {
+ if (y >= 0.33 * fontSize && w <= wMax) {
break;
}
}
@@ -1697,6 +1698,9 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict,
fontSize = w;
}
fontSize = floor(fontSize);
+ if (fontSize > 10) {
+ fontSize = 10;
+ }
if (tfPos >= 0) {
tok = (GString *)daToks->get(tfPos + 1);
tok->clear();
@@ -1783,6 +1787,9 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict,
fontSize = fontSize2;
}
fontSize = floor(fontSize);
+ if (fontSize > 10) {
+ fontSize = 10;
+ }
if (tfPos >= 0) {
tok = (GString *)daToks->get(tfPos + 1);
tok->clear();
@@ -1936,6 +1943,9 @@ void AcroFormField::drawListBox(GString **text, GBool *selection,
fontSize = fontSize2;
}
fontSize = floor(fontSize);
+ if (fontSize > 10) {
+ fontSize = 10;
+ }
if (tfPos >= 0) {
tok = (GString *)daToks->get(tfPos + 1);
tok->clear();
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
index 850c6b25651..61a1d434abf 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
@@ -845,7 +845,7 @@ GBool Annot::setFillColor(Object *colorObj) {
if (!colorObj->isArray()) {
return gFalse;
}
- for (i = 0; i < colorObj->arrayGetLength(); ++i) {
+ for (i = 0; i < colorObj->arrayGetLength() && i < 4; ++i) {
if (colorObj->arrayGet(i, &obj)->isNum()) {
color[i] = obj.getNum();
} else {
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc
index 01dbd110dca..d2f875e45fd 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc
@@ -51,6 +51,7 @@ GBool BuiltinFontWidths::getWidth(const char *name, Gushort *width) {
return gTrue;
}
}
+ *width = 0;
return gFalse;
}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt
index 8fb3f2050bb..4c88d1d351f 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt
@@ -111,7 +111,9 @@ if (HAVE_SPLASH)
${PAPER_LIBRARY}
${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS}
${DTYPE_LIBRARY}
- ${LCMS_LIBRARY})
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
else ()
add_executable(pdftops
$<TARGET_OBJECTS:xpdf_objs>
@@ -119,7 +121,11 @@ else ()
PSOutputDev.cc
pdftops.cc
)
- target_link_libraries(pdftops goo fofi ${PAPER_LIBRARY} ${LCMS_LIBRARY})
+ target_link_libraries(pdftops goo fofi
+ ${PAPER_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
endif ()
install(TARGETS pdftops RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftops.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
@@ -131,7 +137,11 @@ add_executable(pdftotext
TextOutputDev.cc
pdftotext.cc
)
-target_link_libraries(pdftotext goo fofi ${PAPER_LIBRARY} ${LCMS_LIBRARY})
+target_link_libraries(pdftotext goo fofi
+ ${PAPER_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdftotext RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftotext.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
@@ -143,13 +153,17 @@ if (HAVE_SPLASH AND PNG_FOUND)
HTMLGen.cc
SplashOutputDev.cc
TextOutputDev.cc
+ WebFont.cc
pdftohtml.cc
)
target_link_libraries(pdftohtml goo fofi splash
${PAPER_LIBRARY}
${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS}
${DTYPE_LIBRARY}
- ${LCMS_LIBRARY} ${PNG_LIBRARIES})
+ ${LCMS_LIBRARY}
+ ${PNG_LIBRARIES}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdftohtml RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftohtml.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif ()
@@ -160,7 +174,11 @@ add_executable(pdfinfo
$<TARGET_OBJECTS:xpdf_objs>
pdfinfo.cc
)
-target_link_libraries(pdfinfo goo fofi ${PAPER_LIBRARY} ${LCMS_LIBRARY})
+target_link_libraries(pdfinfo goo fofi
+ ${PAPER_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdfinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfinfo.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
@@ -170,7 +188,11 @@ add_executable(pdffonts
$<TARGET_OBJECTS:xpdf_objs>
pdffonts.cc
)
-target_link_libraries(pdffonts goo fofi ${PAPER_LIBRARY} ${LCMS_LIBRARY})
+target_link_libraries(pdffonts goo fofi
+ ${PAPER_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdffonts RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdffonts.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
@@ -180,7 +202,11 @@ add_executable(pdfdetach
$<TARGET_OBJECTS:xpdf_objs>
pdfdetach.cc
)
-target_link_libraries(pdfdetach goo fofi ${PAPER_LIBRARY} ${LCMS_LIBRARY})
+target_link_libraries(pdfdetach goo fofi
+ ${PAPER_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdfdetach RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfdetach.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
@@ -196,7 +222,9 @@ if (HAVE_SPLASH)
${PAPER_LIBRARY}
${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS}
${DTYPE_LIBRARY}
- ${LCMS_LIBRARY})
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdftoppm RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftoppm.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif ()
@@ -213,7 +241,10 @@ if (HAVE_SPLASH AND PNG_FOUND)
${PAPER_LIBRARY}
${FREETYPE_LIBRARY} ${FREETYPE_OTHER_LIBS}
${DTYPE_LIBRARY}
- ${LCMS_LIBRARY} ${PNG_LIBRARIES})
+ ${LCMS_LIBRARY}
+ ${PNG_LIBRARIES}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdftopng RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdftopng.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif ()
@@ -225,7 +256,11 @@ add_executable(pdfimages
ImageOutputDev.cc
pdfimages.cc
)
-target_link_libraries(pdfimages goo fofi ${PAPER_LIBRARY} ${LCMS_LIBRARY})
+target_link_libraries(pdfimages goo fofi
+ ${PAPER_LIBRARY}
+ ${LCMS_LIBRARY}
+ ${FONTCONFIG_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS pdfimages RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfimages.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
index 470807314a6..bec30a8dcfd 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
@@ -89,6 +89,59 @@ EmbeddedFile::~EmbeddedFile() {
}
//------------------------------------------------------------------------
+// PageLabelNode
+//------------------------------------------------------------------------
+
+class PageLabelNode {
+public:
+
+ PageLabelNode(int firstPageA, Dict *dict);
+ ~PageLabelNode();
+
+ int firstPage; // first page number covered by this node
+ int lastPage; // last page number covered by this node
+ TextString *prefix; // label prefix (may be empty)
+ int start; // value of the numeric portion of this
+ // label for the first page in the range
+ char style; // page label style
+};
+
+PageLabelNode::PageLabelNode(int firstPageA, Dict *dict) {
+ Object prefixObj, styleObj, startObj;
+
+ // convert page index to page number
+ firstPage = firstPageA + 1;
+
+ // lastPage will be filled in later
+ lastPage = -1;
+
+ if (dict->lookup("P", &prefixObj)->isString()) {
+ prefix = new TextString(prefixObj.getString());
+ } else {
+ prefix = new TextString();
+ }
+ prefixObj.free();
+
+ style = '\0';
+ if (dict->lookup("S", &styleObj)->isName()) {
+ if (strlen(styleObj.getName()) == 1) {
+ style = styleObj.getName()[0];
+ }
+ }
+ styleObj.free();
+
+ start = 1;
+ if (dict->lookup("St", &startObj)->isInt()) {
+ start = startObj.getInt();
+ }
+ startObj.free();
+}
+
+PageLabelNode::~PageLabelNode() {
+ delete prefix;
+}
+
+//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
@@ -185,6 +238,15 @@ Catalog::Catalog(PDFDoc *docA) {
// get the list of embedded files
readEmbeddedFileList(catDict.getDict());
+ // get the ViewerPreferences object
+ catDict.dictLookupNF("ViewerPreferences", &viewerPrefs);
+
+ pageLabels = NULL;
+ if (catDict.dictLookup("PageLabels", &obj)->isDict()) {
+ readPageLabelTree(&obj);
+ }
+ obj.free();
+
catDict.free();
return;
@@ -229,6 +291,10 @@ Catalog::~Catalog() {
if (embeddedFiles) {
deleteGList(embeddedFiles, EmbeddedFile);
}
+ if (pageLabels) {
+ deleteGList(pageLabels, PageLabelNode);
+ }
+ viewerPrefs.free();
}
Page *Catalog::getPage(int i) {
@@ -833,107 +899,45 @@ Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) {
return strObj;
}
-TextString *Catalog::getPageLabel(int pageNum) {
- Object catDict, node, pageLabelObj, start, prefix, style;
- GString *label, *s;
- TextString *ts;
- int firstPageIndex, pageRangeNum;
-
- if (!xref->getCatalog(&catDict)->isDict()) {
- catDict.free();
- return NULL;
- }
+void Catalog::readPageLabelTree(Object *root) {
+ PageLabelNode *label0, *label1;
+ int i;
- label = NULL;
- catDict.dictLookup("PageLabels", &node);
- if (findPageLabel(&node, pageNum - 1, &pageLabelObj, &firstPageIndex)) {
- if (pageLabelObj.isDict()) {
- if (pageLabelObj.dictLookup("P", &prefix)->isString()) {
- label = prefix.getString()->copy();
- } else {
- label = new GString();
- }
- prefix.free();
+ pageLabels = new GList();
+ readPageLabelTree2(root);
- pageRangeNum = pageNum - firstPageIndex;
- if (pageLabelObj.dictLookup("St", &start)->isInt()) {
- pageRangeNum += start.getInt() - 1;
- }
- start.free();
-
- if (pageLabelObj.dictLookup("S", &style)->isName()) {
- if (style.isName("D")) {
- label->appendf("{0:d}", pageRangeNum);
- } else if (style.isName("R")) {
- s = makeRomanNumeral(pageRangeNum, gTrue);
- label->append(s);
- delete s;
- } else if (style.isName("r")) {
- s = makeRomanNumeral(pageRangeNum, gFalse);
- label->append(s);
- delete s;
- } else if (style.isName("A")) {
- s = makeLetterLabel(pageRangeNum, gTrue);
- label->append(s);
- delete s;
- } else if (style.isName("a")) {
- s = makeLetterLabel(pageRangeNum, gFalse);
- label->append(s);
- delete s;
- }
- }
- style.free();
- }
- pageLabelObj.free();
+ if (pageLabels->getLength() == 0) {
+ deleteGList(pageLabels, PageLabelNode);
+ pageLabels = NULL;
+ return;
}
- node.free();
- catDict.free();
- ts = new TextString(label);
- delete label;
- return ts;
+ // set lastPage in each node
+ label0 = (PageLabelNode *)pageLabels->get(0);
+ for (i = 1; i < pageLabels->getLength(); ++i) {
+ label1 = (PageLabelNode *)pageLabels->get(i);
+ label0->lastPage = label1->firstPage - 1;
+ label0 = label1;
+ }
+ label0->lastPage = numPages;
}
-GBool Catalog::findPageLabel(Object *node, int pageIndex,
- Object *pageLabelObj, int *firstPageIndex) {
- Object limits, limit, nums, num, kids, kid;
+void Catalog::readPageLabelTree2(Object *node) {
+ Object nums, num, labelObj, kids, kid;
int i;
if (!node->isDict()) {
- return gFalse;
- }
-
- // we only check the lower limit because page labels are organized
- // into ranges based on their first page number -- the Nums and Kids
- // arrays are searched backward for the same reason
- if (node->dictLookup("Limits", &limits)->isArray() &&
- limits.arrayGetLength() == 2) {
- if (limits.arrayGet(0, &limit)->isInt()) {
- if (pageIndex < limit.getInt()) {
- limit.free();
- limits.free();
- return gFalse;
- }
- }
- limit.free();
+ return;
}
- limits.free();
if (node->dictLookup("Nums", &nums)->isArray()) {
- for (i = nums.arrayGetLength() / 2 - 1; i >= 0; --i) {
- if (nums.arrayGet(2*i, &num)->isInt()) {
- if (num.getInt() <= pageIndex) {
- nums.arrayGet(2*i + 1, pageLabelObj);
- *firstPageIndex = num.getInt();
- num.free();
- nums.free();
- return gTrue;
+ for (i = 0; i < nums.arrayGetLength() - 1; i += 2) {
+ if (nums.arrayGet(i, &num)->isInt()) {
+ if (nums.arrayGet(i+1, &labelObj)->isDict()) {
+ pageLabels->append(new PageLabelNode(num.getInt(),
+ labelObj.getDict()));
}
- } else {
- error(errSyntaxError, -1, "Invalid key in page label number tree");
- num.free();
- nums.free();
- return gFalse;
+ labelObj.free();
}
num.free();
}
@@ -941,20 +945,61 @@ GBool Catalog::findPageLabel(Object *node, int pageIndex,
nums.free();
if (node->dictLookup("Kids", &kids)->isArray()) {
- for (i = kids.arrayGetLength() - 1; i >= 0; --i) {
- if (kids.arrayGet(i, &kid)->isDict()) {
- if (findPageLabel(&kid, pageIndex, pageLabelObj, firstPageIndex)) {
- kid.free();
- kids.free();
- return gTrue;
- }
- }
+ for (i = 0; i < kids.arrayGetLength(); ++i) {
+ kids.arrayGet(i, &kid);
+ readPageLabelTree2(&kid);
kid.free();
}
}
kids.free();
+}
- return gFalse;
+TextString *Catalog::getPageLabel(int pageNum) {
+ PageLabelNode *label;
+ TextString *ts;
+ int pageRangeNum;
+ GString *suffix;
+
+ if (!pageLabels || !(label = findPageLabel(pageNum))) {
+ return NULL;
+ }
+
+ ts = new TextString(label->prefix);
+
+ pageRangeNum = label->start + (pageNum - label->firstPage);
+
+ suffix = NULL;
+ if (label->style == 'D') {
+ suffix = GString::format("{0:d}", pageRangeNum);
+ } else if (label->style == 'R') {
+ suffix = makeRomanNumeral(pageRangeNum, gTrue);
+ } else if (label->style == 'r') {
+ suffix = makeRomanNumeral(pageRangeNum, gFalse);
+ } else if (label->style == 'A') {
+ suffix = makeLetterLabel(pageRangeNum, gTrue);
+ } else if (label->style == 'a') {
+ suffix = makeLetterLabel(pageRangeNum, gFalse);
+ }
+ if (suffix) {
+ ts->append(suffix);
+ delete suffix;
+ }
+
+ return ts;
+}
+
+PageLabelNode *Catalog::findPageLabel(int pageNum) {
+ PageLabelNode *label;
+ int i;
+
+ //~ this could use a binary search
+ for (i = 0; i < pageLabels->getLength(); ++i) {
+ label = (PageLabelNode *)pageLabels->get(i);
+ if (pageNum >= label->firstPage && pageNum <= label->lastPage) {
+ return label;
+ }
+ }
+ return NULL;
}
GString *Catalog::makeRomanNumeral(int num, GBool uppercase) {
@@ -1022,3 +1067,131 @@ GString *Catalog::makeLetterLabel(int num, GBool uppercase) {
}
return s;
}
+
+int Catalog::getPageNumFromPageLabel(TextString *pageLabel) {
+ PageLabelNode *label;
+ int pageNum, prefixLength, i, n;
+
+ if (!pageLabels) {
+ return -1;
+ }
+ for (i = 0; i < pageLabels->getLength(); ++i) {
+ label = (PageLabelNode *)pageLabels->get(i);
+ prefixLength = label->prefix->getLength();
+ if (pageLabel->getLength() < prefixLength ||
+ memcmp(pageLabel->getUnicode(), label->prefix->getUnicode(),
+ prefixLength * sizeof(Unicode))) {
+ continue;
+ }
+ if (label->style == '\0' && pageLabel->getLength() == prefixLength) {
+ return label->firstPage;
+ }
+ if (!convertPageLabelToInt(pageLabel, prefixLength, label->style, &n)) {
+ continue;
+ }
+ if (n < label->start) {
+ continue;
+ }
+ pageNum = label->firstPage + n - label->start;
+ if (pageNum <= label->lastPage) {
+ return pageNum;
+ }
+ }
+ return -1;
+}
+
+// Attempts to convert pageLabel[prefixLength .. end] to an integer,
+// following the specified page label style. If successful, sets *n
+// and returns true; else returns false.
+GBool Catalog::convertPageLabelToInt(TextString *pageLabel, int prefixLength,
+ char style, int *n) {
+ Unicode *u;
+ Unicode delta;
+ int len, i;
+
+ len = pageLabel->getLength();
+ if (len <= prefixLength) {
+ return gFalse;
+ }
+ u = pageLabel->getUnicode();
+ if (style == 'D') {
+ *n = 0;
+ for (i = prefixLength; i < len; ++i) {
+ if (u[i] < (Unicode)'0' || u[i] > (Unicode)'9') {
+ return gFalse;
+ }
+ *n = *n * 10 + (u[i] - (Unicode)'0');
+ }
+ return gTrue;
+ } else if (style == 'R' || style == 'r') {
+ delta = style - 'R';
+ *n = 0;
+ i = prefixLength;
+ while (i < len && u[i] == (Unicode)'M' + delta) {
+ *n += 1000;
+ ++i;
+ }
+ if (i+1 < len && u[i] == (Unicode)'C' + delta &&
+ u[i+1] == (Unicode)'M' + delta) {
+ *n += 900;
+ i += 2;
+ } else if (i < len && u[i] == (Unicode)'D' + delta) {
+ *n += 500;
+ ++i;
+ } else if (i+1 < len && u[i] == (Unicode)'C' + delta &&
+ u[i+1] == (Unicode)'D' + delta) {
+ *n += 400;
+ i += 2;
+ }
+ while (i < len && u[i] == (Unicode)'C' + delta) {
+ *n += 100;
+ ++i;
+ }
+ if (i+1 < len && u[i] == (Unicode)'X' + delta &&
+ u[i+1] == (Unicode)'C' + delta) {
+ *n += 90;
+ i += 2;
+ } else if (i < len && u[i] == (Unicode)'L' + delta) {
+ *n += 50;
+ ++i;
+ } else if (i+1 < len && u[i] == (Unicode)'X' + delta &&
+ u[i+1] == (Unicode)'L' + delta) {
+ *n += 40;
+ i += 2;
+ }
+ while (i < len && u[i] == (Unicode)'X' + delta) {
+ *n += 10;
+ ++i;
+ }
+ if (i+1 < len && u[i] == (Unicode)'I' + delta &&
+ u[i+1] == (Unicode)'X' + delta) {
+ *n += 9;
+ i += 2;
+ } else if (i < len && u[i] == (Unicode)'V' + delta) {
+ *n += 5;
+ ++i;
+ } else if (i+1 < len && u[i] == (Unicode)'I' + delta &&
+ u[i+1] == (Unicode)'V' + delta) {
+ *n += 4;
+ i += 2;
+ }
+ while (i < len && u[i] == (Unicode)'I' + delta) {
+ *n += 1;
+ ++i;
+ }
+ return i == len;
+ } else if (style == 'A' || style == 'a') {
+ if (u[prefixLength] < (Unicode)style ||
+ u[prefixLength] > (Unicode)style + 25) {
+ return gFalse;
+ }
+ for (i = prefixLength + 1; i < len; ++i) {
+ if (u[i] != u[prefixLength]) {
+ return gFalse;
+ }
+ }
+ *n = (len - prefixLength - 1) * 26 + (u[i] - (Unicode)style) + 1;
+ return gTrue;
+ }
+ return gFalse;
+}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h
index 803550d7f96..b775ae9b9b8 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h
@@ -29,6 +29,7 @@ class PageAttrs;
struct Ref;
class LinkDest;
class PageTreeNode;
+class PageLabelNode;
class Form;
class TextString;
@@ -103,10 +104,20 @@ public:
Object *getEmbeddedFileStreamRef(int idx);
Object *getEmbeddedFileStreamObj(int idx, Object *strObj);
+ // Return true if the document has page labels.
+ GBool hasPageLabels() { return pageLabels != NULL; }
+
// Get the page label for page number [pageNum]. Returns NULL if
// the PDF file doesn't have page labels.
TextString *getPageLabel(int pageNum);
+ // Returns the page number corresponding to [pageLabel]. Returns -1
+ // if there is no matching page label, or if the document doesn't
+ // have page labels.
+ int getPageNumFromPageLabel(TextString *pageLabel);
+
+ Object *getViewerPreferences() { return &viewerPrefs; }
+
private:
PDFDoc *doc;
@@ -129,6 +140,8 @@ private:
Form *form; // parsed form
Object ocProperties; // OCProperties dictionary
GList *embeddedFiles; // embedded file list [EmbeddedFile]
+ GList *pageLabels; // page labels [PageLabelNode]
+ Object viewerPrefs; // ViewerPreferences object
GBool ok; // true if catalog is valid
Object *findDestInTree(Object *tree, GString *name, Object *obj);
@@ -141,10 +154,13 @@ private:
void readFileAttachmentAnnots(Object *pageNodeRef,
char *touchedObjs);
void readEmbeddedFile(Object *fileSpec, Object *name1);
- GBool findPageLabel(Object *node, int pageIndex,
- Object *pageLabelObj, int *firstPageIndex);
+ void readPageLabelTree(Object *root);
+ void readPageLabelTree2(Object *node);
+ 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);
};
#endif
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc
index 72cadd9bed1..82f32b9dd93 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc
@@ -41,7 +41,8 @@ Function::Function() {
Function::~Function() {
}
-Function *Function::parse(Object *funcObj, int recursion) {
+Function *Function::parse(Object *funcObj, int expectedInputs,
+ int expectedOutputs, int recursion) {
Function *func;
Dict *dict;
int funcType;
@@ -57,7 +58,11 @@ Function *Function::parse(Object *funcObj, int recursion) {
} else if (funcObj->isDict()) {
dict = funcObj->getDict();
} else if (funcObj->isName("Identity")) {
- return new IdentityFunction();
+ if (expectedInputs != expectedOutputs) {
+ error(errSyntaxError, -1, "Invalid use of identity function");
+ return NULL;
+ }
+ return new IdentityFunction(expectedInputs);
} else {
error(errSyntaxError, -1, "Expected function dictionary or stream");
return NULL;
@@ -76,7 +81,8 @@ Function *Function::parse(Object *funcObj, int recursion) {
} else if (funcType == 2) {
func = new ExponentialFunction(funcObj, dict);
} else if (funcType == 3) {
- func = new StitchingFunction(funcObj, dict, recursion);
+ func = new StitchingFunction(funcObj, dict, expectedInputs,
+ expectedOutputs, recursion);
} else if (funcType == 4) {
func = new PostScriptFunction(funcObj, dict);
} else {
@@ -88,6 +94,14 @@ Function *Function::parse(Object *funcObj, int recursion) {
return NULL;
}
+ if (func->getInputSize() != expectedInputs ||
+ (expectedOutputs >= 0 && func->getOutputSize() != expectedOutputs)) {
+ error(errSyntaxError, -1,
+ "Incorrect number of function inputs or outputs");
+ delete func;
+ return NULL;
+ }
+
return func;
}
@@ -169,14 +183,12 @@ GBool Function::init(Dict *dict) {
// IdentityFunction
//------------------------------------------------------------------------
-IdentityFunction::IdentityFunction() {
+IdentityFunction::IdentityFunction(int nInputs) {
int i;
- // fill these in with arbitrary values just in case they get used
- // somewhere
- m = funcMaxInputs;
- n = funcMaxOutputs;
- for (i = 0; i < funcMaxInputs; ++i) {
+ m = n = nInputs;
+ // domain info shouldn't be used anywhere
+ for (i = 0; i < nInputs; ++i) {
domain[i][0] = 0;
domain[i][1] = 1;
}
@@ -189,7 +201,7 @@ IdentityFunction::~IdentityFunction() {
void IdentityFunction::transform(double *in, double *out) {
int i;
- for (i = 0; i < funcMaxOutputs; ++i) {
+ for (i = 0; i < m; ++i) {
out[i] = in[i];
}
}
@@ -347,8 +359,13 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
//----- samples
nSamples = n;
- for (i = 0; i < m; ++i)
+ for (i = 0; i < m; ++i) {
+ if (nSamples > INT_MAX / sampleSize[i]) {
+ error(errSyntaxError, -1, "Integer overflow in sampled function setup");
+ goto err1;
+ }
nSamples *= sampleSize[i];
+ }
samples = (double *)gmallocn(nSamples, sizeof(double));
buf = 0;
bits = 0;
@@ -623,6 +640,7 @@ void ExponentialFunction::transform(double *in, double *out) {
//------------------------------------------------------------------------
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict,
+ int expectedInputs, int expectedOutputs,
int recursion) {
Object obj1, obj2;
int i;
@@ -643,7 +661,8 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict,
}
//----- Functions
- if (!dict->lookup("Functions", &obj1)->isArray()) {
+ if (!dict->lookup("Functions", &obj1)->isArray() ||
+ obj1.arrayGetLength() < 1) {
error(errSyntaxError, -1,
"Missing 'Functions' entry in stitching function");
goto err1;
@@ -658,11 +677,14 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict,
}
for (i = 0; i < k; ++i) {
if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2),
+ expectedInputs, expectedOutputs,
recursion + 1))) {
goto err2;
}
- if (funcs[i]->getInputSize() != 1 ||
- (i > 0 && funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
+ if (i == 0) {
+ n = funcs[0]->getOutputSize();
+ }
+ if (funcs[i]->getInputSize() != 1 || funcs[i]->getOutputSize() != n) {
error(errSyntaxError, -1,
"Incompatible subfunctions in stitching function");
goto err2;
@@ -1305,6 +1327,9 @@ int PostScriptFunction::exec(double *stack, int sp0) {
if (sp + 1 >= psStackSize) {
goto underflow;
}
+ if (stack[sp] == 0) {
+ goto invalidArg;
+ }
stack[sp + 1] = stack[sp + 1] / stack[sp];
++sp;
break;
@@ -1371,7 +1396,11 @@ int PostScriptFunction::exec(double *stack, int sp0) {
if (sp + 1 >= psStackSize) {
goto underflow;
}
- stack[sp + 1] = (int)stack[sp + 1] / (int)stack[sp];
+ k = (int)stack[sp];
+ if (k == 0) {
+ goto invalidArg;
+ }
+ stack[sp + 1] = (int)stack[sp + 1] / k;
++sp;
break;
case psOpIndex:
@@ -1417,7 +1446,11 @@ int PostScriptFunction::exec(double *stack, int sp0) {
if (sp + 1 >= psStackSize) {
goto underflow;
}
- stack[sp + 1] = (int)stack[sp + 1] % (int)stack[sp];
+ k = (int)stack[sp];
+ if (k == 0) {
+ goto invalidArg;
+ }
+ stack[sp + 1] = (int)stack[sp + 1] % k;
++sp;
break;
case psOpMul:
@@ -1468,22 +1501,24 @@ int PostScriptFunction::exec(double *stack, int sp0) {
if (nn < 0) {
goto invalidArg;
}
- if (sp + nn > psStackSize) {
- goto underflow;
- }
- if (k >= 0) {
- k %= nn;
- } else {
- k = -k % nn;
- if (k) {
- k = nn - k;
+ if (nn > 0) {
+ if (sp + nn > psStackSize) {
+ goto underflow;
+ }
+ if (k >= 0) {
+ k %= nn;
+ } else {
+ k = -k % nn;
+ if (k) {
+ k = nn - k;
+ }
+ }
+ for (i = 0; i < nn; ++i) {
+ tmp[i] = stack[sp + i];
+ }
+ for (i = 0; i < nn; ++i) {
+ stack[sp + i] = tmp[(i + k) % nn];
}
- }
- for (i = 0; i < nn; ++i) {
- tmp[i] = stack[sp + i];
- }
- for (i = 0; i < nn; ++i) {
- stack[sp + i] = tmp[(i + k) % nn];
}
break;
case psOpRound:
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h
index 5cf45169a49..bf1f25e51cc 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h
@@ -38,8 +38,11 @@ public:
virtual ~Function();
- // Construct a function. Returns NULL if unsuccessful.
- static Function *parse(Object *funcObj, int recursion = 0);
+ // Construct a function, with [expectedInputs] inputs and
+ // [expectedOutputs] outputs. [expectedOutputs] can be -1 to
+ // indicate unknown. Returns NULL if unsuccessful.
+ static Function *parse(Object *funcObj, int expectedInputs,
+ int expectedOutputs, int recursion = 0);
// Initialize the entries common to all function types.
GBool init(Dict *dict);
@@ -86,9 +89,9 @@ protected:
class IdentityFunction: public Function {
public:
- IdentityFunction();
+ IdentityFunction(int nInputs);
virtual ~IdentityFunction();
- virtual Function *copy() { return new IdentityFunction(); }
+ virtual Function *copy() { return new IdentityFunction(m); }
virtual int getType() { return -1; }
virtual void transform(double *in, double *out);
virtual GBool isOk() { return gTrue; }
@@ -173,7 +176,8 @@ private:
class StitchingFunction: public Function {
public:
- StitchingFunction(Object *funcObj, Dict *dict, int recursion);
+ StitchingFunction(Object *funcObj, Dict *dict, int expectedInputs,
+ int expectedOutputs, int recursion);
virtual ~StitchingFunction();
virtual Function *copy() { return new StitchingFunction(this); }
virtual int getType() { return 3; }
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc
index 5d34eb9f9ab..7a0c9c6a9a5 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc
@@ -919,12 +919,24 @@ void Gfx::opSetFlat(Object args[], int numArgs) {
}
void Gfx::opSetLineJoin(Object args[], int numArgs) {
- state->setLineJoin(args[0].getInt());
+ int lineJoin;
+
+ lineJoin = args[0].getInt();
+ if (lineJoin < 0 || lineJoin > 2) {
+ lineJoin = 0;
+ }
+ state->setLineJoin(lineJoin);
out->updateLineJoin(state);
}
void Gfx::opSetLineCap(Object args[], int numArgs) {
- state->setLineCap(args[0].getInt());
+ int lineCap;
+
+ lineCap = args[0].getInt();
+ if (lineCap < 0 || lineCap > 2) {
+ lineCap = 0;
+ }
+ state->setLineCap(lineCap);
out->updateLineCap(state);
}
@@ -1041,17 +1053,17 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
// fill/stroke overprint, overprint mode
if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) {
- if (!state->getInCachedT3Char()) {
+ if (!state->getIgnoreColorOps()) {
state->setFillOverprint(obj2.getBool());
out->updateFillOverprint(state);
} else {
- error(errSyntaxWarning, getPos(),
- "Ignoring overprint setting in cached Type 3 character");
+ error(errSyntaxWarning, getPos(), "Ignoring overprint setting"
+ " in uncolored Type 3 char or tiling pattern");
}
}
obj2.free();
if (obj1.dictLookup("OP", &obj2)->isBool()) {
- if (!state->getInCachedT3Char()) {
+ if (!state->getIgnoreColorOps()) {
state->setStrokeOverprint(obj2.getBool());
out->updateStrokeOverprint(state);
if (!haveFillOP) {
@@ -1059,18 +1071,18 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
out->updateFillOverprint(state);
}
} else {
- error(errSyntaxWarning, getPos(),
- "Ignoring overprint setting in cached Type 3 character");
+ error(errSyntaxWarning, getPos(), "Ignoring overprint setting"
+ " in uncolored Type 3 char or tiling pattern");
}
}
obj2.free();
if (obj1.dictLookup("OPM", &obj2)->isInt()) {
- if (!state->getInCachedT3Char()) {
+ if (!state->getIgnoreColorOps()) {
state->setOverprintMode(obj2.getInt());
out->updateOverprintMode(state);
} else {
- error(errSyntaxWarning, getPos(),
- "Ignoring overprint setting in cached Type 3 character");
+ error(errSyntaxWarning, getPos(), "Ignoring overprint setting"
+ " in uncolored Type 3 char or tiling pattern");
}
}
obj2.free();
@@ -1088,7 +1100,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
obj1.dictLookup("TR", &obj2);
}
if (!obj2.isNull()) {
- if (!state->getInCachedT3Char()) {
+ if (!state->getIgnoreColorOps()) {
if (obj2.isName("Default") ||
obj2.isName("Identity")) {
funcs[0] = funcs[1] = funcs[2] = funcs[3] = NULL;
@@ -1097,7 +1109,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
} else if (obj2.isArray() && obj2.arrayGetLength() == 4) {
for (i = 0; i < 4; ++i) {
obj2.arrayGet(i, &obj3);
- funcs[i] = Function::parse(&obj3);
+ funcs[i] = Function::parse(&obj3, 1, 1);
obj3.free();
if (!funcs[i]) {
break;
@@ -1108,7 +1120,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
out->updateTransfer(state);
}
} else if (obj2.isName() || obj2.isDict() || obj2.isStream()) {
- if ((funcs[0] = Function::parse(&obj2))) {
+ if ((funcs[0] = Function::parse(&obj2, 1, 1))) {
funcs[1] = funcs[2] = funcs[3] = NULL;
state->setTransfer(funcs);
out->updateTransfer(state);
@@ -1118,8 +1130,8 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
"Invalid transfer function in ExtGState");
}
} else {
- error(errSyntaxWarning, getPos(),
- "Ignoring transfer function setting in cached Type 3 character");
+ error(errSyntaxWarning, getPos(), "Ignoring transfer function setting"
+ " in uncolored Type 3 char or tiling pattern");
}
}
obj2.free();
@@ -1129,9 +1141,14 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
if (obj2.isName("None")) {
out->clearSoftMask(state);
} else if (obj2.isDict()) {
- if (obj2.dictLookup("S", &obj3)->isName("Alpha")) {
+ obj2.dictLookup("S", &obj3);
+ if (obj3.isName("Alpha")) {
alpha = gTrue;
- } else { // "Luminosity"
+ } else if (obj3.isName("Luminosity")) {
+ alpha = gFalse;
+ } else {
+ error(errSyntaxError, getPos(),
+ "Missing S (subtype) entry in soft mask");
alpha = gFalse;
}
obj3.free();
@@ -1141,9 +1158,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
obj3.isName("Identity")) {
funcs[0] = NULL;
} else {
- funcs[0] = Function::parse(&obj3);
- if (funcs[0]->getInputSize() != 1 ||
- funcs[0]->getOutputSize() != 1) {
+ if (!(funcs[0] = Function::parse(&obj3, 1, 1))) {
error(errSyntaxError, getPos(),
"Invalid transfer function in soft mask in ExtGState");
delete funcs[0];
@@ -1290,9 +1305,9 @@ void Gfx::doSoftMask(Object *str, Object *strRef, GBool alpha,
void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
GfxRenderingIntent ri;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring rendering intent setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring rendering intent setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
ri = parseRenderingIntent(args[0].getName());
@@ -1320,9 +1335,9 @@ GfxRenderingIntent Gfx::parseRenderingIntent(const char *name) {
void Gfx::opSetFillGray(Object args[], int numArgs) {
GfxColor color;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setFillPattern(NULL);
@@ -1336,9 +1351,9 @@ void Gfx::opSetFillGray(Object args[], int numArgs) {
void Gfx::opSetStrokeGray(Object args[], int numArgs) {
GfxColor color;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setStrokePattern(NULL);
@@ -1353,9 +1368,9 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
GfxColor color;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setFillPattern(NULL);
@@ -1372,9 +1387,9 @@ void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
GfxColor color;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setStrokePattern(NULL);
@@ -1391,9 +1406,9 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
GfxColor color;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setFillPattern(NULL);
@@ -1410,9 +1425,9 @@ void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
GfxColor color;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setStrokePattern(NULL);
@@ -1430,9 +1445,9 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
GfxColorSpace *colorSpace;
GfxColor color;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color space setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color space setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setFillPattern(NULL);
@@ -1461,9 +1476,9 @@ void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
GfxColorSpace *colorSpace;
GfxColor color;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color space setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color space setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
state->setStrokePattern(NULL);
@@ -1491,9 +1506,9 @@ void Gfx::opSetFillColor(Object args[], int numArgs) {
GfxColor color;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
if (numArgs != state->getFillColorSpace()->getNComps()) {
@@ -1531,9 +1546,9 @@ void Gfx::opSetFillColorN(Object args[], int numArgs) {
GfxPattern *pattern;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
if (state->getFillColorSpace()->getMode() == csPattern) {
@@ -1585,9 +1600,9 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
GfxPattern *pattern;
int i;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring color setting in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring color setting"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
if (state->getStrokeColorSpace()->getMode() == csPattern) {
@@ -2068,6 +2083,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
state->setStrokeColor(state->getFillColor());
out->updateFillColor(state);
out->updateStrokeColor(state);
+ state->setIgnoreColorOps(gTrue);
} else {
state->setFillColorSpace(GfxColorSpace::create(csDeviceGray));
out->updateFillColorSpace(state);
@@ -2223,6 +2239,7 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
if (stroke) {
state->clipToStrokePath();
out->clipToStrokePath(state);
+ state->setFillOverprint(state->getStrokeOverprint());
} else if (!text) {
state->clip();
if (eoFill) {
@@ -2241,6 +2258,7 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
det = ctm[0] * ctm[3] - ctm[1] * ctm[2];
if (fabs(det) <= 1e-10) {
error(errSyntaxError, getPos(), "Singular matrix in shading pattern fill");
+ restoreStateStack(savedState);
return;
}
det = 1 / det;
@@ -2338,9 +2356,9 @@ void Gfx::opShFill(Object args[], int numArgs) {
GfxState *savedState;
double xMin, yMin, xMax, yMax;
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring shaded fill in cached Type 3 character");
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring shaded fill"
+ " in uncolored Type 3 char or tiling pattern");
return;
}
@@ -4123,7 +4141,7 @@ void Gfx::opXObject(Object args[], int numArgs) {
ocState = ocSaved;
}
-void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
+GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
Dict *dict, *maskDict;
int width, height;
int bits, maskBits;
@@ -4145,7 +4163,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
// check for optional content
if (!ocState && !inlineImg) {
- return;
+ return gTrue;
}
// get info from the stream
@@ -4309,6 +4327,11 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
if (!colorSpace) {
goto err1;
}
+ if (colorSpace->getMode() == csPattern) {
+ error(errSyntaxError, getPos(), "Image with a Pattern color space");
+ delete colorSpace;
+ goto err1;
+ }
dict->lookup("Decode", &obj1);
if (obj1.isNull()) {
obj1.free();
@@ -4365,6 +4388,12 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
maskHeight = obj1.getInt();
obj1.free();
+ if (maskWidth <= 0 || maskHeight <= 0) {
+ delete colorMap;
+ maskObj.free();
+ smaskObj.free();
+ goto err1;
+ }
maskDict->lookup("BitsPerComponent", &obj1);
if (obj1.isNull()) {
obj1.free();
@@ -4378,6 +4407,12 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
maskBits = obj1.getInt();
obj1.free();
+ if (maskBits < 1 || maskBits > 16) {
+ delete colorMap;
+ maskObj.free();
+ smaskObj.free();
+ goto err1;
+ }
maskDict->lookup("ColorSpace", &obj1);
if (obj1.isNull()) {
obj1.free();
@@ -4501,6 +4536,12 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
maskHeight = obj1.getInt();
obj1.free();
+ if (maskWidth <= 0 || maskHeight <= 0) {
+ delete colorMap;
+ maskObj.free();
+ smaskObj.free();
+ goto err2;
+ }
maskDict->lookup("ImageMask", &obj1);
if (obj1.isNull()) {
obj1.free();
@@ -4534,10 +4575,10 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
// if drawing is disabled, skip over inline image data
- if (state->getInCachedT3Char() || !ocState) {
- if (state->getInCachedT3Char()) {
- error(errSyntaxWarning, getPos(),
- "Ignoring image in cached Type 3 character");
+ if (state->getIgnoreColorOps() || !ocState) {
+ if (state->getIgnoreColorOps()) {
+ error(errSyntaxWarning, getPos(), "Ignoring image"
+ " in uncolored Type 3 char or tiling pattern");
}
if (inlineImg) {
str->reset();
@@ -4582,7 +4623,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
opCounter += i;
- return;
+ return gTrue;
err2:
obj1.free();
@@ -4594,6 +4635,8 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
state->setRenderingIntent(riSaved);
out->updateRenderingIntent(state);
}
+
+ return gFalse;
}
void Gfx::doForm(Object *strRef, Object *str) {
@@ -4826,11 +4869,12 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
// display the image
if (str) {
- doImage(NULL, str, gTrue);
+ if (!doImage(NULL, str, gTrue)) {
+ delete str;
// if we have the stream length, skip to end-of-stream and then
// skip 'EI' in the original stream
- if (haveLength) {
+ } else if (haveLength) {
while ((c1 = str->getChar()) != EOF) ;
delete str;
str = parser->getStream();
@@ -4935,7 +4979,7 @@ void Gfx::opSetCharWidth(Object args[], int numArgs) {
}
void Gfx::opSetCacheDevice(Object args[], int numArgs) {
- state->setInCachedT3Char(gTrue);
+ state->setIgnoreColorOps(gTrue);
out->type3D1(state, args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h
index 9d175825f97..2159eaaf2e9 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h
@@ -330,7 +330,7 @@ private:
// XObject operators
void opXObject(Object args[], int numArgs);
- void doImage(Object *ref, Stream *str, GBool inlineImg);
+ GBool doImage(Object *ref, Stream *str, GBool inlineImg);
void doForm(Object *strRef, Object *str);
// in-line image operators
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc
index 640cf81db02..b10c81779ff 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc
@@ -164,7 +164,8 @@ GfxFontLoc::~GfxFontLoc() {
// GfxFont
//------------------------------------------------------------------------
-GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
+GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA,
+ Ref idA, Dict *fontDict) {
GString *nameA;
Ref embFontIDA;
GfxFontType typeA;
@@ -197,7 +198,7 @@ GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
return font;
}
-GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA,
+GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Ref embFontIDA) {
ok = gFalse;
tag = new GString(tagA);
@@ -541,6 +542,7 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
GfxFontLoc *fontLoc;
SysFontType sysFontType;
+ FoFiIdentifierType fft;
GString *path, *base14Name, *substName;
PSFontParam16 *psFont16;
Object refObj, embFontObj;
@@ -635,32 +637,43 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
//----- system font
if (name && (path = globalParams->findSystemFontFile(name, &sysFontType,
&fontNum))) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->path = path;
+ fontLoc->fontNum = fontNum;
if (isCIDFont()) {
if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) {
- fontLoc = new GfxFontLoc();
- fontLoc->locType = gfxFontLocExternal;
fontLoc->fontType = fontCIDType2;
- fontLoc->path = path;
- fontLoc->fontNum = fontNum;
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 = new GfxFontLoc();
- fontLoc->locType = gfxFontLocExternal;
fontLoc->fontType = fontTrueType;
- fontLoc->path = path;
- fontLoc->fontNum = fontNum;
return fontLoc;
} else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) {
- fontLoc = new GfxFontLoc();
- fontLoc->locType = gfxFontLocExternal;
fontLoc->fontType = fontType1;
- fontLoc->path = path;
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;
+ }
}
}
- delete path;
+ delete fontLoc;
}
if (!isCIDFont()) {
@@ -863,7 +876,7 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
// Gfx8BitFont
//------------------------------------------------------------------------
-Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
+Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
GfxFont(tagA, idA, nameA, typeA, embFontIDA)
{
@@ -1490,6 +1503,33 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
return map;
}
+int *Gfx8BitFont::getCodeToGIDMap(FoFiType1C *ff) {
+ int *map;
+ GHash *nameToGID;
+ int i, gid;
+
+ map = (int *)gmallocn(256, sizeof(int));
+ for (i = 0; i < 256; ++i) {
+ map[i] = 0;
+ }
+
+ nameToGID = ff->getNameToGIDMap();
+ for (i = 0; i < 256; ++i) {
+ if (!enc[i]) {
+ continue;
+ }
+ gid = nameToGID->lookupInt(enc[i]);
+ if (gid < 0 || gid >= 65536) {
+ continue;
+ }
+ map[i] = gid;
+ }
+
+ delete nameToGID;
+
+ return map;
+}
+
Dict *Gfx8BitFont::getCharProcs() {
return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
}
@@ -1575,7 +1615,7 @@ GBool Gfx8BitFont::problematicForUnicode() {
// GfxCIDFont
//------------------------------------------------------------------------
-GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
+GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
GfxFont(tagA, idA, nameA, typeA, embFontIDA)
{
@@ -2001,6 +2041,13 @@ GString *GfxCIDFont::getCollection() {
return cMap ? cMap->getCollection() : (GString *)NULL;
}
+double GfxCIDFont::getWidth(CID cid) {
+ double w;
+
+ getHorizontalMetrics(cid, &w);
+ return w;
+}
+
GBool GfxCIDFont::problematicForUnicode() {
GString *nameLC;
GBool symbolic;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h
index b2d8637a46d..3b63fa69fe0 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h
@@ -26,6 +26,7 @@ class Dict;
class CMap;
class CharCodeToUnicode;
class FoFiTrueType;
+class FoFiType1C;
struct GfxFontCIDWidths;
struct Base14FontMapEntry;
class FNVHash;
@@ -131,9 +132,10 @@ class GfxFont {
public:
// Build a GfxFont object.
- static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict);
+ static GfxFont *makeFont(XRef *xref, const char *tagA,
+ Ref idA, Dict *fontDict);
- GfxFont(char *tagA, Ref idA, GString *nameA,
+ GfxFont(const char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Ref embFontIDA);
virtual ~GfxFont();
@@ -243,7 +245,7 @@ protected:
class Gfx8BitFont: public GfxFont {
public:
- Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
+ Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Ref embFontIDA, Dict *fontDict);
virtual ~Gfx8BitFont();
@@ -274,6 +276,10 @@ public:
// (This is only useful for TrueType fonts.)
int *getCodeToGIDMap(FoFiTrueType *ff);
+ // Return a char code-to-GID mapping for the provided font file.
+ // (This is only useful for Type1C fonts.)
+ int *getCodeToGIDMap(FoFiType1C *ff);
+
// Return the Type 3 CharProc dictionary, or NULL if none.
Dict *getCharProcs();
@@ -311,7 +317,7 @@ private:
class GfxCIDFont: public GfxFont {
public:
- GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
+ GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Ref embFontIDA, Dict *fontDict);
virtual ~GfxCIDFont();
@@ -331,6 +337,9 @@ public:
// Get the collection name (<registry>-<ordering>).
GString *getCollection();
+ // Return the horizontal width for <cid>.
+ double getWidth(CID cid);
+
// Return the CID-to-GID mapping table. These should only be called
// if type is fontCIDType2.
int *getCIDToGID() { return cidToGID; }
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc
index 9a43608c2fe..60b5f577054 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc
@@ -1281,7 +1281,7 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr,
}
obj1.free();
arr->get(3, &obj1);
- if (!(funcA = Function::parse(&obj1))) {
+ if (!(funcA = Function::parse(&obj1, 1, altA->getNComps()))) {
goto err4;
}
obj1.free();
@@ -1476,7 +1476,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr,
}
obj1.free();
arr->get(3, &obj1);
- if (!(funcA = Function::parse(&obj1))) {
+ if (!(funcA = Function::parse(&obj1, nCompsA, altA->getNComps()))) {
goto err4;
}
obj1.free();
@@ -2117,14 +2117,14 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict
}
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
+ if (!(funcsA[i] = Function::parse(&obj2, 2, 1))) {
goto err2;
}
obj2.free();
}
} else {
nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
+ if (!(funcsA[0] = Function::parse(&obj1, 2, -1))) {
goto err1;
}
}
@@ -2137,6 +2137,16 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict
delete shading;
return NULL;
}
+
+ for (i = 0; i < shading->nFuncs; ++i) {
+ if (shading->funcs[i]->getOutputSize()
+ != shading->getColorSpace()->getNComps()) {
+ error(errSyntaxError, -1, "Invalid function in shading dictionary");
+ delete shading;
+ return NULL;
+ }
+ }
+
return shading;
err2:
@@ -2274,7 +2284,7 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict
}
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
+ if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
obj1.free();
obj2.free();
goto err1;
@@ -2283,7 +2293,7 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict
}
} else {
nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
+ if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
obj1.free();
goto err1;
}
@@ -2307,6 +2317,16 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict
delete shading;
return NULL;
}
+
+ for (i = 0; i < shading->nFuncs; ++i) {
+ if (shading->funcs[i]->getOutputSize()
+ != shading->getColorSpace()->getNComps()) {
+ error(errSyntaxError, -1, "Invalid function in shading dictionary");
+ delete shading;
+ return NULL;
+ }
+ }
+
return shading;
err1:
@@ -2446,7 +2466,7 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict
}
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
+ if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
obj1.free();
obj2.free();
goto err1;
@@ -2455,7 +2475,7 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict
}
} else {
nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
+ if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
obj1.free();
goto err1;
}
@@ -2479,6 +2499,16 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict
delete shading;
return NULL;
}
+
+ for (i = 0; i < shading->nFuncs; ++i) {
+ if (shading->funcs[i]->getOutputSize()
+ != shading->getColorSpace()->getNComps()) {
+ error(errSyntaxError, -1, "Invalid function in shading dictionary");
+ delete shading;
+ return NULL;
+ }
+ }
+
return shading;
err1:
@@ -2719,7 +2749,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(
}
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
+ if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
obj1.free();
obj2.free();
goto err1;
@@ -2728,7 +2758,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(
}
} else {
nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
+ if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
obj1.free();
goto err1;
}
@@ -2832,6 +2862,16 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(
delete shading;
return NULL;
}
+
+ for (i = 0; i < shading->nFuncs; ++i) {
+ if (shading->funcs[i]->getOutputSize()
+ != shading->getColorSpace()->getNComps()) {
+ error(errSyntaxError, -1, "Invalid function in shading dictionary");
+ delete shading;
+ return NULL;
+ }
+ }
+
return shading;
err2:
@@ -3017,7 +3057,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
}
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
- if (!(funcsA[i] = Function::parse(&obj2))) {
+ if (!(funcsA[i] = Function::parse(&obj2, 1, 1))) {
obj1.free();
obj2.free();
goto err1;
@@ -3026,7 +3066,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
}
} else {
nFuncsA = 1;
- if (!(funcsA[0] = Function::parse(&obj1))) {
+ if (!(funcsA[0] = Function::parse(&obj1, 1, -1))) {
obj1.free();
goto err1;
}
@@ -3044,6 +3084,12 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
if (!bitBuf->getBits(flagBits, &flag)) {
break;
}
+ flag &= 3;
+ if (flag != 0 && nPatchesA == 0) {
+ error(errSyntaxError, -1, "Invalid patch in patch mesh shading");
+ delete bitBuf;
+ goto err1;
+ }
if (typeA == 6) {
switch (flag) {
case 0: nPts = 12; nColors = 4; break;
@@ -3445,6 +3491,16 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
delete shading;
return NULL;
}
+
+ for (i = 0; i < shading->nFuncs; ++i) {
+ if (shading->funcs[i]->getOutputSize()
+ != shading->getColorSpace()->getNComps()) {
+ error(errSyntaxError, -1, "Invalid function in shading dictionary");
+ delete shading;
+ return NULL;
+ }
+ }
+
return shading;
err2:
@@ -4122,7 +4178,7 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
clipXMax = pageWidth;
clipYMax = pageHeight;
- inCachedT3Char = gFalse;
+ ignoreColorOps = gFalse;
saved = NULL;
}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h
index 8e5d3b0b7a5..50507040fed 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h
@@ -1183,7 +1183,7 @@ public:
void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax);
double getLineX() { return lineX; }
double getLineY() { return lineY; }
- GBool getInCachedT3Char() { return inCachedT3Char; }
+ GBool getIgnoreColorOps() { return ignoreColorOps; }
// Is there a current point/path?
GBool isCurPt() { return path->isCurPt(); }
@@ -1280,8 +1280,9 @@ public:
void textShift(double tx, double ty);
void shift(double dx, double dy);
- // Cached Type 3 char status.
- void setInCachedT3Char(GBool in) { inCachedT3Char = in; }
+ // Ignore color operators (in cached/uncolored Type 3 chars, and
+ // uncolored tiling patterns). Cached Type 3 char status.
+ void setIgnoreColorOps(GBool ignore) { ignoreColorOps = ignore; }
// Push/pop GfxState on/off stack.
GfxState *save();
@@ -1344,7 +1345,9 @@ private:
double clipXMin, clipYMin, // bounding box for clip region
clipXMax, clipYMax;
- GBool inCachedT3Char; // in a cached (uncolored) Type 3 char
+ GBool ignoreColorOps; // ignore color ops (in cached/uncolored
+ // Type 3 chars, and uncolored tiling
+ // patterns)
GfxState *saved; // next GfxState on stack
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc
index 2205a621322..56bfba8e3cc 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc
@@ -17,13 +17,18 @@
#include <string.h>
#include <stdio.h>
+#include <stdarg.h>
#include <ctype.h>
+#include <time.h>
#ifdef _WIN32
# include <shlobj.h>
#endif
#if HAVE_PAPER_H
#include <paper.h>
#endif
+#if HAVE_FONTCONFIG
+# include <fontconfig/fontconfig.h>
+#endif
#include "gmem.h"
#include "gmempp.h"
#include "GString.h"
@@ -91,14 +96,14 @@ static struct {
{"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-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-BoldItalic", NULL, 0},
- {"Times-Italic", "n021023l.pfb", "timesi.ttf", "Times", "Times-Italic", NULL, 0},
- {"Times-Roman", "n021003l.pfb", "times.ttf", "Times", "Times-Roman", 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},
{NULL}
};
@@ -226,6 +231,10 @@ public:
void scanWindowsFonts(char *winFontDir);
#endif
+#if HAVE_FONTCONFIG
+ void scanFontconfigFonts();
+#endif
+
private:
#ifdef _WIN32
@@ -458,6 +467,8 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
if (!strcasecmp(path + strlen(path) - 4, ".ttc")) {
type = sysFontTTC;
+ } else if (!strcasecmp(path + strlen(path) - 4, ".otf")) {
+ type = sysFontOTF;
} else {
type = sysFontTTF;
}
@@ -465,6 +476,109 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
}
#endif
+#if HAVE_FONTCONFIG
+void SysFontList::scanFontconfigFonts() {
+ FcPattern *pattern;
+ FcObjectSet *objSet;
+ FcFontSet *fontSet;
+ char *family, *file, *styleLang, *style;
+ GString *family2;
+ SysFontType type;
+ GBool bold, italic;
+ char c;
+ int fontNum, i, j, n;
+
+ FcInit();
+
+ pattern = FcPatternBuild(NULL,
+ FC_OUTLINE, FcTypeBool, FcTrue,
+ FC_SCALABLE, FcTypeBool, FcTrue,
+ NULL);
+ objSet = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_STYLELANG,
+ FC_FILE, FC_INDEX, NULL);
+ fontSet = FcFontList(NULL, pattern, objSet);
+ FcPatternDestroy(pattern);
+ FcObjectSetDestroy(objSet);
+
+ if (fontSet) {
+ for (i = 0; i < fontSet->nfont; ++i) {
+
+ //--- font file, font type
+ if (FcPatternGetString(fontSet->fonts[i], FC_FILE, 0,
+ (FcChar8 **)&file)
+ != FcResultMatch) {
+ continue;
+ }
+ n = (int)strlen(file);
+ if (n > 4 && !strcasecmp(file + n - 4, ".pfa")) {
+ type = sysFontPFA;
+ } else if (n > 4 && !strcasecmp(file + n - 4, ".pfb")) {
+ type = sysFontPFB;
+ } else if (n > 4 && !strcasecmp(file + n - 4, ".ttf")) {
+ type = sysFontTTF;
+ } else if (n > 4 && !strcasecmp(file + n - 4, ".otf")) {
+ type = sysFontOTF;
+ } else {
+ continue;
+ }
+
+ //--- font number
+ if (FcPatternGetInteger(fontSet->fonts[i], FC_INDEX, 0, &fontNum)
+ != FcResultMatch) {
+ fontNum = 0;
+ }
+
+ //--- font family
+ if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0,
+ (FcChar8 **)&family)
+ != FcResultMatch) {
+ continue;
+ }
+
+ //----- normalize the font name
+ family2 = new GString(family);
+ j = 0;
+ while (j < family2->getLength()) {
+ c = family2->getChar(j);
+ if (c == ' ' || c == ',' || c == '-') {
+ family2->del(j);
+ } else {
+ ++j;
+ }
+ }
+
+ //--- font style
+ style = NULL;
+ for (j = 0;
+ FcPatternGetString(fontSet->fonts[i], FC_STYLELANG, j,
+ (FcChar8 **)&styleLang)
+ == FcResultMatch;
+ ++j) {
+ if (!strcmp(styleLang, "en")) {
+ if (FcPatternGetString(fontSet->fonts[i], FC_STYLE, j,
+ (FcChar8 **)&style)
+ != FcResultMatch) {
+ style = NULL;
+ }
+ break;
+ }
+ ++j;
+ }
+ bold = style && strstr(style, "Bold") != NULL;
+ italic = style && (strstr(style, "Italic") != NULL ||
+ strstr(style, "Oblique") != NULL);
+
+ fonts->append(new SysFontInfo(family2, bold, italic,
+ new GString(file), type, fontNum));
+ }
+
+ FcFontSetDestroy(fontSet);
+ }
+
+ FcFini();
+}
+#endif // HAVE_FONTCONFIG
+
//------------------------------------------------------------------------
// KeyBinding
//------------------------------------------------------------------------
@@ -619,7 +733,10 @@ GlobalParams::GlobalParams(const char *cfgFileName) {
textKeepTinyChars = gTrue;
initialZoom = new GString("125");
defaultFitZoom = 0;
+ initialDisplayMode = new GString("continuous");
+ initialToolbarState = gTrue;
initialSidebarState = gTrue;
+ initialSelectMode = new GString("linear");
maxTileWidth = 1500;
maxTileHeight = 1500;
tileCacheSize = 10;
@@ -644,6 +761,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) {
paperColor = new GString("#ffffff");
matteColor = new GString("#808080");
fullScreenMatteColor = new GString("#000000");
+ reverseVideoInvertImages = gFalse;
launchCommand = NULL;
movieCommand = NULL;
defaultPrinter = NULL;
@@ -657,6 +775,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) {
tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state");
printCommands = gFalse;
errQuiet = gFalse;
+ debugLogFile = NULL;
cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
unicodeToUnicodeCache =
@@ -787,6 +906,9 @@ void GlobalParams::createDefaultKeyBindings() {
xpdfKeyContextAny, "newWindow"));
keyBindings->append(new KeyBinding('w', xpdfKeyModCtrl,
xpdfKeyContextAny, "closeTabOrQuit"));
+ keyBindings->append(new KeyBinding('l', xpdfKeyModCtrl,
+ xpdfKeyContextAny,
+ "toggleFullScreenMode"));
keyBindings->append(new KeyBinding('q', xpdfKeyModCtrl,
xpdfKeyContextAny, "quit"));
keyBindings->append(new KeyBinding(xpdfKeyCodeTab, xpdfKeyModCtrl,
@@ -1022,9 +1144,18 @@ 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("initialDisplayMode")) {
+ parseString("initialDisplayMode", &initialDisplayMode,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("initialToolbarState")) {
+ parseYesNo("initialToolbarState", &initialToolbarState,
+ tokens, fileName, line);
} else if (!cmd->cmp("initialSidebarState")) {
parseYesNo("initialSidebarState", &initialSidebarState,
tokens, fileName, line);
+ } else if (!cmd->cmp("initialSelectMode")) {
+ parseString("initialSelectMode", &initialSelectMode,
+ tokens, fileName, line);
} else if (!cmd->cmp("maxTileWidth")) {
parseInteger("maxTileWidth", &maxTileWidth, tokens, fileName, line);
} else if (!cmd->cmp("maxTileHeight")) {
@@ -1086,6 +1217,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
} else if (!cmd->cmp("fullScreenMatteColor")) {
parseString("fullScreenMatteColor", &fullScreenMatteColor,
tokens, fileName, line);
+ } else if (!cmd->cmp("reverseVideoInvertImages")) {
+ parseYesNo("reverseVideoInvertImages", &reverseVideoInvertImages,
+ tokens, fileName, line);
} else if (!cmd->cmp("launchCommand")) {
parseString("launchCommand", &launchCommand, tokens, fileName, line);
} else if (!cmd->cmp("movieCommand")) {
@@ -1118,6 +1252,8 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
parseYesNo("printCommands", &printCommands, tokens, fileName, line);
} else if (!cmd->cmp("errQuiet")) {
parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
+ } else if (!cmd->cmp("debugLogFile")) {
+ parseString("debugLogFile", &debugLogFile, tokens, fileName, line);
} else {
error(errConfig, -1, "Unknown config file command '{0:t}' ({1:t}:{2:d})",
cmd, fileName, line);
@@ -1862,6 +1998,8 @@ GlobalParams::~GlobalParams() {
deleteGList(psResidentFontsCC, PSFontParam16);
delete textEncoding;
delete initialZoom;
+ delete initialDisplayMode;
+ delete initialSelectMode;
if (paperColor) {
delete paperColor;
}
@@ -1943,6 +2081,7 @@ static void getWinFontDir(char *winFontDir) {
}
}
}
+ FreeLibrary(shell32Lib);
}
// if something went wrong, or we're on a Terminal Server, try using
// %SYSTEMROOT%\Fonts
@@ -1958,6 +2097,40 @@ static void getWinFontDir(char *winFontDir) {
}
#endif
+#ifdef __APPLE__
+// Apple dfonts and ttc fonts seem to randomly and interchangeably use
+// space and hyphen, and sometimes drop the separator entirely.
+static GBool macFontNameMatches(GString *name1, const char *name2) {
+ const char *p1, *p2;
+ char c1, c2;
+
+ p1 = name1->getCString();
+ p2 = name2;
+ while (*p1 && *p2) {
+ c1 = *p1;
+ c2 = *p2;
+ if (c2 == ' ') {
+ // * space or hyphen matches a space in the pattern
+ // * separators can also be dropped, in which case we move to
+ // the next char in the pattern
+ if (c1 == ' ' || c1 == '-') {
+ ++p1;
+ }
+ } else {
+ if (c1 != c2) {
+ return gFalse;
+ }
+ ++p1;
+ }
+ ++p2;
+ }
+ if (*p1 || *p2) {
+ return gFalse;
+ }
+ return gTrue;
+}
+#endif
+
void GlobalParams::setupBaseFonts(const char *dir) {
GString *fontName;
GString *fileName;
@@ -2036,8 +2209,8 @@ void GlobalParams::setupBaseFonts(const char *dir) {
}
if (dfontFontNames) {
for (k = 0; k < dfontFontNames->getLength(); ++k) {
- if (!((GString *)dfontFontNames->get(k))
- ->cmp(displayFontTab[i].macFontName)) {
+ if (macFontNameMatches((GString *)dfontFontNames->get(k),
+ displayFontTab[i].macFontName)) {
fontNum = k;
found = gTrue;
break;
@@ -2114,6 +2287,9 @@ void GlobalParams::setupBaseFonts(const char *dir) {
sysFonts->scanWindowsFonts(winFontDir);
}
#endif
+#if HAVE_FONTCONFIG
+ sysFonts->scanFontconfigFonts();
+#endif
}
//------------------------------------------------------------------------
@@ -2653,6 +2829,24 @@ int GlobalParams::getDefaultFitZoom() {
return z;
}
+GString *GlobalParams::getInitialDisplayMode() {
+ GString *s;
+
+ lockGlobalParams;
+ s = initialDisplayMode->copy();
+ unlockGlobalParams;
+ return s;
+}
+
+GBool GlobalParams::getInitialToolbarState() {
+ GBool state;
+
+ lockGlobalParams;
+ state = initialToolbarState;
+ unlockGlobalParams;
+ return state;
+}
+
GBool GlobalParams::getInitialSidebarState() {
GBool state;
@@ -2662,6 +2856,15 @@ GBool GlobalParams::getInitialSidebarState() {
return state;
}
+GString *GlobalParams::getInitialSelectMode() {
+ GString *s;
+
+ lockGlobalParams;
+ s = initialSelectMode->copy();
+ unlockGlobalParams;
+ return s;
+}
+
int GlobalParams::getMaxTileWidth() {
int w;
@@ -2872,6 +3075,15 @@ GString *GlobalParams::getFullScreenMatteColor() {
return s;
}
+GBool GlobalParams::getReverseVideoInvertImages() {
+ GBool invert;
+
+ lockGlobalParams;
+ invert = reverseVideoInvertImages;
+ unlockGlobalParams;
+ return invert;
+}
+
GString *GlobalParams::getDefaultPrinter() {
GString *s;
@@ -2998,6 +3210,51 @@ GBool GlobalParams::getErrQuiet() {
return errQuiet;
}
+GString *GlobalParams::getDebugLogFile() {
+ return debugLogFile;
+}
+
+void GlobalParams::debugLogPrintf(char *fmt, ...) {
+ GString *path;
+ FILE *f;
+ GBool needClose;
+ time_t t;
+ struct tm tm;
+ va_list args;
+
+ if (!(path = getDebugLogFile())) {
+ return;
+ }
+ needClose = gFalse;
+ if (!path->cmp("-")) {
+ f = stdout;
+ } else if (!path->cmp("+")) {
+ f = stderr;
+ } else {
+ f = fopen(path->getCString(), "a");
+ needClose = gTrue;
+ }
+ if (!f) {
+ return;
+ }
+ t = time(NULL);
+#ifdef _WIN32
+ localtime_s(&tm, &t);
+#else
+ localtime_r(&t, &tm);
+#endif
+ fprintf(f, "[%04d-%02d-%02d %02d:%02d:%02d] ",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ va_start(args, fmt);
+ vfprintf(f, fmt, args);
+ va_end(args);
+ fflush(f);
+ if (needClose) {
+ fclose(f);
+ }
+}
+
CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
GString *fileName;
CharCodeToUnicode *ctu;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h
index 066b420dfa8..ed1fed3152d 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h
@@ -55,7 +55,8 @@ enum SysFontType {
sysFontPFA,
sysFontPFB,
sysFontTTF,
- sysFontTTC
+ sysFontTTC,
+ sysFontOTF
};
//------------------------------------------------------------------------
@@ -283,7 +284,10 @@ public:
GBool getTextKeepTinyChars();
GString *getInitialZoom();
int getDefaultFitZoom();
+ GString *getInitialDisplayMode();
+ GBool getInitialToolbarState();
GBool getInitialSidebarState();
+ GString *getInitialSelectMode();
int getMaxTileWidth();
int getMaxTileHeight();
int getTileCacheSize();
@@ -308,6 +312,7 @@ public:
GString *getPaperColor();
GString *getMatteColor();
GString *getFullScreenMatteColor();
+ GBool getReverseVideoInvertImages();
GString *getLaunchCommand() { return launchCommand; }
GString *getMovieCommand() { return movieCommand; }
GString *getDefaultPrinter();
@@ -322,6 +327,8 @@ public:
GString *getTabStateFile();
GBool getPrintCommands();
GBool getErrQuiet();
+ GString *getDebugLogFile();
+ void debugLogPrintf(char *fmt, ...);
CharCodeToUnicode *getCIDToUnicode(GString *collection);
CharCodeToUnicode *getUnicodeToUnicode(GString *fontName);
@@ -509,8 +516,13 @@ private:
GString *initialZoom; // initial zoom level
int defaultFitZoom; // default zoom factor if initialZoom is
// 'page' or 'width'.
+ GString *initialDisplayMode; // initial display mode (single,
+ // continuous, etc.)
+ GBool initialToolbarState; // initial toolbar state - open (true)
+ // or closed (false)
GBool initialSidebarState; // initial sidebar state - open (true)
// or closed (false)
+ GString *initialSelectMode; // initial selection mode (block or linear)
int maxTileWidth; // maximum rasterization tile width
int maxTileHeight; // maximum rasterization tile height
int tileCacheSize; // number of rasterization tiles in cache
@@ -536,6 +548,7 @@ private:
GString *paperColor; // paper (page background) color
GString *matteColor; // matte (background outside of page) color
GString *fullScreenMatteColor; // matte color in full-screen mode
+ GBool reverseVideoInvertImages; // invert images in reverse video mode
GString *launchCommand; // command executed for 'launch' links
GString *movieCommand; // command executed for movie annotations
GString *defaultPrinter; // default printer (for interactive printing
@@ -551,6 +564,7 @@ private:
GString *tabStateFile; // path for the tab state save file
GBool printCommands; // print the drawing commands
GBool errQuiet; // suppress error messages?
+ GString *debugLogFile; // path for debug log file
CharCodeToUnicodeCache *cidToUnicodeCache;
CharCodeToUnicodeCache *unicodeToUnicodeCache;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc
index d6cbc24680d..036f1116c01 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc
@@ -34,9 +34,11 @@
#include "GList.h"
#include "SplashBitmap.h"
#include "PDFDoc.h"
+#include "GfxFont.h"
#include "TextOutputDev.h"
#include "SplashOutputDev.h"
#include "ErrorCodes.h"
+#include "WebFont.h"
#include "HTMLGen.h"
#ifdef _WIN32
@@ -62,11 +64,14 @@ static FontStyleTagInfo fontStyleTags[] = {
{"CondensedBold", 13, gTrue, gFalse},
{"CondensedLight", 14, gFalse, gFalse},
{"SemiBold", 8, gTrue, gFalse},
+ {"BoldItalicMT", 12, gTrue, gTrue},
{"BoldItalic", 10, gTrue, gTrue},
{"Bold_Italic", 11, gTrue, gTrue},
{"BoldOblique", 11, gTrue, gTrue},
{"Bold_Oblique", 12, gTrue, gTrue},
+ {"BoldMT", 6, gTrue, gFalse},
{"Bold", 4, gTrue, gFalse},
+ {"ItalicMT", 8, gFalse, gTrue},
{"Italic", 6, gFalse, gTrue},
{"Oblique", 7, gFalse, gTrue},
{"Light", 5, gFalse, gFalse},
@@ -171,6 +176,26 @@ static const char *vertAlignNames[] = {
//------------------------------------------------------------------------
+class HTMLGenFontDefn {
+public:
+
+ HTMLGenFontDefn(Ref fontIDA, GString *fontFaceA, GString *fontSpecA,
+ double scaleA)
+ : fontID(fontIDA), fontFace(fontFaceA), fontSpec(fontSpecA)
+ , scale(scaleA), used(gFalse) {}
+ ~HTMLGenFontDefn() { delete fontFace; delete fontSpec; }
+ GBool match(Ref fontIDA)
+ { return fontIDA.num == fontID.num && fontIDA.gen == fontID.gen; }
+
+ Ref fontID;
+ GString *fontFace; // NULL for substituted fonts
+ GString *fontSpec;
+ double scale;
+ GBool used; // set when used (per page)
+};
+
+//------------------------------------------------------------------------
+
//------------------------------------------------------------------------
@@ -184,6 +209,7 @@ HTMLGen::HTMLGen(double backgroundResolutionA) {
zoom = 1.0;
drawInvisibleText = gTrue;
allTextInvisible = gFalse;
+ extractFontFiles = gFalse;
// set up the TextOutputDev
textOutControl.mode = textOutReadingOrder;
@@ -196,16 +222,27 @@ HTMLGen::HTMLGen(double backgroundResolutionA) {
// set up the SplashOutputDev
paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor);
+
+ fontDefns = NULL;
}
HTMLGen::~HTMLGen() {
delete textOut;
delete splashOut;
+ if (fontDefns) {
+ deleteGList(fontDefns, HTMLGenFontDefn);
+ }
}
void HTMLGen::startDoc(PDFDoc *docA) {
doc = docA;
splashOut->startDoc(doc->getXRef());
+
+ if (fontDefns) {
+ deleteGList(fontDefns, HTMLGenFontDefn);
+ }
+ fontDefns = new GList();
+ nextFontFaceIdx = 0;
}
static inline int pr(int (*writeFunc)(void *stream, const char *data, int size),
@@ -240,7 +277,7 @@ static void pngWriteFunc(png_structp png, png_bytep data, png_size_t size) {
}
int HTMLGen::convertPage(
- int pg, const char *pngURL,
+ int pg, const char *pngURL, const char *htmlDir,
int (*writeHTML)(void *stream, const char *data, int size),
void *htmlStream,
int (*writePNG)(void *stream, const char *data, int size),
@@ -257,6 +294,7 @@ int HTMLGen::convertPage(
TextColumn *col;
TextParagraph *par;
TextLine *line;
+ HTMLGenFontDefn *fontDefn;
GString *s;
double base;
int primaryDir, spanDir;
@@ -269,7 +307,7 @@ int HTMLGen::convertPage(
0, gFalse, gTrue, gFalse);
bitmap = splashOut->getBitmap();
if (!(png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
- NULL, NULL, NULL)) ||
+ NULL, NULL, NULL)) ||
!(pngInfo = png_create_info_struct(png))) {
return errFileIO;
}
@@ -314,11 +352,19 @@ int HTMLGen::convertPage(
pr(writeHTML, htmlStream, ".txt { white-space:nowrap; }\n");
fonts = text->getFonts();
fontScales = (double *)gmallocn(fonts->getLength(), sizeof(double));
+ for (i = 0; i < fontDefns->getLength(); ++i) {
+ fontDefn = (HTMLGenFontDefn *)fontDefns->get(i);
+ fontDefn->used = gFalse;
+ }
for (i = 0; i < fonts->getLength(); ++i) {
font = (TextFontInfo *)fonts->get(i);
- s = getFontDefn(font, &fontScales[i]);
- pf(writeHTML, htmlStream, "#f{0:d} {{ {1:t} }}\n", i, s);
- delete s;
+ fontDefn = getFontDefn(font, htmlDir);
+ if (!fontDefn->used && fontDefn->fontFace) {
+ pr(writeHTML, htmlStream, fontDefn->fontFace->getCString());
+ }
+ pf(writeHTML, htmlStream, "#f{0:d} {{ {1:t} }}\n", i, fontDefn->fontSpec);
+ fontScales[i] = fontDefn->scale;
+ fontDefn->used = gTrue;
}
pr(writeHTML, htmlStream, "</style>\n");
pr(writeHTML, htmlStream, "</head>\n");
@@ -592,7 +638,112 @@ void HTMLGen::appendUTF8(Unicode u, GString *s) {
}
}
-GString *HTMLGen::getFontDefn(TextFontInfo *font, double *scale) {
+HTMLGenFontDefn *HTMLGen::getFontDefn(TextFontInfo *font,
+ const char *htmlDir) {
+ Ref id;
+ HTMLGenFontDefn *fontDefn;
+ int i;
+
+ // check the existing font defns
+ id = font->getFontID();
+ if (id.num >= 0) {
+ for (i = 0; i < fontDefns->getLength(); ++i) {
+ fontDefn = (HTMLGenFontDefn *)fontDefns->get(i);
+ if (fontDefn->match(id)) {
+ return fontDefn;
+ }
+ }
+ }
+
+ // try to extract a font file
+ if (!extractFontFiles ||
+ !(fontDefn = getFontFile(font, htmlDir))) {
+
+ // get a substitute font
+ fontDefn = getSubstituteFont(font);
+ }
+
+ fontDefns->append(fontDefn);
+ return fontDefn;
+}
+
+HTMLGenFontDefn *HTMLGen::getFontFile(TextFontInfo *font,
+ const char *htmlDir) {
+ Ref id;
+ HTMLGenFontDefn *fontDefn;
+ Object fontObj;
+ GfxFont *gfxFont;
+ WebFont *webFont;
+ GString *fontFile, *fontPath, *fontFace, *fontSpec;
+ const char *family, *weight, *style;
+ double scale;
+
+ id = font->getFontID();
+ if (id.num < 0) {
+ return NULL;
+ }
+
+ doc->getXRef()->fetch(id.num, id.gen, &fontObj);
+ if (!fontObj.isDict()) {
+ fontObj.free();
+ return NULL;
+ }
+
+ gfxFont = GfxFont::makeFont(doc->getXRef(), "F", id, fontObj.getDict());
+ webFont = new WebFont(gfxFont, doc->getXRef());
+ fontDefn = NULL;
+
+ if (webFont->canWriteTTF()) {
+ fontFile = GString::format("{0:d}.ttf", nextFontFaceIdx);
+ fontPath = GString::format("{0:s}/{1:t}", htmlDir, fontFile);
+ if (webFont->writeTTF(fontPath->getCString())) {
+ fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"{1:t}\"); }}\n",
+ nextFontFaceIdx, fontFile);
+ getFontDetails(font, &family, &weight, &style, &scale);
+ fontSpec = GString::format("font-family:ff{0:d},{1:s}; font-weight:{2:s}; font-style:{3:s};",
+ nextFontFaceIdx, family, weight, style);
+ ++nextFontFaceIdx;
+ fontDefn = new HTMLGenFontDefn(id, fontFace, fontSpec, 1.0);
+ }
+ delete fontPath;
+ delete fontFile;
+
+ } else if (webFont->canWriteOTF()) {
+ fontFile = GString::format("{0:d}.otf", nextFontFaceIdx);
+ fontPath = GString::format("{0:s}/{1:t}", htmlDir, fontFile);
+ if (webFont->writeOTF(fontPath->getCString())) {
+ fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"{1:t}\"); }}\n",
+ nextFontFaceIdx, fontFile);
+ getFontDetails(font, &family, &weight, &style, &scale);
+ fontSpec = GString::format("font-family:ff{0:d},{1:s}; font-weight:{2:s}; font-style:{3:s};",
+ nextFontFaceIdx, family, weight, style);
+ fontDefn = new HTMLGenFontDefn(id, fontFace, fontSpec, 1.0);
+ }
+ delete fontPath;
+ delete fontFile;
+ }
+
+ delete webFont;
+ delete gfxFont;
+ fontObj.free();
+
+ return fontDefn;
+}
+
+HTMLGenFontDefn *HTMLGen::getSubstituteFont(TextFontInfo *font) {
+ const char *family, *weight, *style;
+ double scale;
+ GString *fontSpec;
+
+ getFontDetails(font, &family, &weight, &style, &scale);
+ fontSpec = GString::format("font-family:{0:s}; font-weight:{1:s}; font-style:{2:s};",
+ family, weight, style);
+ return new HTMLGenFontDefn(font->getFontID(), NULL, fontSpec, scale);
+}
+
+void HTMLGen::getFontDetails(TextFontInfo *font, const char **family,
+ const char **weight, const char **style,
+ double *scale) {
GString *fontName;
char *fontName2;
FontStyleTagInfo *fst;
@@ -666,11 +817,7 @@ GString *HTMLGen::getFontDefn(TextFontInfo *font, double *scale) {
}
}
- // generate the CSS markup
- return GString::format("font-family:{0:s}; font-weight:{1:s}; font-style:{2:s};",
- fixedWidth ? "monospace"
- : serif ? "serif"
- : "sans-serif",
- bold ? "bold" : "normal",
- italic ? "italic" : "normal");
+ *family = fixedWidth ? "monospace" : serif ? "serif" : "sans-serif";
+ *weight = bold ? "bold" : "normal";
+ *style = italic ? "italic" : "normal";
}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h
index e870d8ef842..d09eea3f266 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h
@@ -20,6 +20,7 @@ class PDFDoc;
class TextOutputDev;
class TextFontInfo;
class SplashOutputDev;
+class HTMLGenFontDefn;
//------------------------------------------------------------------------
@@ -46,8 +47,11 @@ public:
void setAllTextInvisible(GBool allTextInvisibleA)
{ allTextInvisible = allTextInvisibleA; }
+ void setExtractFontFiles(GBool extractFontFilesA)
+ { extractFontFiles = extractFontFilesA; }
+
void startDoc(PDFDoc *docA);
- int convertPage(int pg, const char *pngURL,
+ int convertPage(int pg, const char *pngURL, const char *htmlDir,
int (*writeHTML)(void *stream, const char *data, int size),
void *htmlStream,
int (*writePNG)(void *stream, const char *data, int size),
@@ -61,20 +65,29 @@ private:
int primaryDir, int spanDir,
double base, GBool dropCapLine, GString *s);
void appendUTF8(Unicode u, GString *s);
- GString *getFontDefn(TextFontInfo *font, double *scale);
+ HTMLGenFontDefn *getFontDefn(TextFontInfo *font, const char *htmlDir);
+ HTMLGenFontDefn *getFontFile(TextFontInfo *font, const char *htmlDir);
+ HTMLGenFontDefn *getSubstituteFont(TextFontInfo *font);
+ void getFontDetails(TextFontInfo *font, const char **family,
+ const char **weight, const char **style,
+ double *scale);
double backgroundResolution;
double zoom;
GBool drawInvisibleText;
GBool allTextInvisible;
+ GBool extractFontFiles;
PDFDoc *doc;
TextOutputDev *textOut;
SplashOutputDev *splashOut;
- GList *fonts;
+ GList *fonts; // [TextFontInfo]
double *fontScales;
+ GList *fontDefns; // [HTMLGenFontDefn]
+ int nextFontFaceIdx;
+
GBool ok;
};
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc
index d3c9b6f8c4d..fcb9d6d0e3a 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc
@@ -838,6 +838,9 @@ void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
} else {
y0 = 0;
}
+ if (y > INT_MAX - bitmap->h) {
+ return;
+ }
if (y + bitmap->h > h) {
y1 = h - y;
} else {
@@ -1202,10 +1205,13 @@ Stream *JBIG2Stream::copy() {
}
void JBIG2Stream::reset() {
- // read the globals stream
+ GList *t;
+
+ segments = new GList();
globalSegments = new GList();
+
+ // read the globals stream
if (globalsStream.isStream()) {
- segments = globalSegments;
curStr = globalsStream.getStream();
curStr->reset();
arithDecoder->setStream(curStr);
@@ -1213,10 +1219,13 @@ void JBIG2Stream::reset() {
mmrDecoder->setStream(curStr);
readSegments();
curStr->close();
+ // swap the newly read segments list into globalSegments
+ t = segments;
+ segments = globalSegments;
+ globalSegments = t;
}
// read the main stream
- segments = new GList();
curStr = str;
curStr->reset();
arithDecoder->setStream(curStr);
@@ -1280,7 +1289,8 @@ int JBIG2Stream::getBlock(char *blk, int size) {
return n;
}
-GString *JBIG2Stream::getPSFilter(int psLevel, const char *indent) {
+GString *JBIG2Stream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
return NULL;
}
@@ -1506,7 +1516,7 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
Guint symHeight, symWidth, totalWidth, x, symID;
int dh, dw, refAggNum, refDX, refDY, bmSize;
GBool ex;
- int run, cnt;
+ int run, prevRun, cnt;
Guint i, j, k;
symWidths = NULL;
@@ -1853,12 +1863,21 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
// exported symbol list
i = j = 0;
ex = gFalse;
+ prevRun = 1;
while (i < numInputSyms + numNewSyms) {
if (huff) {
huffDecoder->decodeInt(&run, huffTableA);
} else {
arithDecoder->decodeInt(&run, iaexStats);
}
+ if (run == 0 && prevRun == 0) {
+ // this avoids infinite loops with damaged files (consecutive
+ // zero runs are never useful)
+ error(errSyntaxError, getPos(),
+ "Invalid exported symbol list in JBIG2 symbol dictionary");
+ delete symbolDict;
+ goto syntaxError;
+ }
if (i + run > numInputSyms + numNewSyms ||
(ex && j + run > numExSyms)) {
error(errSyntaxError, getPos(),
@@ -1874,6 +1893,7 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
i += run;
}
ex = !ex;
+ prevRun = run;
}
if (j != numExSyms) {
error(errSyntaxError, getPos(), "Too few symbols in JBIG2 symbol dictionary");
@@ -2143,18 +2163,23 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
runLengthTab[i].val = i;
runLengthTab[i].prefixLen = huffDecoder->readBits(4);
runLengthTab[i].rangeLen = 0;
+ runLengthTab[i].prefix = 0;
}
runLengthTab[32].val = 0x103;
runLengthTab[32].prefixLen = huffDecoder->readBits(4);
runLengthTab[32].rangeLen = 2;
+ runLengthTab[32].prefix = 0;
runLengthTab[33].val = 0x203;
runLengthTab[33].prefixLen = huffDecoder->readBits(4);
runLengthTab[33].rangeLen = 3;
+ runLengthTab[33].prefix = 0;
runLengthTab[34].val = 0x20b;
runLengthTab[34].prefixLen = huffDecoder->readBits(4);
runLengthTab[34].rangeLen = 7;
+ runLengthTab[34].prefix = 0;
runLengthTab[35].prefixLen = 0;
runLengthTab[35].rangeLen = jbig2HuffmanEOT;
+ runLengthTab[35].prefix = 0;
huffDecoder->buildTable(runLengthTab, 35);
symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1,
sizeof(JBIG2HuffmanTable));
@@ -2170,6 +2195,12 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
symCodeTab[i++].prefixLen = 0;
}
} else if (j > 0x100) {
+ if (i == 0) {
+ error(errSyntaxError, getPos(), "Invalid code in JBIG2 text region");
+ gfree(syms);
+ gfree(symCodeTab);
+ return;
+ }
for (j -= 0x100; j && i < numSyms; --j) {
symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
++i;
@@ -2226,8 +2257,8 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
codeTableError:
error(errSyntaxError, getPos(), "Missing code table in JBIG2 text region");
- gfree(codeTables);
- delete syms;
+ delete codeTables;
+ gfree(syms);
return;
eofError:
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h
index 17181d72038..7aa4d9d8edb 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h
@@ -42,7 +42,8 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getBlock(char *blk, int size);
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
index 79a7c51eda9..a5dd6f0db0e 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
@@ -414,18 +414,17 @@ void JPXStream::fillReadBuf() {
if (curY >= (img.ySize >> reduction)) {
return;
}
- tileIdx = ((curY - img.yTileOffsetR) / img.yTileSizeR) * img.nXTiles
- + (curX - img.xTileOffsetR) / img.xTileSizeR;
+ tileIdx = (((curY << reduction) - img.yTileOffset) / img.yTileSize)
+ * img.nXTiles
+ + ((curX << reduction) - img.xTileOffset) / img.xTileSize;
#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
tileComp = &img.tiles[tileIdx].tileComps[curComp];
#else
tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
#endif
- //~ can curX/curY be less than x/yTileOffsetR?
- //~ if yes, we need to use tx = max(0, ....)
- tx = jpxFloorDiv((curX - img.xTileOffsetR) % img.xTileSizeR,
+ tx = jpxFloorDiv(curX - jpxCeilDivPow2(img.tiles[tileIdx].x0, reduction),
tileComp->hSep);
- ty = jpxFloorDiv((curY - img.yTileOffsetR) % img.yTileSizeR,
+ ty = jpxFloorDiv(curY - jpxCeilDivPow2(img.tiles[tileIdx].y0, reduction),
tileComp->vSep);
pix = (int)tileComp->data[ty * tileComp->w + tx];
pixBits = tileComp->prec;
@@ -463,7 +462,8 @@ void JPXStream::fillReadBuf() {
} while (readBufLen < 8);
}
-GString *JPXStream::getPSFilter(int psLevel, const char *indent) {
+GString *JPXStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
return NULL;
}
@@ -960,10 +960,6 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) {
img.ySizeR = jpxCeilDivPow2(img.ySize, reduction);
img.xOffsetR = jpxCeilDivPow2(img.xOffset, reduction);
img.yOffsetR = jpxCeilDivPow2(img.yOffset, reduction);
- img.xTileSizeR = jpxCeilDivPow2(img.xTileSize, reduction);
- img.yTileSizeR = jpxCeilDivPow2(img.yTileSize, reduction);
- img.xTileOffsetR = jpxCeilDivPow2(img.xTileOffset, reduction);
- img.yTileOffsetR = jpxCeilDivPow2(img.yTileOffset, reduction);
img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
/ img.xTileSize;
img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
@@ -1449,8 +1445,7 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) {
ok = gTrue;
while (1) {
if (!readTilePart()) {
- ok = gFalse;
- break;
+ return jpxDecodeFatalError;
}
if (!readMarkerHdr(&segType, &segLen)) {
error(errSyntaxError, getPos(), "Error in JPX codestream");
@@ -1913,6 +1908,7 @@ GBool JPXStream::readTilePart() {
tile->res = 0;
tile->precinct = 0;
tile->layer = 0;
+ tile->done = gFalse;
tile->maxNDecompLevels = 0;
for (comp = 0; comp < img.nComps; ++comp) {
tileComp = &tile->tileComps[comp];
@@ -1925,8 +1921,15 @@ GBool JPXStream::readTilePart() {
tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep);
tileComp->cbW = 1 << tileComp->codeBlockW;
tileComp->cbH = 1 << tileComp->codeBlockH;
- tileComp->w = jpxCeilDivPow2(tileComp->x1 - tileComp->x0, reduction);
- tileComp->h = jpxCeilDivPow2(tileComp->y1 - tileComp->y0, reduction);
+ tileComp->w = jpxCeilDivPow2(tileComp->x1, reduction)
+ - jpxCeilDivPow2(tileComp->x0, reduction);
+ tileComp->h = jpxCeilDivPow2(tileComp->y1, reduction)
+ - jpxCeilDivPow2(tileComp->y0, reduction);
+ if (tileComp->w == 0 || tileComp->h == 0) {
+ error(errSyntaxError, getPos(),
+ "Invalid tile size or sample separation in JPX stream");
+ return gFalse;
+ }
tileComp->data = (int *)gmallocn(tileComp->w * tileComp->h, sizeof(int));
if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
n = tileComp->x1 - tileComp->x0;
@@ -1942,13 +1945,20 @@ GBool JPXStream::readTilePart() {
resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
+ // the JPEG 2000 spec says that packets for empty res levels
+ // should all be present in the codestream (B.6, B.9, B.10),
+ // but it appears that encoders drop packets if the res level
+ // AND the subbands are all completely empty
+ resLevel->empty = resLevel->x0 == resLevel->x1 ||
+ resLevel->y0 == resLevel->y1;
if (r == 0) {
resLevel->bx0[0] = resLevel->x0;
resLevel->by0[0] = resLevel->y0;
resLevel->bx1[0] = resLevel->x1;
resLevel->by1[0] = resLevel->y1;
- resLevel->empty = resLevel->bx0[0] == resLevel->bx1[0] ||
- resLevel->by0[0] == resLevel->by1[0];
+ resLevel->empty = resLevel->empty &&
+ (resLevel->bx0[0] == resLevel->bx1[0] ||
+ resLevel->by0[0] == resLevel->by1[0]);
} else {
resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
resLevel->by0[0] = resLevel->y0;
@@ -1962,7 +1972,8 @@ GBool JPXStream::readTilePart() {
resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
- resLevel->empty = (resLevel->bx0[0] == resLevel->bx1[0] ||
+ resLevel->empty = resLevel->empty &&
+ (resLevel->bx0[0] == resLevel->bx1[0] ||
resLevel->by0[0] == resLevel->by1[0]) &&
(resLevel->bx0[1] == resLevel->bx1[1] ||
resLevel->by0[1] == resLevel->by1[1]) &&
@@ -2117,6 +2128,12 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile = &img.tiles[tileIdx];
+ // if the tile is finished, just skip this tile part
+ if (tile->done) {
+ bufStr->discardChars(tilePartLen);
+ return gTrue;
+ }
+
// read all packets from this tile-part
while (1) {
if (tilePartToEOC) {
@@ -2373,6 +2390,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile->res = 0;
if (++tile->layer == tile->nLayers) {
tile->layer = 0;
+ tile->done = gTrue;
}
}
}
@@ -2385,6 +2403,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile->layer = 0;
if (++tile->res == tile->maxNDecompLevels + 1) {
tile->res = 0;
+ tile->done = gTrue;
}
}
}
@@ -2398,6 +2417,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile->comp = 0;
if (++tile->res == tile->maxNDecompLevels + 1) {
tile->res = 0;
+ tile->done = gTrue;
}
}
}
@@ -2411,6 +2431,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile->res = 0;
if (++tile->comp == img.nComps) {
tile->comp = 0;
+ tile->done = gTrue;
}
}
}
@@ -2424,6 +2445,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile->res = 0;
if (++tile->comp == img.nComps) {
tile->comp = 0;
+ tile->done = gTrue;
}
}
}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h
index f1a66f5310d..bc5eac4f5ee 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h
@@ -230,10 +230,11 @@ struct JPXTile {
// in any component in this tile
//----- progression order loop counters
- Guint comp; // component
- Guint res; // resolution level
- Guint precinct; // precinct
- Guint layer; // layer
+ Guint comp; // component
+ Guint res; // resolution level
+ Guint precinct; // precinct
+ Guint layer; // layer
+ GBool done; // set when this tile is done
//----- tile part info
Guint nextTilePart; // next expected tile-part
@@ -253,9 +254,6 @@ struct JPXImage {
yTileOffset;
Guint xSizeR, ySizeR; // size of reference grid >> reduction
Guint xOffsetR, yOffsetR; // image offset >> reduction
- Guint xTileSizeR, yTileSizeR; // size of tiles >> reduction
- Guint xTileOffsetR, // offset of first tile >> reduction
- yTileOffsetR;
Guint nComps; // number of components
//----- computed
@@ -287,7 +285,8 @@ public:
virtual void close();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
virtual void getImageParams(int *bitsPerComponent,
StreamColorSpaceMode *csMode);
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc
index 05e9df9f24c..6ff75b0b621 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc
@@ -112,7 +112,7 @@ int Lexer::lookChar() {
Object *Lexer::getObj(Object *obj) {
char *p;
int c, c2;
- GBool comment, neg, doubleMinus, done;
+ GBool comment, neg, doubleMinus, done, invalid;
int numParen;
int xi;
double xf, scale;
@@ -343,6 +343,7 @@ Object *Lexer::getObj(Object *obj) {
p = tokBuf;
n = 0;
s = NULL;
+ invalid = gFalse;
while ((c = lookChar()) != EOF && !specialChars[c]) {
getChar();
if (c == '#') {
@@ -370,6 +371,9 @@ Object *Lexer::getObj(Object *obj) {
goto notEscChar;
}
getChar();
+ if (c == 0) {
+ invalid = gTrue;
+ }
}
notEscChar:
// the PDF spec claims that names are limited to 127 chars, but
@@ -385,7 +389,13 @@ Object *Lexer::getObj(Object *obj) {
s->append((char)c);
}
}
- if (n < tokBufSize) {
+ if (invalid) {
+ error(errSyntaxError, getPos(), "Null character in name");
+ obj->initError();
+ if (s) {
+ delete s;
+ }
+ } else if (n < tokBufSize) {
*p = '\0';
obj->initName(tokBuf);
} else {
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc
index 70919f48947..09b5b99759a 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc
@@ -39,7 +39,7 @@
PDFCore::PDFCore(SplashColorMode colorMode, int bitmapRowPad,
GBool reverseVideo, SplashColorPtr paperColor) {
- GString *initialZoom;
+ GString *initialZoom, *initialDisplayMode;
int z, i;
doc = NULL;
@@ -81,6 +81,19 @@ PDFCore::PDFCore(SplashColorMode colorMode, int bitmapRowPad,
state->setZoom(z);
}
delete initialZoom;
+ initialDisplayMode = globalParams->getInitialDisplayMode();
+ if (!initialDisplayMode->cmp("single")) {
+ state->setDisplayMode(displaySingle);
+ } else if (!initialDisplayMode->cmp("sideBySideSingle")) {
+ state->setDisplayMode(displaySideBySideSingle);
+ } else if (!initialDisplayMode->cmp("sideBySideContinuous")) {
+ state->setDisplayMode(displaySideBySideContinuous);
+ } else if (!initialDisplayMode->cmp("horizontalContinuous")) {
+ state->setDisplayMode(displayHorizontalContinuous);
+ } else {
+ state->setDisplayMode(displayContinuous);
+ }
+ delete initialDisplayMode;
selectMode = selectModeBlock;
selectPage = 0;
@@ -615,8 +628,8 @@ void PDFCore::scrollRight(int nCols) {
scrollTo(state->getScrollX() + nCols, state->getScrollY());
}
-void PDFCore::scrollUp(int nLines) {
- scrollTo(state->getScrollX(), state->getScrollY() - nLines);
+void PDFCore::scrollUp(int nLines, GBool snapToPage) {
+ scrollTo(state->getScrollX(), state->getScrollY() - nLines, snapToPage);
}
void PDFCore::scrollUpPrevPage(int nLines) {
@@ -624,12 +637,12 @@ void PDFCore::scrollUpPrevPage(int nLines) {
state->getScrollY() == 0) {
gotoPrevPage(1, gFalse, gTrue);
} else {
- scrollUp(nLines);
+ scrollUp(nLines, gTrue);
}
}
-void PDFCore::scrollDown(int nLines) {
- scrollTo(state->getScrollX(), state->getScrollY() + nLines);
+void PDFCore::scrollDown(int nLines, GBool snapToPage) {
+ scrollTo(state->getScrollX(), state->getScrollY() + nLines, snapToPage);
}
void PDFCore::scrollDownNextPage(int nLines) {
@@ -643,7 +656,7 @@ void PDFCore::scrollDownNextPage(int nLines) {
scrollDown(nLines);
}
} else {
- scrollDown(nLines);
+ scrollDown(nLines, gTrue);
}
}
@@ -655,9 +668,35 @@ void PDFCore::scrollPageDown() {
scrollDownNextPage(state->getWinH());
}
-void PDFCore::scrollTo(int x, int y) {
+void PDFCore::scrollTo(int x, int y, GBool snapToPage) {
+ int next, topPage, topPageY, sy, dy;
+
startUpdate();
state->setScrollPosition(state->getScrollPage(), x, y);
+
+ if (snapToPage) {
+ if (state->getDisplayMode() == displayContinuous ||
+ state->getDisplayMode() == displaySideBySideContinuous) {
+ next = state->getDisplayMode() == displaySideBySideContinuous ? 2 : 1;
+ topPage = tileMap->getFirstPage();
+ topPageY = tileMap->getPageTopY(topPage);
+ sy = state->getScrollY();
+ dy = sy - topPageY;
+ // note: dy can be negative here if the inter-page gap is at the
+ // top of the window
+ if (-16 < dy && dy < 16) {
+ state->setScrollPosition(state->getScrollPage(), x, topPageY);
+ } else if (topPage + next <= doc->getNumPages()) {
+ topPage += next;
+ topPageY = tileMap->getPageTopY(topPage);
+ dy = sy - topPageY;
+ if (-16 < dy && dy < 0) {
+ state->setScrollPosition(state->getScrollPage(), x, topPageY);
+ }
+ }
+ }
+ }
+
finishUpdate(gTrue, gTrue);
}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h
index 0fa089ff949..510c01a1a76 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h
@@ -135,13 +135,13 @@ public:
virtual GBool goBackward();
virtual void scrollLeft(int nCols = 16);
virtual void scrollRight(int nCols = 16);
- virtual void scrollUp(int nLines = 16);
+ virtual void scrollUp(int nLines = 16, GBool snapToPage = gFalse);
virtual void scrollUpPrevPage(int nLines = 16);
- virtual void scrollDown(int nLines = 16);
+ virtual void scrollDown(int nLines = 16, GBool snapToPage = gFalse);
virtual void scrollDownNextPage(int nLines = 16);
virtual void scrollPageUp();
virtual void scrollPageDown();
- virtual void scrollTo(int x, int y);
+ virtual void scrollTo(int x, int y, GBool snapToPage = gFalse);
virtual void scrollToLeftEdge();
virtual void scrollToRightEdge();
virtual void scrollToTopEdge();
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc
index 8bc14eb47ad..a130b164f91 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc
@@ -46,6 +46,15 @@
#define headerSearchSize 1024 // read this many bytes at beginning of
// file to look for '%PDF'
+// Avoid sharing files with child processes on Windows, where sharing
+// can cause problems.
+#ifdef _WIN32
+# define fopenReadMode "rbN"
+# define wfopenReadMode L"rbN"
+#else
+# define fopenReadMode "rb"
+#endif
+
//------------------------------------------------------------------------
// PDFDoc
//------------------------------------------------------------------------
@@ -75,18 +84,18 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
// try to open file
fileName2 = NULL;
#ifdef VMS
- if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
+ if (!(file = fopen(fileName1->getCString(), fopenReadMode, "ctx=stm"))) {
error(errIO, -1, "Couldn't open file '{0:t}'", fileName1);
errCode = errOpenFile;
return;
}
#else
- if (!(file = fopen(fileName1->getCString(), "rb"))) {
+ if (!(file = fopen(fileName1->getCString(), fopenReadMode))) {
fileName2 = fileName->copy();
fileName2->lowerCase();
- if (!(file = fopen(fileName2->getCString(), "rb"))) {
+ if (!(file = fopen(fileName2->getCString(), fopenReadMode))) {
fileName2->upperCase();
- if (!(file = fopen(fileName2->getCString(), "rb"))) {
+ if (!(file = fopen(fileName2->getCString(), fopenReadMode))) {
error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
delete fileName2;
errCode = errOpenFile;
@@ -127,9 +136,9 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword,
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version);
if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- file = _wfopen(fileNameU, L"rb");
+ file = _wfopen(fileNameU, wfopenReadMode);
} else {
- file = fopen(fileName->getCString(), "rb");
+ file = fopen(fileName->getCString(), fopenReadMode);
}
if (!file) {
error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
@@ -181,18 +190,17 @@ PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword,
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version);
if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- file = _wfopen(fileNameU, L"rb");
+ file = _wfopen(fileNameU, wfopenReadMode);
} else {
#endif /* 0 */
- file = fopen(fileName->getCString(), "rb");
+ file = fopen(fileName->getCString(), fopenReadMode);
#if 0
}
#endif /* 0 */
-
#elif defined(VMS)
- file = fopen(fileName->getCString(), "rb", "ctx=stm");
+ file = fopen(fileName->getCString(), fopenReadMode, "ctx=stm");
#else
- file = fopen(fileName->getCString(), "rb");
+ file = fopen(fileName->getCString(), fopenReadMode);
#endif
if (!file) {
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDocEncoding.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDocEncoding.cc
index c4eef7c24b8..8258395b543 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDocEncoding.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDocEncoding.cc
@@ -6,6 +6,7 @@
//
//========================================================================
+#include <aconf.h>
#include "gmempp.h"
#include "PDFDocEncoding.h"
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc
index 15a2a233990..f39a72e9015 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc
@@ -77,6 +77,7 @@ static const char *prolog[] = {
" put",
" } for",
"~123ngs",
+ "/bdef { bind def } bind def",
"/pdfSetup {",
" /pdfDuplex exch def",
" /setpagedevice where {",
@@ -393,9 +394,9 @@ static const char *prolog[] = {
"/f { fCol fill } def",
"/f* { fCol eofill } def",
"% clipping operators",
- "/W { clip newpath } def",
- "/W* { eoclip newpath } def",
- "/Ws { strokepath clip newpath } def",
+ "/W { clip newpath } bdef",
+ "/W* { eoclip newpath } bdef",
+ "/Ws { strokepath clip newpath } bdef",
"% text state operators",
"/Tc { /pdfCharSpacing exch def } def",
"/Tf { dup /pdfFontSize exch def",
@@ -985,7 +986,9 @@ public:
{ return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
virtual int lookChar()
{ return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
- virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
@@ -1084,7 +1087,9 @@ public:
{ return (bufIdx >= width && !fillBuf()) ? EOF : buf[bufIdx++]; }
virtual int lookChar()
{ return (bufIdx >= width && !fillBuf()) ? EOF : buf[bufIdx]; }
- virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
@@ -1167,7 +1172,9 @@ public:
{ return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; }
virtual int lookChar()
{ return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; }
- virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
+ { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
@@ -3841,7 +3848,7 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask,
useLZW = useRLE = gFalse;
useCompressed = gFalse;
} else {
- s = str->getPSFilter(level < psLevel3 ? 2 : 3, "");
+ s = str->getPSFilter(level < psLevel3 ? 2 : 3, "", gTrue);
if (s) {
useLZW = useRLE = gFalse;
useCompressed = gTrue;
@@ -4191,7 +4198,13 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI,
}
sliceX = sliceY = 0;
sliceW = (int)((box.x2 - box.x1) * hDPI2 / 72.0);
+ if (sliceW == 0) {
+ sliceW = 1;
+ }
sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0);
+ if (sliceH == 0) {
+ sliceH = 1;
+ }
}
nStripes = (int)ceil(((double)sliceW * (double)sliceH) /
(double)globalParams->getPSRasterSliceSize());
@@ -5223,6 +5236,7 @@ void PSOutputDev::tilingPatternFillL2(GfxState *state, Gfx *gfx,
// set the pattern
if (paintType == 2) {
+ writePS("fCol\n");
writePS("currentcolor ");
}
writePSFmt("xpdfTile{0:d} setpattern\n", numTilingPatterns);
@@ -6315,7 +6329,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxState *state,
useASCII = gFalse;
} else {
s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
- " ");
+ " ", !inlineImg);
if ((colorMap && (colorMap->getColorSpace()->getMode() == csDeviceN ||
level == psLevel2Gray || level == psLevel3Gray)) ||
inlineImg || !s) {
@@ -6790,7 +6804,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxState *state,
maskUseCompressed = gFalse;
maskUseASCII = gFalse;
} else {
- s = maskStr->getPSFilter(3, " ");
+ s = maskStr->getPSFilter(3, " ", !inlineImg);
if (!s) {
if (globalParams->getPSLZW()) {
maskUseLZW = gTrue;
@@ -7018,7 +7032,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxState *state,
useCompressed = gFalse;
useASCII = gFalse;
} else {
- s = str->getPSFilter(3, " ");
+ s = str->getPSFilter(3, " ", !inlineImg);
if ((colorMap && level == psLevel3Gray) || inlineImg || !s) {
if (globalParams->getPSLZW()) {
useLZW = gTrue;
@@ -7557,19 +7571,13 @@ GString *PSOutputDev::createDeviceNTintFunc(GfxDeviceNColorSpace *cs) {
}
obj1.free();
sepCSObj.arrayGet(3, &funcObj);
- if (!(func = Function::parse(&funcObj))) {
+ if (!(func = Function::parse(&funcObj, 1, 4))) {
funcObj.free();
sepCSObj.free();
colorants.free();
return NULL;
}
funcObj.free();
- if (func->getInputSize() != 1 || func->getOutputSize() != 4) {
- delete func;
- sepCSObj.free();
- colorants.free();
- return NULL;
- }
sepIn = 1;
func->transform(&sepIn, cmyk[i]);
delete func;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc
index df2e2b289cc..187ef5657b5 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc
@@ -28,6 +28,7 @@
#include "BuiltinFont.h"
#include "BuiltinFontTables.h"
#include "FoFiTrueType.h"
+#include "FoFiType1C.h"
#include "JPXStream.h"
#include "SplashBitmap.h"
#include "SplashGlyphBitmap.h"
@@ -498,6 +499,7 @@ public:
int cacheAssoc; // cache associativity (glyphs per set)
Guchar *cacheData; // glyph pixmap cache
T3FontCacheTag *cacheTags; // cache tags, i.e., char codes
+ GBool inUse; // set while this T3 font is in active use
};
T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
@@ -539,6 +541,7 @@ T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
for (i = 0; i < cacheSets * cacheAssoc; ++i) {
cacheTags[i].mru = (Gushort)(i & (cacheAssoc - 1));
}
+ inUse = gFalse;
}
T3FontCache::~T3FontCache() {
@@ -615,8 +618,8 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
xref = NULL;
bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
- splash = new Splash(bitmap, vectorAntialias, &screenParams);
+ colorMode != splashModeMono1, bitmapTopDown, NULL);
+ splash = new Splash(bitmap, vectorAntialias, NULL, &screenParams);
splash->setMinLineWidth(globalParams->getMinLineWidth());
splash->setStrokeAdjust(
mapStrokeAdjustMode[globalParams->getStrokeAdjust()]);
@@ -761,9 +764,10 @@ void SplashOutputDev::startPage(int pageNum, GfxState *state) {
bitmap = NULL;
}
bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
+ colorMode != splashModeMono1, bitmapTopDown,
+ NULL);
}
- splash = new Splash(bitmap, vectorAntialias, &screenParams);
+ splash = new Splash(bitmap, vectorAntialias, NULL, &screenParams);
splash->setMinLineWidth(globalParams->getMinLineWidth());
splash->setEnablePathSimplification(
globalParams->getEnablePathSimplification());
@@ -804,6 +808,7 @@ void SplashOutputDev::startPage(int pageNum, GfxState *state) {
splash->setStrokeAdjust(
mapStrokeAdjustMode[globalParams->getStrokeAdjust()]);
splash->clear(paperColor, 0);
+ reverseVideoInvertImages = globalParams->getReverseVideoInvertImages();
if (startPageCbk) {
(*startPageCbk)(startPageCbkData);
}
@@ -1149,6 +1154,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
SplashFontFile *fontFile;
int fontNum;
FoFiTrueType *ff;
+ FoFiType1C *ffT1C;
Ref embRef;
Object refObj, strObj;
#if LOAD_FONTS_FROM_MEM
@@ -1166,9 +1172,9 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
double fsx, fsy, w, fontScaleMin, fontScaleAvg, fontScale;
Gushort ww;
SplashCoord mat[4];
- char *name;
+ char *name, *start;
Unicode uBuf[8];
- int substIdx, n, code, cmap, cmapPlatform, cmapEncoding, i;
+ int substIdx, n, code, cmap, cmapPlatform, cmapEncoding, length, i;
needFontUpdate = gFalse;
font = NULL;
@@ -1306,6 +1312,17 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
}
break;
case fontType1C:
+#if LOAD_FONTS_FROM_MEM
+ if ((ffT1C = FoFiType1C::make(fontBuf->getCString(),
+ fontBuf->getLength()))) {
+#else
+ if ((ffT1C = FoFiType1C::load(fileName->getCString()))) {
+#endif
+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffT1C);
+ delete ffT1C;
+ } else {
+ codeToGID = NULL;
+ }
if (!(fontFile = fontEngine->loadType1CFont(
id,
#if LOAD_FONTS_FROM_MEM
@@ -1314,6 +1331,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
fileName->getCString(),
fileName == tmpFileName,
#endif
+ codeToGID,
(const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
@@ -1323,6 +1341,21 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
}
break;
case fontType1COT:
+ codeToGID = NULL;
+#if LOAD_FONTS_FROM_MEM
+ if ((ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(),
+ fontNum, gTrue))) {
+#else
+ if ((ff = FoFiTrueType::load(fileName->getCString(),
+ fontNum, gTrue))) {
+#endif
+ if (ff->getCFFBlock(&start, &length) &&
+ (ffT1C = FoFiType1C::make(start, length))) {
+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffT1C);
+ delete ffT1C;
+ }
+ delete ff;
+ }
if (!(fontFile = fontEngine->loadOpenTypeT1CFont(
id,
#if LOAD_FONTS_FROM_MEM
@@ -1331,6 +1364,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
fileName->getCString(),
fileName == tmpFileName,
#endif
+ codeToGID,
(const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
gfxFont->getName() ? gfxFont->getName()->getCString()
@@ -1559,6 +1593,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
break;
default:
// this shouldn't happen
+ delete fontLoc;
goto err2;
}
@@ -1593,8 +1628,8 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
(name[0] >= 'a' && name[0] <= 'z') ||
(name[0] >= '0' && name[0] <= '9'))) {
w = ((Gfx8BitFont *)gfxFont)->getWidth((Guchar)code);
- builtinFontSubst[substIdx]->widths->getWidth(name, &ww);
- if (w > 0.01 && ww > 10) {
+ if (builtinFontSubst[substIdx]->widths->getWidth(name, &ww) &&
+ w > 0.01 && ww > 10) {
w /= ww * 0.001;
if (w < fontScaleMin) {
fontScaleMin = w;
@@ -1780,7 +1815,10 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx,
// check for an excessively large tile size
tileSize = tileW * tileH;
- if (tileSize > 1000000 || tileSize < 0) {
+ if (tileXMax - tileXMin + 0.5 > (double)INT_MAX ||
+ tileYMax - tileYMin + 0.5 > (double)INT_MAX ||
+ tileW > INT_MAX / tileH ||
+ tileSize > 1000000) {
mat1[0] = mat[0];
mat1[1] = mat[1];
mat1[2] = mat[2];
@@ -1932,8 +1970,10 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx,
origBitmap = bitmap;
origSplash = splash;
bitmap = tileBitmap = new SplashBitmap(tileW, tileH, bitmapRowPad,
- colorMode, gTrue, bitmapTopDown);
- splash = new Splash(bitmap, vectorAntialias, origSplash->getScreen());
+ colorMode, gTrue, bitmapTopDown,
+ origBitmap);
+ splash = new Splash(bitmap, vectorAntialias,
+ origSplash->getImageCache(), origSplash->getScreen());
for (i = 0; i < splashMaxColorComps; ++i) {
color[i] = 0;
}
@@ -2085,7 +2125,7 @@ GBool SplashOutputDev::axialShadedFill(GfxState *state,
bitmapWidth = ixMax - ixMin;
bitmapHeight = iyMax - iyMin;
tBitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1,
- srcMode, gTrue, gTrue);
+ srcMode, gTrue, gTrue, bitmap);
memset(tBitmap->getAlphaPtr(), 0, (size_t)bitmapWidth * bitmapHeight);
nComps = splashColorModeNComps[srcMode];
@@ -2403,7 +2443,7 @@ GBool SplashOutputDev::radialShadedFill(GfxState *state,
bitmapWidth = ixMax - ixMin;
bitmapHeight = iyMax - iyMin;
tBitmap = new SplashBitmap(bitmapWidth, bitmapHeight, 1,
- srcMode, gTrue, gTrue);
+ srcMode, gTrue, gTrue, bitmap);
memset(tBitmap->getAlphaPtr(), 0, tBitmap->getAlphaRowSize() * bitmapHeight);
nComps = splashColorModeNComps[srcMode];
@@ -2908,12 +2948,25 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
if (i >= nT3Fonts) {
// create new entry in the font cache
- if (nT3Fonts == splashOutT3FontCacheSize) {
- delete t3FontCache[nT3Fonts - 1];
+ if (nT3Fonts < splashOutT3FontCacheSize) {
+ for (j = nT3Fonts; j > 0; --j) {
+ t3FontCache[j] = t3FontCache[j - 1];
+ }
+ } else {
+ for (j = nT3Fonts - 1; j >= 0; --j) {
+ if (!t3FontCache[j]->inUse) {
+ break;
+ }
+ }
+ if (j < 0) {
+ error(errSyntaxError, -1, "Type 3 fonts nested too deeply");
+ return gTrue;
+ }
+ delete t3FontCache[j];
--nT3Fonts;
- }
- for (j = nT3Fonts; j > 0; --j) {
- t3FontCache[j] = t3FontCache[j - 1];
+ for (; j > 0; --j) {
+ t3FontCache[j] = t3FontCache[j - 1];
+ }
}
++nT3Fonts;
bbox = gfxFont->getFontBBox();
@@ -2985,6 +3038,8 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
}
}
+ t3Font->inUse = gTrue;
+
// push a new Type 3 glyph record
t3gs = new T3GlyphStack();
t3gs->next = t3GlyphStack;
@@ -3021,6 +3076,7 @@ void SplashOutputDev::endType3Char(GfxState *state) {
}
t3gs = t3GlyphStack;
t3GlyphStack = t3gs->next;
+ t3gs->cache->inUse = gFalse;
delete t3gs;
}
@@ -3131,16 +3187,19 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
if (colorMode == splashModeMono1) {
colorMode = splashModeMono1;
bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
- splashModeMono1, gFalse);
- splash = new Splash(bitmap, gFalse, t3GlyphStack->origSplash->getScreen());
+ splashModeMono1, gFalse, gTrue, bitmap);
+ splash = new Splash(bitmap, gFalse,
+ t3GlyphStack->origSplash->getImageCache(),
+ t3GlyphStack->origSplash->getScreen());
color[0] = 0;
splash->clear(color);
color[0] = 0xff;
} else {
colorMode = splashModeMono8;
bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1,
- splashModeMono8, gFalse);
+ splashModeMono8, gFalse, gTrue, bitmap);
splash = new Splash(bitmap, vectorAntialias,
+ t3GlyphStack->origSplash->getImageCache(),
t3GlyphStack->origSplash->getScreen());
color[0] = 0x00;
splash->clear(color);
@@ -3214,6 +3273,7 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
double *ctm;
SplashCoord mat[6];
SplashOutImageMaskData imgMaskData;
+ GString *imgTag;
if (state->getFillColorSpace()->isNonMarking()) {
return;
@@ -3239,8 +3299,11 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
imgMaskData.height = height;
imgMaskData.y = 0;
- splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat,
+ imgTag = makeImageTag(ref);
+ splash->fillImageMask(imgTag,
+ &imageMaskSrc, &imgMaskData, width, height, mat,
t3GlyphStack != NULL, interpolate);
+
if (inlineImg) {
while (imgMaskData.y < height) {
imgMaskData.imgStr->getLine();
@@ -3248,6 +3311,7 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
}
}
+ delete imgTag;
delete imgMaskData.imgStr;
str->close();
}
@@ -3264,6 +3328,7 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state,
SplashBitmap *maskBitmap;
Splash *maskSplash;
SplashColor maskColor;
+ GString *imgTag;
ctm = state->getCTM();
mat[0] = ctm[0];
@@ -3280,8 +3345,8 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state,
imgMaskData.height = height;
imgMaskData.y = 0;
maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
- 1, splashModeMono8, gFalse);
- maskSplash = new Splash(maskBitmap, gTrue);
+ 1, splashModeMono8, gFalse, gTrue, bitmap);
+ maskSplash = new Splash(maskBitmap, gTrue, splash->getImageCache());
maskSplash->setStrokeAdjust(
mapStrokeAdjustMode[globalParams->getStrokeAdjust()]);
maskSplash->setEnablePathSimplification(
@@ -3289,8 +3354,10 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state,
clearMaskRegion(state, maskSplash, 0, 0, 1, 1);
maskColor[0] = 0xff;
maskSplash->setFillPattern(new SplashSolidColor(maskColor));
- maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
+ imgTag = makeImageTag(ref);
+ maskSplash->fillImageMask(imgTag, &imageMaskSrc, &imgMaskData,
width, height, mat, gFalse, interpolate);
+ delete imgTag;
delete imgMaskData.imgStr;
str->close();
delete maskSplash;
@@ -3304,6 +3371,7 @@ struct SplashOutImageData {
SplashColorPtr lookup;
int *maskColors;
SplashColorMode colorMode;
+ GBool invert;
int width, height, y;
};
@@ -3312,7 +3380,7 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
SplashOutImageData *imgData = (SplashOutImageData *)data;
Guchar *p;
SplashColorPtr q, col;
- int x;
+ int n, x;
if (imgData->y == imgData->height ||
!(p = imgData->imgStr->getLine())) {
@@ -3371,6 +3439,13 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
}
}
+ if (imgData->invert) {
+ n = imgData->width * splashColorModeNComps[imgData->colorMode];
+ for (x = 0, p = colorLine; x < n; ++x, ++p) {
+ *p ^= 0xff;
+ }
+ }
+
++imgData->y;
return gTrue;
}
@@ -3381,7 +3456,7 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
Guchar *p0, *p, *aq;
SplashColorPtr q, col;
Guchar alpha;
- int nComps, x, i;
+ int nComps, x, n, i;
if (imgData->y == imgData->height ||
!(p0 = imgData->imgStr->getLine())) {
@@ -3455,6 +3530,13 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
*aq++ = alpha;
}
+ if (imgData->invert) {
+ n = imgData->width * splashColorModeNComps[imgData->colorMode];
+ for (x = 0, p = colorLine; x < n; ++x, ++p) {
+ *p ^= 0xff;
+ }
+ }
+
++imgData->y;
return gTrue;
}
@@ -3470,6 +3552,7 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
SplashOutImageData imgData;
SplashColorMode srcMode;
SplashImageSource src;
+ GString *imgTag;
GfxGray gray;
GfxRGB rgb;
#if SPLASH_CMYK
@@ -3500,6 +3583,7 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
imgData.ri = state->getRenderingIntent();
imgData.maskColors = maskColors;
imgData.colorMode = colorMode;
+ imgData.invert = reverseVideo && reverseVideoInvertImages;
imgData.width = width;
imgData.height = height;
imgData.y = 0;
@@ -3559,7 +3643,9 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
srcMode = colorMode;
}
src = maskColors ? &alphaImageSrc : &imageSrc;
- splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse,
+ imgTag = makeImageTag(ref);
+ splash->drawImage(imgTag,
+ src, &imgData, srcMode, maskColors ? gTrue : gFalse,
width, height, mat, interpolate);
if (inlineImg) {
while (imgData.y < height) {
@@ -3568,6 +3654,7 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
}
}
+ delete imgTag;
gfree(imgData.lookup);
delete imgData.imgStr;
str->close();
@@ -3580,6 +3667,7 @@ struct SplashOutMaskedImageData {
SplashBitmap *mask;
SplashColorPtr lookup;
SplashColorMode colorMode;
+ GBool invert;
int width, height, y;
};
@@ -3591,7 +3679,7 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
static Guchar bitToByte[2] = {0x00, 0xff};
Guchar *maskPtr;
int maskShift;
- int x;
+ int n, x;
if (imgData->y == imgData->height ||
!(p = imgData->imgStr->getLine())) {
@@ -3672,6 +3760,13 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine,
}
}
+ if (imgData->invert) {
+ n = imgData->width * splashColorModeNComps[imgData->colorMode];
+ for (x = 0, p = colorLine; x < n; ++x, ++p) {
+ *p ^= 0xff;
+ }
+ }
+
++imgData->y;
return gTrue;
}
@@ -3692,6 +3787,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
SplashColorMode srcMode;
SplashBitmap *maskBitmap;
Splash *maskSplash;
+ GString *imgTag;
SplashColor maskColor;
GfxGray gray;
GfxRGB rgb;
@@ -3741,8 +3837,9 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
imgMaskData.width = maskWidth;
imgMaskData.height = maskHeight;
imgMaskData.y = 0;
- maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, gFalse);
- maskSplash = new Splash(maskBitmap, gFalse);
+ maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1,
+ gFalse, gTrue, bitmap);
+ maskSplash = new Splash(maskBitmap, gFalse, splash->getImageCache());
maskSplash->setStrokeAdjust(
mapStrokeAdjustMode[globalParams->getStrokeAdjust()]);
maskSplash->setEnablePathSimplification(
@@ -3752,7 +3849,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
maskColor[0] = 0xff;
maskSplash->setFillPattern(new SplashSolidColor(maskColor));
// use "glyph mode" here to get the correct scaled size
- maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData,
+ maskSplash->fillImageMask(NULL, &imageMaskSrc, &imgMaskData,
maskWidth, maskHeight, mat, gTrue, interpolate);
delete imgMaskData.imgStr;
maskStr->close();
@@ -3775,6 +3872,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
imgData.ri = state->getRenderingIntent();
imgData.mask = maskBitmap;
imgData.colorMode = colorMode;
+ imgData.invert = reverseVideo && reverseVideoInvertImages;
imgData.width = width;
imgData.height = height;
imgData.y = 0;
@@ -3833,9 +3931,12 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
} else {
srcMode = colorMode;
}
- splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue,
+ imgTag = makeImageTag(ref);
+ splash->drawImage(imgTag,
+ &maskedImageSrc, &imgData, srcMode, gTrue,
width, height, mat, interpolate);
+ delete imgTag;
delete maskBitmap;
gfree(imgData.lookup);
delete imgData.imgStr;
@@ -3850,6 +3951,7 @@ struct SplashOutSoftMaskMatteImageData {
GfxRenderingIntent ri;
Guchar matte[gfxColorMaxComps];
SplashColorMode colorMode;
+ GBool invert;
int width, height, y;
};
@@ -3866,7 +3968,7 @@ GBool SplashOutputDev::softMaskMatteImageSrc(void *data,
GfxCMYK cmyk;
#endif
Guchar alpha;
- int nComps, x;
+ int nComps, n, x;
if (imgData->y == imgData->height ||
!(p = imgData->imgStr->getLine()) ||
@@ -3938,6 +4040,13 @@ GBool SplashOutputDev::softMaskMatteImageSrc(void *data,
*aq++ = alpha;
}
+ if (imgData->invert) {
+ n = imgData->width * splashColorModeNComps[imgData->colorMode];
+ for (x = 0, p = colorLine; x < n; ++x, ++p) {
+ *p ^= 0xff;
+ }
+ }
+
++imgData->y;
return gTrue;
}
@@ -3955,6 +4064,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
SplashOutImageData imgData;
SplashOutImageData imgMaskData;
SplashOutSoftMaskMatteImageData matteImgData;
+ GString *imgTag;
SplashColorMode srcMode;
SplashBitmap *maskBitmap;
Splash *maskSplash;
@@ -4044,11 +4154,14 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
n = 1 << 8;
}
matteImgData.colorMode = colorMode;
+ matteImgData.invert = reverseVideo && reverseVideoInvertImages;
matteImgData.width = width;
matteImgData.height = height;
matteImgData.y = 0;
- splash->drawImage(&softMaskMatteImageSrc, &matteImgData,
+ imgTag = makeImageTag(ref);
+ splash->drawImage(imgTag, &softMaskMatteImageSrc, &matteImgData,
srcMode, gTrue, width, height, mat, interpolate);
+ delete imgTag;
delete matteImgData.maskStr;
delete matteImgData.imgStr;
maskStr->close();
@@ -4069,6 +4182,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
imgMaskData.ri = state->getRenderingIntent();
imgMaskData.maskColors = NULL;
imgMaskData.colorMode = splashModeMono8;
+ imgMaskData.invert = gFalse;
imgMaskData.width = maskWidth;
imgMaskData.height = maskHeight;
imgMaskData.y = 0;
@@ -4080,14 +4194,16 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
imgMaskData.lookup[i] = colToByte(gray);
}
maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
- 1, splashModeMono8, gFalse);
- maskSplash = new Splash(maskBitmap, vectorAntialias);
+ 1, splashModeMono8, gFalse, gTrue, bitmap);
+ maskSplash = new Splash(maskBitmap, vectorAntialias,
+ splash->getImageCache());
maskSplash->setStrokeAdjust(
mapStrokeAdjustMode[globalParams->getStrokeAdjust()]);
maskSplash->setEnablePathSimplification(
globalParams->getEnablePathSimplification());
clearMaskRegion(state, maskSplash, 0, 0, 1, 1);
- maskSplash->drawImage(&imageSrc, &imgMaskData, splashModeMono8, gFalse,
+ maskSplash->drawImage(NULL,
+ &imageSrc, &imgMaskData, splashModeMono8, gFalse,
maskWidth, maskHeight, mat, interpolate);
delete imgMaskData.imgStr;
maskStr->close();
@@ -4105,6 +4221,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
imgData.ri = state->getRenderingIntent();
imgData.maskColors = NULL;
imgData.colorMode = colorMode;
+ imgData.invert = reverseVideo && reverseVideoInvertImages;
imgData.width = width;
imgData.height = height;
imgData.y = 0;
@@ -4156,10 +4273,13 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
}
}
- splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat,
+ imgTag = makeImageTag(ref);
+ splash->drawImage(imgTag,
+ &imageSrc, &imgData, srcMode, gFalse, width, height, mat,
interpolate);
splash->setSoftMask(NULL);
+ delete imgTag;
gfree(imgData.lookup);
delete imgData.imgStr;
@@ -4168,12 +4288,21 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
}
}
+GString *SplashOutputDev::makeImageTag(Object *ref) {
+ if (!ref || !ref->isRef()) {
+ return NULL;
+ }
+ return GString::format("{0:d}_{1:d}", ref->getRefNum(), ref->getRefGen());
+}
+
void SplashOutputDev::reduceImageResolution(Stream *str, double *ctm,
int *width, int *height) {
double sw, sh;
int reduction;
if (str->getKind() == strJPX &&
+ *width >= 256 &&
+ *height >= 256 &&
*width * *height > 10000000) {
sw = (double)*width / (fabs(ctm[0]) + fabs(ctm[1]));
sh = (double)*height / (fabs(ctm[2]) + fabs(ctm[3]));
@@ -4396,8 +4525,9 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
// create the temporary bitmap
bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
- bitmapTopDown);
+ bitmapTopDown, transpGroup->origBitmap);
splash = new Splash(bitmap, vectorAntialias,
+ transpGroup->origSplash->getImageCache(),
transpGroup->origSplash->getScreen());
splash->setMinLineWidth(globalParams->getMinLineWidth());
splash->setStrokeAdjust(
@@ -4415,11 +4545,12 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
}
if (!isolated &&
transpGroup->origBitmap->getAlphaPtr() &&
- transpGroup->origSplash->getInNonIsolatedGroup()) {
+ transpGroup->origSplash->getInNonIsolatedGroup() &&
+ colorMode != splashModeMono1) {
// when drawing a non-isolated group into another non-isolated group,
// compute a backdrop bitmap with corrected alpha values
backdropBitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
- bitmapTopDown);
+ bitmapTopDown, transpGroup->origBitmap);
transpGroup->origSplash->blitCorrectedAlpha(backdropBitmap,
tx, ty, 0, 0, w, h);
transpGroup->backdropBitmap = backdropBitmap;
@@ -4521,6 +4652,7 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox,
//~ space is given
if (transpGroupStack->blendingColorSpace) {
tSplash = new Splash(tBitmap, vectorAntialias,
+ transpGroupStack->origSplash->getImageCache(),
transpGroupStack->origSplash->getScreen());
tSplash->setStrokeAdjust(
mapStrokeAdjustMode[globalParams->getStrokeAdjust()]);
@@ -4578,7 +4710,7 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox,
}
softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(),
- 1, splashModeMono8, gFalse);
+ 1, splashModeMono8, gFalse, gTrue, bitmap);
memset(softMask->getDataPtr(), (int)(backdrop2 * 255.0 + 0.5),
softMask->getRowSize() * softMask->getHeight());
if (tx < softMask->getWidth() && ty < softMask->getHeight()) {
@@ -4660,7 +4792,7 @@ SplashBitmap *SplashOutputDev::takeBitmap() {
ret = bitmap;
bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
- colorMode != splashModeMono1, bitmapTopDown);
+ colorMode != splashModeMono1, bitmapTopDown, NULL);
return ret;
}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h
index 12e8831a905..2215f883d32 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h
@@ -279,6 +279,7 @@ private:
static GBool softMaskMatteImageSrc(void *data,
SplashColorPtr colorLine,
Guchar *alphaLine);
+ GString *makeImageTag(Object *ref);
void reduceImageResolution(Stream *str, double *mat,
int *width, int *height);
void clearMaskRegion(GfxState *state,
@@ -295,6 +296,7 @@ private:
GBool allowAntialias;
GBool vectorAntialias;
GBool reverseVideo; // reverse video mode
+ GBool reverseVideoInvertImages;
SplashColor paperColor; // paper color
SplashScreenParams screenParams;
GBool skipHorizText;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc
index 4e9a2dc2ff4..a7c13c9eab3 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc
@@ -121,7 +121,8 @@ Guint Stream::discardChars(Guint n) {
return count;
}
-GString *Stream::getPSFilter(int psLevel, const char *indent) {
+GString *Stream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
return new GString();
}
@@ -132,15 +133,15 @@ Stream *Stream::addFilters(Object *dict, int recursion) {
int i;
str = this;
- dict->dictLookup("Filter", &obj);
+ dict->dictLookup("Filter", &obj, recursion);
if (obj.isNull()) {
obj.free();
- dict->dictLookup("F", &obj);
+ dict->dictLookup("F", &obj, recursion);
}
- dict->dictLookup("DecodeParms", &params);
+ dict->dictLookup("DecodeParms", &params, recursion);
if (params.isNull()) {
params.free();
- dict->dictLookup("DP", &params);
+ dict->dictLookup("DP", &params, recursion);
}
if (obj.isName()) {
str = makeFilter(obj.getName(), str, &params, recursion);
@@ -1096,13 +1097,14 @@ int ASCIIHexStream::lookChar() {
return buf;
}
-GString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent) {
+GString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
if (psLevel < 2) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
return NULL;
}
s->append(indent)->append("/ASCIIHexDecode filter\n");
@@ -1181,13 +1183,14 @@ int ASCII85Stream::lookChar() {
return b[index];
}
-GString *ASCII85Stream::getPSFilter(int psLevel, const char *indent) {
+GString *ASCII85Stream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
if (psLevel < 2) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
return NULL;
}
s->append(indent)->append("/ASCII85Decode filter\n");
@@ -1408,13 +1411,14 @@ int LZWStream::getCode() {
return code;
}
-GString *LZWStream::getPSFilter(int psLevel, const char *indent) {
+GString *LZWStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
if (psLevel < 2 || pred) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
return NULL;
}
s->append(indent)->append("<< ");
@@ -1474,13 +1478,14 @@ int RunLengthStream::getBlock(char *blk, int size) {
return n;
}
-GString *RunLengthStream::getPSFilter(int psLevel, const char *indent) {
+GString *RunLengthStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
if (psLevel < 2) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
return NULL;
}
s->append(indent)->append("/RunLengthDecode filter\n");
@@ -2012,7 +2017,7 @@ GBool CCITTFaxStream::readRow() {
lookBits(1);
eatBits(1);
}
- if (encoding >= 0) {
+ if (encoding > 0) {
for (i = 0; i < 4; ++i) {
code1 = lookBits(12);
if (code1 != 0x001) {
@@ -2260,14 +2265,15 @@ short CCITTFaxStream::lookBits(int n) {
return (short)((inputBuf >> (inputBits - n)) & (0xffffffff >> (32 - n)));
}
-GString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent) {
+GString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
char s1[50];
if (psLevel < 2) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
return NULL;
}
s->append(indent)->append("<< ");
@@ -2384,6 +2390,11 @@ void DCTStream::reset() {
jpeg_start_decompress(&decomp);
}
+GBool DCTStream::checkSequentialInterleaved() {
+ //~ this is unimplemented
+ return gTrue;
+}
+
void DCTStream::close() {
// we don't call jpeg_finish_decompress() here because it will report
// an error if the full image wasn't read
@@ -2754,6 +2765,28 @@ void DCTStream::reset() {
}
}
+GBool DCTStream::checkSequentialInterleaved() {
+ GBool headerOk;
+
+ str->reset();
+
+ progressive = interleaved = gFalse;
+ width = height = 0;
+ numComps = 0;
+ numQuantTables = 0;
+ numDCHuffTables = 0;
+ numACHuffTables = 0;
+ gotJFIFMarker = gFalse;
+ gotAdobeMarker = gFalse;
+ restartInterval = 0;
+
+ headerOk = readHeader(gTrue);
+
+ FilterStream::close();
+
+ return headerOk && !progressive && interleaved;
+}
+
void DCTStream::close() {
int i;
@@ -3755,7 +3788,7 @@ int DCTStream::readBit() {
GBool DCTStream::readHeader(GBool frame) {
GBool doScan;
- int n;
+ int n, i;
int c = 0;
// read headers
@@ -3850,6 +3883,13 @@ GBool DCTStream::readHeader(GBool frame) {
}
}
+ for (i = 0; i < numComps; ++i) {
+ if (compInfo[i].quantTable >= numQuantTables) {
+ error(errSyntaxError, getPos(), "Invalid DCT quant table selector");
+ return gFalse;
+ }
+ }
+
return gTrue;
}
@@ -3878,8 +3918,14 @@ GBool DCTStream::readBaselineSOF() {
compInfo[i].hSample = (c >> 4) & 0x0f;
compInfo[i].vSample = c & 0x0f;
compInfo[i].quantTable = str->getChar();
- if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 ||
- compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
+ // a sampling factor of 3 is allowed by the spec, but requires
+ // messy upsampling, and appears not to be used in practice
+ if (!(compInfo[i].hSample == 1 ||
+ compInfo[i].hSample == 2 ||
+ compInfo[i].hSample == 4) ||
+ !(compInfo[i].vSample == 1 ||
+ compInfo[i].vSample == 2 ||
+ compInfo[i].vSample == 4)) {
error(errSyntaxError, getPos(), "Bad DCT sampling factor");
return gFalse;
}
@@ -3917,8 +3963,14 @@ GBool DCTStream::readProgressiveSOF() {
compInfo[i].hSample = (c >> 4) & 0x0f;
compInfo[i].vSample = c & 0x0f;
compInfo[i].quantTable = str->getChar();
- if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 ||
- compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
+ // a sampling factor of 3 is allowed by the spec, but requires
+ // messy upsampling, and appears not to be used in practice
+ if (!(compInfo[i].hSample == 1 ||
+ compInfo[i].hSample == 2 ||
+ compInfo[i].hSample == 4) ||
+ !(compInfo[i].vSample == 1 ||
+ compInfo[i].vSample == 2 ||
+ compInfo[i].vSample == 4)) {
error(errSyntaxError, getPos(), "Bad DCT sampling factor");
return gFalse;
}
@@ -4182,13 +4234,19 @@ int DCTStream::read16() {
#endif // HAVE_JPEGLIB
-GString *DCTStream::getPSFilter(int psLevel, const char *indent) {
+GString *DCTStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
if (psLevel < 2) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
+ return NULL;
+ }
+ if (okToReadStream && !checkSequentialInterleaved()) {
+ // PostScript does not allow progressive or interleaved JPEG
+ delete s;
return NULL;
}
s->append(indent)->append("<< >> /DCTDecode filter\n");
@@ -4982,13 +5040,14 @@ int FlateStream::getBlock(char *blk, int size) {
return n;
}
-GString *FlateStream::getPSFilter(int psLevel, const char *indent) {
+GString *FlateStream::getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream) {
GString *s;
if (psLevel < 3 || pred) {
return NULL;
}
- if (!(s = str->getPSFilter(psLevel, indent))) {
+ if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
return NULL;
}
s->append(indent)->append("<< >> /FlateDecode filter\n");
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h
index c25d46b2cd7..38a8dd3497c 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h
@@ -117,7 +117,8 @@ public:
virtual void setPos(GFileOffset pos, int dir = 0) = 0;
// Get PostScript command for the filter(s).
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
// Does this stream type potentially contain non-printable chars?
virtual GBool isBinary(GBool last = gTrue) = 0;
@@ -422,7 +423,8 @@ public:
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -446,7 +448,8 @@ public:
virtual int getChar()
{ int ch = lookChar(); ++index; return ch; }
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -474,7 +477,8 @@ public:
virtual int lookChar();
virtual int getRawChar();
virtual int getBlock(char *blk, int size);
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -520,7 +524,8 @@ public:
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual int getBlock(char *blk, int size);
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -552,7 +557,8 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getBlock(char *blk, int size);
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -650,12 +656,15 @@ public:
virtual int getChar();
virtual int lookChar();
virtual int getBlock(char *blk, int size);
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
Stream *getRawStream() { return str; }
private:
+ GBool checkSequentialInterleaved();
+
#if HAVE_JPEGLIB
int colorXform; // color transform: -1 = unspecified
@@ -785,7 +794,8 @@ public:
virtual int lookChar();
virtual int getRawChar();
virtual int getBlock(char *blk, int size);
- virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream);
virtual GBool isBinary(GBool last = gTrue);
private:
@@ -840,7 +850,8 @@ public:
virtual int getChar() { return EOF; }
virtual int lookChar() { return EOF; }
virtual int getBlock(char *blk, int size) { return 0; }
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
};
@@ -859,7 +870,8 @@ public:
virtual void reset();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue);
@@ -885,7 +897,8 @@ public:
virtual void reset();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue);
virtual GBool isEncoder() { return gTrue; }
@@ -912,7 +925,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
@@ -944,7 +958,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
@@ -976,7 +991,8 @@ public:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
@@ -1012,7 +1028,8 @@ public:
virtual void reset();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(int psLevel, const char *indent)
+ virtual GString *getPSFilter(int psLevel, const char *indent,
+ GBool okToReadStream)
{ return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
virtual GBool isEncoder() { return gTrue; }
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc
index 9c226af3f31..4f594384915 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
+#include <limits.h>
#include <ctype.h>
#ifdef _WIN32
#include <fcntl.h> // for O_BINARY
@@ -111,7 +112,7 @@
// In simple layout mode, lines are broken at gaps larger than this
// value multiplied by font size.
-#define simpleLayoutGapThreshold 0.4
+#define simpleLayoutGapThreshold 0.7
// Table cells (TextColumns) are allowed to overlap by this much
// in table layout mode (as a fraction of cell width or height).
@@ -407,19 +408,52 @@ void TextBlock::updateBounds(int childIdx) {
}
//------------------------------------------------------------------------
-// TextGap
+// TextGaps
//------------------------------------------------------------------------
-class TextGap {
+struct TextGap {
+ double x; // center of gap: x for vertical gaps,
+ // y for horizontal gaps
+ double w; // width/height of gap
+};
+
+class TextGaps {
public:
- TextGap(double aXY, double aW): xy(aXY), w(aW) {}
+ TextGaps();
+ ~TextGaps();
+ void addGap(double x, double w);
+ int getLength() { return length; }
+ double getX(int idx) { return gaps[idx].x; }
+ double getW(int idx) { return gaps[idx].w; }
- double xy; // center of gap: x for vertical gaps,
- // y for horizontal gaps
- double w; // width of gap
+private:
+
+ int length;
+ int size;
+ TextGap *gaps;
};
+TextGaps::TextGaps() {
+ length = 0;
+ size = 16;
+ gaps = (TextGap *)gmallocn(size, sizeof(TextGap));
+}
+
+TextGaps::~TextGaps() {
+ gfree(gaps);
+}
+
+void TextGaps::addGap(double x, double w) {
+ if (length == size) {
+ size *= 2;
+ gaps = (TextGap *)greallocn(gaps, size, sizeof(TextGap));
+ }
+ gaps[length].x = x;
+ gaps[length].w = w;
+ ++length;
+}
+
//------------------------------------------------------------------------
// TextSuperLine
//------------------------------------------------------------------------
@@ -508,6 +542,10 @@ TextOutputControl::TextOutputControl() {
discardInvisibleText = gFalse;
discardClippedText = gFalse;
insertBOM = gFalse;
+ marginLeft = 0;
+ marginRight = 0;
+ marginTop = 0;
+ marginBottom = 0;
}
@@ -1136,9 +1174,11 @@ void TextPage::updateFont(GfxState *state) {
if (name && name[0] == 'm' && name[1] == '\0') {
mCode = code;
}
- if (letterCode < 0 && name && name[1] == '\0' &&
+ if (letterCode < 0 &&
+ name &&
((name[0] >= 'A' && name[0] <= 'Z') ||
- (name[0] >= 'a' && name[0] <= 'z'))) {
+ (name[0] >= 'a' && name[0] <= 'z')) &&
+ name[1] == '\0') {
letterCode = code;
}
if (anyCode < 0 && name &&
@@ -1239,9 +1279,12 @@ void TextPage::addChar(GfxState *state, double x, double y,
// throw away chars that aren't inside the page bounds
// (and also do a sanity check on the character size)
state->transform(x, y, &x1, &y1);
- if (x1 + w1 < 0 || x1 > pageWidth ||
- y1 + h1 < 0 || y1 > pageHeight ||
- w1 > pageWidth || h1 > pageHeight) {
+ if (x1 + w1 < control.marginLeft ||
+ x1 > pageWidth - control.marginRight ||
+ y1 + h1 < control.marginTop ||
+ y1 > pageHeight - control.marginBottom ||
+ w1 > pageWidth ||
+ h1 > pageHeight) {
charPos += nBytes;
return;
}
@@ -1876,8 +1919,9 @@ void TextPage::writeRaw(void *outputStream,
if (fabs(ch2->yMin - ch->yMin) > rawModeLineDelta * ch->fontSize ||
ch2->xMin - ch->xMax < -rawModeCharOverlap * ch->fontSize) {
s->append(eol, eolLen);
- } else if (ch2->xMin - ch->xMax >
- rawModeWordSpacing * ch->fontSize) {
+ } else if (ch->spaceAfter ||
+ ch2->xMin - ch->xMax >
+ rawModeWordSpacing * ch->fontSize) {
s->append(space, spaceLen);
}
break;
@@ -1885,8 +1929,9 @@ void TextPage::writeRaw(void *outputStream,
if (fabs(ch->xMax - ch2->xMax) > rawModeLineDelta * ch->fontSize ||
ch2->yMin - ch->yMax < -rawModeCharOverlap * ch->fontSize) {
s->append(eol, eolLen);
- } else if (ch2->yMin - ch->yMax >
- rawModeWordSpacing * ch->fontSize) {
+ } else if (ch->spaceAfter ||
+ ch2->yMin - ch->yMax >
+ rawModeWordSpacing * ch->fontSize) {
s->append(space, spaceLen);
}
break;
@@ -1894,8 +1939,9 @@ void TextPage::writeRaw(void *outputStream,
if (fabs(ch->yMax - ch2->yMax) > rawModeLineDelta * ch->fontSize ||
ch->xMin - ch2->xMax < -rawModeCharOverlap * ch->fontSize) {
s->append(eol, eolLen);
- } else if (ch->xMin - ch2->xMax >
- rawModeWordSpacing * ch->fontSize) {
+ } else if (ch->spaceAfter ||
+ ch->xMin - ch2->xMax >
+ rawModeWordSpacing * ch->fontSize) {
s->append(space, spaceLen);
}
break;
@@ -1903,8 +1949,9 @@ void TextPage::writeRaw(void *outputStream,
if (fabs(ch2->xMin - ch->xMin) > rawModeLineDelta * ch->fontSize ||
ch->yMin - ch2->yMax < -rawModeCharOverlap * ch->fontSize) {
s->append(eol, eolLen);
- } else if (ch->yMin - ch2->yMax >
- rawModeWordSpacing * ch->fontSize) {
+ } else if (ch->spaceAfter ||
+ ch->yMin - ch2->yMax >
+ rawModeWordSpacing * ch->fontSize) {
s->append(space, spaceLen);
}
break;
@@ -2693,12 +2740,11 @@ TextBlock *TextPage::splitChars(GList *charsA) {
TextBlock *TextPage::split(GList *charsA, int rot) {
TextBlock *blk;
GList *chars2, *chars3;
- GList *horizGaps, *vertGaps;
- TextGap *gap;
+ TextGaps *horizGaps, *vertGaps;
TextChar *ch;
double xMin, yMin, xMax, yMax, avgFontSize;
double horizGapSize, vertGapSize, minHorizChunkWidth, minVertChunkWidth;
- double nLines, vertGapThreshold, minChunk;
+ double gap, nLines, vertGapThreshold, minChunk;
double largeCharSize;
double x0, x1, y0, y1;
int nHorizGaps, nVertGaps, nLargeChars;
@@ -2707,8 +2753,8 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
//----- find all horizontal and vertical gaps
- horizGaps = new GList();
- vertGaps = new GList();
+ horizGaps = new TextGaps();
+ vertGaps = new TextGaps();
findGaps(charsA, rot, &xMin, &yMin, &xMax, &yMax, &avgFontSize,
horizGaps, vertGaps);
@@ -2716,16 +2762,16 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
horizGapSize = 0;
for (i = 0; i < horizGaps->getLength(); ++i) {
- gap = (TextGap *)horizGaps->get(i);
- if (gap->w > horizGapSize) {
- horizGapSize = gap->w;
+ gap = horizGaps->getW(i);
+ if (gap > horizGapSize) {
+ horizGapSize = gap;
}
}
vertGapSize = 0;
for (i = 0; i < vertGaps->getLength(); ++i) {
- gap = (TextGap *)vertGaps->get(i);
- if (gap->w > vertGapSize) {
- vertGapSize = gap->w;
+ gap = vertGaps->getW(i);
+ if (gap > vertGapSize) {
+ vertGapSize = gap;
}
}
@@ -2736,14 +2782,14 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
if (horizGaps->getLength() > 0) {
y0 = yMin;
for (i = 0; i < horizGaps->getLength(); ++i) {
- gap = (TextGap *)horizGaps->get(i);
- if (gap->w > horizGapSize - splitGapSlack * avgFontSize) {
+ gap = horizGaps->getW(i);
+ if (gap > horizGapSize - splitGapSlack * avgFontSize) {
++nHorizGaps;
- y1 = gap->xy - 0.5 * gap->w;
+ y1 = horizGaps->getX(i) - 0.5 * gap;
if (y1 - y0 < minHorizChunkWidth) {
minHorizChunkWidth = y1 - y0;
}
- y0 = y1 + gap->w;
+ y0 = y1 + gap;
}
}
y1 = yMax;
@@ -2756,14 +2802,14 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
if (vertGaps->getLength() > 0) {
x0 = xMin;
for (i = 0; i < vertGaps->getLength(); ++i) {
- gap = (TextGap *)vertGaps->get(i);
- if (gap->w > vertGapSize - splitGapSlack * avgFontSize) {
+ gap = vertGaps->getW(i);
+ if (gap > vertGapSize - splitGapSlack * avgFontSize) {
++nVertGaps;
- x1 = gap->xy - 0.5 * gap->w;
+ x1 = vertGaps->getX(i) - 0.5 * gap;
if (x1 - x0 < minVertChunkWidth) {
minVertChunkWidth = x1 - x0;
}
- x0 = x1 + gap->w;
+ x0 = x1 + gap;
}
}
x1 = xMax;
@@ -2881,9 +2927,8 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
printf("vert split xMin=%g yMin=%g xMax=%g yMax=%g small=%d\n",
xMin, pageHeight - yMax, xMax, pageHeight - yMin, smallSplit);
for (i = 0; i < vertGaps->getLength(); ++i) {
- gap = (TextGap *)vertGaps->get(i);
- if (gap->w > vertGapSize - splitGapSlack * avgFontSize) {
- printf(" x=%g\n", gap->xy);
+ if (vertGaps->getW(i) > vertGapSize - splitGapSlack * avgFontSize) {
+ printf(" x=%g\n", vertGaps->getX(i));
}
}
#endif
@@ -2891,9 +2936,8 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
blk->smallSplit = smallSplit;
x0 = xMin - 1;
for (i = 0; i < vertGaps->getLength(); ++i) {
- gap = (TextGap *)vertGaps->get(i);
- if (gap->w > vertGapSize - splitGapSlack * avgFontSize) {
- x1 = gap->xy;
+ if (vertGaps->getW(i) > vertGapSize - splitGapSlack * avgFontSize) {
+ x1 = vertGaps->getX(i);
chars2 = getChars(charsA, x0, yMin - 1, x1, yMax + 1);
blk->addChild(split(chars2, rot));
delete chars2;
@@ -2910,9 +2954,8 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
printf("horiz split xMin=%g yMin=%g xMax=%g yMax=%g small=%d\n",
xMin, pageHeight - yMax, xMax, pageHeight - yMin, smallSplit);
for (i = 0; i < horizGaps->getLength(); ++i) {
- gap = (TextGap *)horizGaps->get(i);
- if (gap->w > horizGapSize - splitGapSlack * avgFontSize) {
- printf(" y=%g\n", pageHeight - gap->xy);
+ if (horizGaps->getW(i) > horizGapSize - splitGapSlack * avgFontSize) {
+ printf(" y=%g\n", pageHeight - horizGaps->getX(i));
}
}
#endif
@@ -2920,9 +2963,8 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
blk->smallSplit = smallSplit;
y0 = yMin - 1;
for (i = 0; i < horizGaps->getLength(); ++i) {
- gap = (TextGap *)horizGaps->get(i);
- if (gap->w > horizGapSize - splitGapSlack * avgFontSize) {
- y1 = gap->xy;
+ if (horizGaps->getW(i) > horizGapSize - splitGapSlack * avgFontSize) {
+ y1 = horizGaps->getX(i);
chars2 = getChars(charsA, xMin - 1, y0, xMax + 1, y1);
blk->addChild(split(chars2, rot));
delete chars2;
@@ -2966,8 +3008,8 @@ TextBlock *TextPage::split(GList *charsA, int rot) {
}
}
- deleteGList(horizGaps, TextGap);
- deleteGList(vertGaps, TextGap);
+ delete horizGaps;
+ delete vertGaps;
tagBlock(blk);
@@ -3001,11 +3043,12 @@ void TextPage::findGaps(GList *charsA, int rot,
double *xMinOut, double *yMinOut,
double *xMaxOut, double *yMaxOut,
double *avgFontSizeOut,
- GList *horizGaps, GList *vertGaps) {
+ TextGaps *horizGaps, TextGaps *vertGaps) {
TextChar *ch;
- int *horizProfile, *vertProfile;
+ char *horizProfile, *vertProfile;
double xMin, yMin, xMax, yMax, w;
- double minFontSize, avgFontSize, splitPrecision, ascentAdjust, descentAdjust;
+ double minFontSize, avgFontSize, splitPrecision, invSplitPrecision;
+ double ascentAdjust, descentAdjust;
int xMinI, yMinI, xMaxI, yMaxI, xMinI2, yMinI2, xMaxI2, yMaxI2;
int start, x, y, i;
@@ -3037,6 +3080,7 @@ void TextPage::findGaps(GList *charsA, int rot,
if (splitPrecision < minSplitPrecision) {
splitPrecision = minSplitPrecision;
}
+ invSplitPrecision = 1 / splitPrecision;
*xMinOut = xMin;
*yMinOut = yMin;
*xMaxOut = xMax;
@@ -3045,59 +3089,65 @@ void TextPage::findGaps(GList *charsA, int rot,
//----- compute the horizontal and vertical profiles
+ if (xMin * invSplitPrecision < 0.5 * INT_MIN ||
+ xMax * invSplitPrecision > 0.5 * INT_MAX ||
+ yMin * invSplitPrecision < 0.5 * INT_MIN ||
+ xMax * invSplitPrecision > 0.5 * INT_MAX) {
+ return;
+ }
// add some slack to the array bounds to avoid floating point
// precision problems
- xMinI = (int)floor(xMin / splitPrecision) - 1;
- yMinI = (int)floor(yMin / splitPrecision) - 1;
- xMaxI = (int)floor(xMax / splitPrecision) + 1;
- yMaxI = (int)floor(yMax / splitPrecision) + 1;
- horizProfile = (int *)gmallocn(yMaxI - yMinI + 1, sizeof(int));
- vertProfile = (int *)gmallocn(xMaxI - xMinI + 1, sizeof(int));
- memset(horizProfile, 0, (yMaxI - yMinI + 1) * sizeof(int));
- memset(vertProfile, 0, (xMaxI - xMinI + 1) * sizeof(int));
+ xMinI = (int)floor(xMin * invSplitPrecision) - 1;
+ yMinI = (int)floor(yMin * invSplitPrecision) - 1;
+ xMaxI = (int)floor(xMax * invSplitPrecision) + 1;
+ yMaxI = (int)floor(yMax * invSplitPrecision) + 1;
+ horizProfile = (char *)gmalloc(yMaxI - yMinI + 1);
+ vertProfile = (char *)gmalloc(xMaxI - xMinI + 1);
+ memset(horizProfile, 0, yMaxI - yMinI + 1);
+ memset(vertProfile, 0, xMaxI - xMinI + 1);
for (i = 0; i < charsA->getLength(); ++i) {
ch = (TextChar *)charsA->get(i);
// yMinI2 and yMaxI2 are adjusted to allow for slightly overlapping lines
switch (rot) {
case 0:
default:
- xMinI2 = (int)floor(ch->xMin / splitPrecision);
- xMaxI2 = (int)floor(ch->xMax / splitPrecision);
+ xMinI2 = (int)floor(ch->xMin * invSplitPrecision);
+ xMaxI2 = (int)floor(ch->xMax * invSplitPrecision);
ascentAdjust = ascentAdjustFactor * (ch->yMax - ch->yMin);
- yMinI2 = (int)floor((ch->yMin + ascentAdjust) / splitPrecision);
+ yMinI2 = (int)floor((ch->yMin + ascentAdjust) * invSplitPrecision);
descentAdjust = descentAdjustFactor * (ch->yMax - ch->yMin);
- yMaxI2 = (int)floor((ch->yMax - descentAdjust) / splitPrecision);
+ yMaxI2 = (int)floor((ch->yMax - descentAdjust) * invSplitPrecision);
break;
case 1:
descentAdjust = descentAdjustFactor * (ch->xMax - ch->xMin);
- xMinI2 = (int)floor((ch->xMin + descentAdjust) / splitPrecision);
+ xMinI2 = (int)floor((ch->xMin + descentAdjust) * invSplitPrecision);
ascentAdjust = ascentAdjustFactor * (ch->xMax - ch->xMin);
- xMaxI2 = (int)floor((ch->xMax - ascentAdjust) / splitPrecision);
- yMinI2 = (int)floor(ch->yMin / splitPrecision);
- yMaxI2 = (int)floor(ch->yMax / splitPrecision);
+ xMaxI2 = (int)floor((ch->xMax - ascentAdjust) * invSplitPrecision);
+ yMinI2 = (int)floor(ch->yMin * invSplitPrecision);
+ yMaxI2 = (int)floor(ch->yMax * invSplitPrecision);
break;
case 2:
- xMinI2 = (int)floor(ch->xMin / splitPrecision);
- xMaxI2 = (int)floor(ch->xMax / splitPrecision);
+ xMinI2 = (int)floor(ch->xMin * invSplitPrecision);
+ xMaxI2 = (int)floor(ch->xMax * invSplitPrecision);
descentAdjust = descentAdjustFactor * (ch->yMax - ch->yMin);
- yMinI2 = (int)floor((ch->yMin + descentAdjust) / splitPrecision);
+ yMinI2 = (int)floor((ch->yMin + descentAdjust) * invSplitPrecision);
ascentAdjust = ascentAdjustFactor * (ch->yMax - ch->yMin);
- yMaxI2 = (int)floor((ch->yMax - ascentAdjust) / splitPrecision);
+ yMaxI2 = (int)floor((ch->yMax - ascentAdjust) * invSplitPrecision);
break;
case 3:
ascentAdjust = ascentAdjustFactor * (ch->xMax - ch->xMin);
- xMinI2 = (int)floor((ch->xMin + ascentAdjust) / splitPrecision);
+ xMinI2 = (int)floor((ch->xMin + ascentAdjust) * invSplitPrecision);
descentAdjust = descentAdjustFactor * (ch->xMax - ch->xMin);
- xMaxI2 = (int)floor((ch->xMax - descentAdjust) / splitPrecision);
- yMinI2 = (int)floor(ch->yMin / splitPrecision);
- yMaxI2 = (int)floor(ch->yMax / splitPrecision);
+ xMaxI2 = (int)floor((ch->xMax - descentAdjust) * invSplitPrecision);
+ yMinI2 = (int)floor(ch->yMin * invSplitPrecision);
+ yMaxI2 = (int)floor(ch->yMax * invSplitPrecision);
break;
}
for (y = yMinI2; y <= yMaxI2; ++y) {
- ++horizProfile[y - yMinI];
+ horizProfile[y - yMinI] = 1;
}
for (x = xMinI2; x <= xMaxI2; ++x) {
- ++vertProfile[x - xMinI];
+ vertProfile[x - xMinI] = 1;
}
}
@@ -3112,8 +3162,7 @@ void TextPage::findGaps(GList *charsA, int rot,
} else {
if (horizProfile[y + 1 - yMinI]) {
w = (y - start) * splitPrecision;
- horizGaps->append(new TextGap((start + 1) * splitPrecision + 0.5 * w,
- w));
+ horizGaps->addGap((start + 1) * splitPrecision + 0.5 * w, w);
}
}
}
@@ -3129,8 +3178,7 @@ void TextPage::findGaps(GList *charsA, int rot,
} else {
if (vertProfile[x + 1 - xMinI]) {
w = (x - start) * splitPrecision;
- vertGaps->append(new TextGap((start + 1) * splitPrecision + 0.5 * w,
- w));
+ vertGaps->addGap((start + 1) * splitPrecision + 0.5 * w, w);
}
}
}
@@ -3818,18 +3866,27 @@ double TextPage::computeWordSpacingThreshold(GList *charsA, int rot) {
minGap = 0;
}
- // if spacing is nearly uniform (minGap is close to maxGap), use the
- // SpGap/AdjGap values if available, otherwise assume it's a single
- // word (technically it could be either "ABC" or "A B C", but it's
- // essentially impossible to tell)
+ // if spacing is nearly uniform (minGap is close to maxGap), there
+ // are three cases:
+ // (1) if the SpGap and AdjGap values are both available and
+ // sensible, use them
+ // (2) if only the SpGap values are available, meaning that every
+ // character in the line had a space after it, split after every
+ // character
+ // (3) otherwise assume it's a single word (technically it could be
+ // either "ABC" or "A B C", but it's essentially impossible to
+ // tell)
if (maxGap - minGap < uniformSpacing * avgFontSize) {
- if (minAdjGap <= maxAdjGap &&
- minSpGap <= maxSpGap &&
- minSpGap - maxAdjGap > 0.01) {
- return 0.5 * (maxAdjGap + minSpGap);
- } else {
- return maxGap + 1;
+ if (minSpGap <= maxSpGap) {
+ if (minAdjGap <= maxAdjGap &&
+ minSpGap - maxAdjGap > 0.01) {
+ return 0.5 * (maxAdjGap + minSpGap);
+ } else if (minAdjGap > maxAdjGap &&
+ maxSpGap - minSpGap < uniformSpacing * avgFontSize) {
+ return minSpGap - 1;
+ }
}
+ return maxGap + 1;
// if there is some variation in spacing, but it's small, assume
// there are some inter-word spaces
@@ -4033,8 +4090,8 @@ void TextPage::assignSimpleLayoutPositions(GList *superLines,
UnicodeMap *uMap) {
GList *lines;
TextLine *line0, *line1;
- double xMin;
- int px, sp, i, j;
+ double xMin, xMax;
+ int px, px2, sp, i, j;
// build a list of lines and sort by x
lines = new GList();
@@ -4048,21 +4105,25 @@ void TextPage::assignSimpleLayoutPositions(GList *superLines,
for (i = 0; i < lines->getLength(); ++i) {
line0 = (TextLine *)lines->get(i);
computeLinePhysWidth(line0, uMap);
- line0->px = (int)((line0->xMin - xMin) / (0.5 * line0->fontSize));
+ px = 0;
+ xMax = xMin;
for (j = 0; j < i; ++j) {
line1 = (TextLine *)lines->get(j);
if (line0->xMin > line1->xMax) {
- sp = (int)((line0->xMin - line1->xMax) /
- (0.5 * line0->fontSize) + 0.5);
- if (sp < 1) {
- sp = 1;
+ if (line1->xMax > xMax) {
+ xMax = line1->xMax;
}
- px = line1->px + line1->pw + sp;
- if (px > line0->px) {
- line0->px = px;
+ px2 = line1->px + line1->pw;
+ if (px2 > px) {
+ px = px2;
}
}
}
+ sp = (int)((line0->xMin - xMax) / (0.5 * line0->fontSize) + 0.5);
+ if (sp < 1 && xMax > xMin) {
+ sp = 1;
+ }
+ line0->px = px + sp;
}
delete lines;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h
index 0884ace6b6b..0f00cf5ae7b 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h
@@ -26,6 +26,7 @@ class UnicodeRemapping;
class TextBlock;
class TextChar;
+class TextGaps;
class TextLink;
class TextPage;
@@ -69,6 +70,10 @@ public:
GBool discardClippedText; // discard all clipped characters
GBool insertBOM; // insert a Unicode BOM at the start of
// the text output
+ double marginLeft, // characters outside the margins are
+ marginRight, // discarded
+ marginTop,
+ marginBottom;
};
//------------------------------------------------------------------------
@@ -502,7 +507,7 @@ private:
double *xMinOut, double *yMinOut,
double *xMaxOut, double *yMaxOut,
double *avgFontSizeOut,
- GList *horizGaps, GList *vertGaps);
+ TextGaps *horizGaps, TextGaps *vertGaps);
void tagBlock(TextBlock *blk);
void insertLargeChars(GList *largeChars, TextBlock *blk);
void insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk);
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc
index 431c639a020..70128a4a47f 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc
@@ -67,7 +67,7 @@ SplashBitmap *TileCompositor::getBitmap(GBool *finished) {
}
bitmap = new SplashBitmap(state->getWinW(), state->getWinH(),
state->getBitmapRowPad(), state->getColorMode(),
- gFalse);
+ gFalse, gTrue, NULL);
}
clearBitmap();
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc
index 6db67738d70..d1a5aea2963 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc
@@ -592,6 +592,11 @@ GBool TileMap::cvtWindowToDev(int xw, int yw,
offsetY = 0;
}
*pg = findContinuousPage(yw - offsetY + state->getScrollY());
+ if (*pg < 1 || *pg > state->getDoc()->getNumPages()) {
+ *pg = 0;
+ *xd = *yd = 0;
+ return gFalse;
+ }
pageW1 = pageW[*pg - 1];
pageH1 = pageH[*pg - 1];
if (maxW < state->getWinW()) {
@@ -655,6 +660,11 @@ GBool TileMap::cvtWindowToDev(int xw, int yw,
offsetY = 0;
}
*pg = findSideBySideContinuousPage(yw - offsetY + state->getScrollY());
+ if (*pg < 1 || *pg > state->getDoc()->getNumPages()) {
+ *pg = 0;
+ *xd = *yd = 0;
+ return gFalse;
+ }
pageW1 = pageW[*pg - 1];
pageH1 = pageH[*pg - 1];
if (*pg + 1 <= state->getDoc()->getNumPages()) {
@@ -693,6 +703,11 @@ GBool TileMap::cvtWindowToDev(int xw, int yw,
offsetX = 0;
}
*pg = findHorizContinuousPage(xw - offsetX + state->getScrollX());
+ if (*pg < 1 || *pg > state->getDoc()->getNumPages()) {
+ *pg = 0;
+ *xd = *yd = 0;
+ return gFalse;
+ }
pageW1 = pageW[*pg - 1];
pageH1 = pageH[*pg - 1];
if (maxH < state->getWinH()) {
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UTF8.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/UTF8.cc
index 637d36b6d58..9ee01425094 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/UTF8.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UTF8.cc
@@ -6,6 +6,7 @@
//
//========================================================================
+#include <aconf.h>
#include "UTF8.h"
int mapUTF8(Unicode u, char *buf, int bufSize) {
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
new file mode 100644
index 00000000000..95f0e983a31
--- /dev/null
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
@@ -0,0 +1,384 @@
+//========================================================================
+//
+// WebFont.cc
+//
+// Copyright 2019 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "gmempp.h"
+#include "GHash.h"
+#include "FoFiTrueType.h"
+#include "FoFiType1C.h"
+#include "CharCodeToUnicode.h"
+#include "WebFont.h"
+
+WebFont::WebFont(GfxFont *gfxFontA, XRef *xref) {
+ GfxFontType type;
+
+ gfxFont = gfxFontA;
+ fontBuf = NULL;
+ ffTrueType = NULL;
+ ffType1C = NULL;
+ isOpenType = gFalse;
+
+ type = gfxFont->getType();
+ if (type == fontTrueType ||
+ type == fontTrueTypeOT ||
+ type == fontCIDType2 ||
+ type == fontCIDType2OT) {
+ if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) {
+ ffTrueType = FoFiTrueType::make(fontBuf, fontLength, 0);
+ }
+ } else if (type == fontType1C ||
+ type == fontCIDType0C) {
+ if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) {
+ ffType1C = FoFiType1C::make(fontBuf, fontLength);
+ }
+ } else if (type == fontType1COT ||
+ type == fontCIDType0COT) {
+ if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) {
+ isOpenType = gTrue;
+ }
+ }
+}
+
+WebFont::~WebFont() {
+ delete ffTrueType;
+ delete ffType1C;
+ gfree(fontBuf);
+}
+
+GBool WebFont::canWriteTTF() {
+ return ffTrueType != NULL;
+}
+
+GBool WebFont::canWriteOTF() {
+ return ffType1C || isOpenType;
+}
+
+static void writeToFile(void *stream, const char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
+GBool WebFont::writeTTF(const char *fontFilePath) {
+ FILE *out;
+ int *codeToGID;
+ Guchar *cmapTable;
+ GBool freeCodeToGID;
+ int nCodes, cmapTableLength;
+
+ if (!ffTrueType) {
+ return gFalse;
+ }
+ if (gfxFont->isCIDFont()) {
+ codeToGID = ((GfxCIDFont *)gfxFont)->getCIDToGID();
+ nCodes = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+ if (!codeToGID) {
+ nCodes = ffTrueType->getNumGlyphs();
+ }
+ freeCodeToGID = gFalse;
+ } else {
+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffTrueType);
+ nCodes = 256;
+ freeCodeToGID = gTrue;
+ }
+ cmapTable = makeUnicodeCmapTable(codeToGID, nCodes, &cmapTableLength);
+ if (freeCodeToGID) {
+ gfree(codeToGID);
+ }
+ if (!cmapTable) {
+ return gFalse;
+ }
+ if (!(out = fopen(fontFilePath, "wb"))) {
+ gfree(cmapTable);
+ return gFalse;
+ }
+ ffTrueType->writeTTF(writeToFile, out, NULL, NULL,
+ cmapTable, cmapTableLength);
+ fclose(out);
+ gfree(cmapTable);
+ return gTrue;
+}
+
+GBool WebFont::writeOTF(const char *fontFilePath) {
+ int *codeToGID;
+ Gushort *widths;
+ Guchar *cmapTable;
+ FILE *out;
+ int nCodes, nWidths, cmapTableLength;
+
+ if (ffType1C) {
+ if (gfxFont->getType() == fontType1C) {
+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffType1C);
+ if (!(cmapTable = makeUnicodeCmapTable(codeToGID, 256,
+ &cmapTableLength))) {
+ gfree(codeToGID);
+ return gFalse;
+ }
+ widths = makeType1CWidths(codeToGID, 256, &nWidths);
+ gfree(codeToGID);
+ } else { // fontCIDType0C
+ codeToGID = ffType1C->getCIDToGIDMap(&nCodes);
+ if (!(cmapTable = makeUnicodeCmapTable(codeToGID, nCodes,
+ &cmapTableLength))) {
+ gfree(codeToGID);
+ return gFalse;
+ }
+ widths = makeCIDType0CWidths(codeToGID, nCodes, &nWidths);
+ gfree(codeToGID);
+ }
+ if (!(out = fopen(fontFilePath, "wb"))) {
+ gfree(cmapTable);
+ gfree(widths);
+ return gFalse;
+ }
+ ffType1C->convertToOpenType(writeToFile, out,
+ nWidths, widths,
+ cmapTable, cmapTableLength);
+ fclose(out);
+ gfree(cmapTable);
+ gfree(widths);
+
+ } else if (isOpenType) {
+ if (!(out = fopen(fontFilePath, "wb"))) {
+ return gFalse;
+ }
+ if (fwrite(fontBuf, 1, fontLength, out) != (Guint)fontLength) {
+ fclose(out);
+ return gFalse;
+ }
+ fclose(out);
+
+ } else {
+ return gFalse;
+ }
+
+ return gTrue;
+}
+
+Gushort *WebFont::makeType1CWidths(int *codeToGID, int nCodes,
+ int *nWidths) {
+ Gushort *widths;
+ Gushort width;
+ int widthsLen, gid, i;
+
+ widthsLen = ffType1C->getNumGlyphs();
+ widths = (Gushort *)gmallocn(widthsLen, sizeof(Gushort));
+ for (i = 0; i < widthsLen; ++i) {
+ widths[i] = 0;
+ }
+ for (i = 0; i < nCodes; ++i) {
+ gid = codeToGID[i];
+ if (gid < 0 || gid >= widthsLen) {
+ continue;
+ }
+ width = (Gushort)(((Gfx8BitFont *)gfxFont)->getWidth((Guchar)i)
+ * 1000 + 0.5);
+ if (width == 0) {
+ continue;
+ }
+ widths[gid] = width;
+ }
+ *nWidths = widthsLen;
+ return widths;
+}
+
+Gushort *WebFont::makeCIDType0CWidths(int *codeToGID, int nCodes,
+ int *nWidths) {
+ Gushort *widths;
+ Gushort width;
+ int widthsLen, gid, i;
+
+ widthsLen = ffType1C->getNumGlyphs();
+ widths = (Gushort *)gmallocn(widthsLen, sizeof(Gushort));
+ for (i = 0 ; i < widthsLen; ++i) {
+ widths[i] = 0;
+ }
+ for (i = 0; i < nCodes; ++i) {
+ gid = codeToGID[i];
+ if (gid < 0 || gid >= widthsLen) {
+ continue;
+ }
+ width = (Gushort)(((GfxCIDFont *)gfxFont)->getWidth((CID)i)
+ * 1000 + 0.5);
+ if (width == 0) {
+ continue;
+ }
+ widths[gid] = width;
+ }
+ *nWidths = widthsLen;
+ return widths;
+}
+
+Guchar *WebFont::makeUnicodeCmapTable(int *codeToGID, int nCodes,
+ int *unicodeCmapLength) {
+ int *unicodeToGID;
+ Guchar *cmapTable;
+ int unicodeToGIDLength, nMappings, len;
+ int nSegs, searchRange, entrySelector, rangeShift;
+ int glyphIdOffset, idRangeOffset;
+ int start, end, c, i;
+
+ if (!(unicodeToGID = makeUnicodeToGID(codeToGID, nCodes,
+ &unicodeToGIDLength))) {
+ return NULL;
+ }
+
+ // count the valid code-to-glyph mappings, and the sequences of
+ // consecutive valid mappings
+ // (note: char code 65535 is used to mark the end of table)
+ nMappings = 0;
+ nSegs = 1; // count the last segment, mapping 65535
+ for (c = 0; c < unicodeToGIDLength && c <= 65534; ++c) {
+ if (unicodeToGID[c]) {
+ ++nMappings;
+ if (c == 0 || !unicodeToGID[c-1]) {
+ ++nSegs;
+ }
+ }
+ }
+
+ i = 1;
+ entrySelector = 0;
+ while (2 * i <= nSegs) {
+ i *= 2;
+ ++entrySelector;
+ }
+ searchRange = 1 << (entrySelector + 1);
+ rangeShift = 2 * nSegs - searchRange;
+
+ len = 28 + nSegs * 8 + nMappings * 2;
+ cmapTable = (Guchar *)gmalloc(len);
+
+ // header
+ cmapTable[ 0] = 0x00; // table version
+ cmapTable[ 1] = 0x00;
+ cmapTable[ 2] = 0x00; // number of cmaps
+ cmapTable[ 3] = 0x01;
+ cmapTable[ 4] = 0x00; // platform[0]
+ cmapTable[ 5] = 0x03;
+ cmapTable[ 6] = 0x00; // encoding[0]
+ cmapTable[ 7] = 0x01;
+ cmapTable[ 8] = 0x00; // offset[0]
+ cmapTable[ 9] = 0x00;
+ cmapTable[10] = 0x00;
+ cmapTable[11] = 0x0c;
+
+ // table info
+ cmapTable[12] = 0x00; // cmap format
+ cmapTable[13] = 0x04;
+ cmapTable[14] = (Guchar)((len - 12) >> 8); // cmap length
+ cmapTable[15] = (Guchar)(len - 12);
+ cmapTable[16] = 0x00; // cmap version
+ cmapTable[17] = 0x00;
+ cmapTable[18] = (Guchar)(nSegs >> 7); // segCountX2
+ cmapTable[19] = (Guchar)(nSegs << 1);
+ cmapTable[20] = (Guchar)(searchRange >> 8); // searchRange
+ cmapTable[21] = (Guchar)searchRange;
+ cmapTable[22] = (Guchar)(entrySelector >> 8); // entrySelector
+ cmapTable[23] = (Guchar)entrySelector;
+ cmapTable[24] = (Guchar)(rangeShift >> 8); // rangeShift
+ cmapTable[25] = (Guchar)rangeShift;
+ cmapTable[26 + nSegs*2 ] = 0; // reservedPad
+ cmapTable[26 + nSegs*2 + 1] = 0;
+
+ i = 0;
+ glyphIdOffset = 28 + nSegs*8;
+ for (c = 0; c < unicodeToGIDLength && c <= 65534; ++c) {
+ if (unicodeToGID[c]) {
+ if (c == 0 || !unicodeToGID[c-1]) {
+ start = c;
+ cmapTable[28 + nSegs*2 + i*2 ] = (Guchar)(start >> 8);
+ cmapTable[28 + nSegs*2 + i*2 + 1] = (Guchar)start;
+ cmapTable[28 + nSegs*4 + i*2 ] = (Guchar)0; // idDelta
+ cmapTable[28 + nSegs*4 + i*2 + 1] = (Guchar)0;
+ idRangeOffset = glyphIdOffset - (28 + nSegs*6 + i*2);
+ cmapTable[28 + nSegs*6 + i*2 ] = (Guchar)(idRangeOffset >> 8);
+ cmapTable[28 + nSegs*6 + i*2 + 1] = (Guchar)idRangeOffset;
+ }
+ if (c == 65534 || !unicodeToGID[c+1]) {
+ end = c;
+ cmapTable[26 + i*2 ] = (Guchar)(end >> 8);
+ cmapTable[26 + i*2 + 1] = (Guchar)end;
+ ++i;
+ }
+ cmapTable[glyphIdOffset++] = (Guchar)(unicodeToGID[c] >> 8);
+ cmapTable[glyphIdOffset++] = (Guchar)unicodeToGID[c];
+ }
+ }
+
+ // last segment maps code 65535 to GID 0
+ cmapTable[26 + i*2 ] = (Guchar)0xff; // end
+ cmapTable[26 + i*2 + 1] = (Guchar)0xff;
+ cmapTable[28 + nSegs*2 + i*2 ] = (Guchar)0xff; // start
+ cmapTable[28 + nSegs*2 + i*2 + 1] = (Guchar)0xff;
+ cmapTable[28 + nSegs*4 + i*2 ] = (Guchar)0; // idDelta
+ cmapTable[28 + nSegs*4 + i*2 + 1] = (Guchar)1;
+ cmapTable[28 + nSegs*6 + i*2 ] = (Guchar)0; // idRangeOffset
+ cmapTable[28 + nSegs*6 + i*2 + 1] = (Guchar)0;
+
+ gfree(unicodeToGID);
+
+ *unicodeCmapLength = len;
+ return cmapTable;
+}
+
+int *WebFont::makeUnicodeToGID(int *codeToGID, int nCodes,
+ int *unicodeToGIDLength) {
+ int *unicodeToGID;
+ CharCodeToUnicode *ctu;
+ Unicode u[2];
+ int len, size, newSize, uLen, c, gid;
+
+ if (gfxFont->isCIDFont()) {
+ if (!(ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
+ return NULL;
+ }
+ } else {
+ ctu = ((Gfx8BitFont *)gfxFont)->getToUnicode();
+ }
+
+ len = 0;
+ size = 256;
+ unicodeToGID = (int *)gmallocn(size, sizeof(int));
+ memset(unicodeToGID, 0, size * sizeof(int));
+ for (c = 0; c < nCodes; ++c) {
+ gid = codeToGID ? codeToGID[c] : c;
+ if (gid < 0 || gid >= 65536) {
+ continue;
+ }
+ uLen = ctu->mapToUnicode(c, u, 2);
+ if (uLen != 1) {
+ continue;
+ }
+ if (u[0] >= 65536) { // sanity check
+ continue;
+ }
+ if ((int)u[0] >= size) {
+ newSize = 2 * size;
+ while ((int)u[0] >= newSize) {
+ newSize *= 2;
+ }
+ unicodeToGID = (int *)greallocn(unicodeToGID, newSize, sizeof(int));
+ memset(unicodeToGID + size, 0, (newSize - size) * sizeof(int));
+ size = newSize;
+ }
+ unicodeToGID[u[0]] = gid;
+ if ((int)u[0] >= len) {
+ len = u[0] + 1;
+ }
+ }
+
+ ctu->decRefCnt();
+
+ *unicodeToGIDLength = len;
+ return unicodeToGID;
+}
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h
new file mode 100644
index 00000000000..a967e2e490a
--- /dev/null
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h
@@ -0,0 +1,69 @@
+//========================================================================
+//
+// WebFont.h
+//
+// Modify/convert embedded PDF fonts to a form usable by web browsers.
+//
+// Copyright 2019 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef WEBFONT_H
+#define WEBFONT_H
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "GfxFont.h"
+
+class FoFiTrueType;
+class FoFiType1C;
+class XRef;
+
+//------------------------------------------------------------------------
+
+class WebFont {
+public:
+
+ WebFont(GfxFont *gfxFontA, XRef *xref);
+
+ ~WebFont();
+
+ // Returns true if the font is, or can be converted to, a TrueType
+ // font.
+ GBool canWriteTTF();
+
+ // Returns true if the font is, or can be converted to, an OpenType
+ // font.
+ GBool canWriteOTF();
+
+ // Write a TrueType (.ttf) file to [fontFilePath]. This can only be
+ // called if canWriteTTF() returns true. Returns true on success.
+ GBool writeTTF(const char *fontFilePath);
+
+ // Write an OpenType (.otf) file to [fontFilePath]. This can only
+ // be called if canWriteOTF() returns true. Returns true on
+ // success.
+ GBool writeOTF(const char *fontFilePath);
+
+private:
+
+ Gushort *makeType1CWidths(int *codeToGID, int nCodes, int *nWidths);
+ Gushort *makeCIDType0CWidths(int *codeToGID, int nCodes, int *nWidths);
+ Guchar *makeUnicodeCmapTable(int *codeToGID, int nCodes,
+ int *unicodeCmapLength);
+ int *makeUnicodeToGID(int *codeToGID, int nCodes, int *unicodeToGIDLength);
+
+ GfxFont *gfxFont;
+ char *fontBuf;
+ int fontLength;
+ FoFiTrueType *ffTrueType;
+ FoFiType1C *ffType1C;
+ GBool isOpenType;
+};
+
+#endif
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.cc
index 18534401946..3b88270c798 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.cc
@@ -25,6 +25,7 @@
#include "GfxFont.h"
#include "Zoox.h"
#include "PDF417Barcode.h"
+#include "UTF8.h"
#include "XFAForm.h"
#ifdef _WIN32
@@ -446,7 +447,7 @@ XFAForm *XFAForm::load(PDFDoc *docA, Catalog *catalog,
fullNameIdx = new GHash();
xfaForm->scanNode(tmpl, name, fullName, gFalse, NULL,
nameCount, nameIdx, fullNameCount, fullNameIdx,
- catalog);
+ NULL, catalog);
delete nameCount;
delete nameIdx;
delete fullNameCount;
@@ -504,11 +505,6 @@ XFAForm::~XFAForm() {
gfree(pageOffsetY);
}
-//~ need to handle exclGroup
-//~ - fields in an exclGroup may/must(?) not have names
-//~ - each field has an items element with the the value when that
-//~ field is selected
-
// Scan <elem>. Constructs the node's name and full name. If <elem>
// is a field, creates an XFAFormField; else scans <elem>'s children.
void XFAForm::scanNode(ZxElement *elem,
@@ -516,7 +512,7 @@ void XFAForm::scanNode(ZxElement *elem,
GBool inPageSet, XFATableInfo *tableInfo,
GHash *nameCount, GHash *nameIdx,
GHash *fullNameCount, GHash *fullNameIdx,
- Catalog *catalog) {
+ GString *exclGroupName, Catalog *catalog) {
ZxAttr *attr;
GString *name, *fullName, *namePart, *fullNamePart;
GHash *childNameCount, *childNameIdx, *childFullNameCount, *childFullNameIdx;
@@ -575,7 +571,8 @@ void XFAForm::scanNode(ZxElement *elem,
}
if (elem->isElement("field")) {
- scanField(elem, name, fullName, inPageSet, tableInfo, colSpan, catalog);
+ scanField(elem, name, fullName, exclGroupName,
+ inPageSet, tableInfo, colSpan, catalog);
} else {
scanNonField(elem, name, fullName, inPageSet, tableInfo, colSpan,
childNameCount, childNameIdx,
@@ -652,7 +649,7 @@ void XFAForm::scanFullNames(ZxElement *elem, GHash *fullNameCount) {
}
void XFAForm::scanField(ZxElement *elem, GString *name, GString *fullName,
- GBool inPageSet,
+ GString *exclGroupName, GBool inPageSet,
XFATableInfo *tableInfo, int colSpan,
Catalog *catalog) {
double xSubOffset, ySubOffset, columnWidth, rowHeight;
@@ -679,6 +676,8 @@ void XFAForm::scanField(ZxElement *elem, GString *name, GString *fullName,
}
fields->append(new XFAFormField(this, elem, name->copy(), fullName->copy(),
+ exclGroupName ? exclGroupName->copy()
+ : (GString *)NULL,
curPageNum, curXOffset, curYOffset,
columnWidth, rowHeight));
@@ -699,6 +698,7 @@ void XFAForm::scanNonField(ZxElement *elem, GString *name, GString *fullName,
ZxNode *child;
ZxAttr *attr;
PDFRectangle *box;
+ GString *exclGroupName;
double xSubOffset, ySubOffset;
int savedPageNum;
@@ -744,7 +744,8 @@ void XFAForm::scanNonField(ZxElement *elem, GString *name, GString *fullName,
curXOffset += xSubOffset;
curYOffset += ySubOffset;
- } else if (elem->isElement("area")) {
+ } else if (elem->isElement("area") ||
+ elem->isElement("exclGroup")) {
xSubOffset = XFAFormField::getMeasurement(elem->findAttr("x"), 0);
ySubOffset = XFAFormField::getMeasurement(elem->findAttr("y"), 0);
curXOffset += xSubOffset;
@@ -780,11 +781,17 @@ void XFAForm::scanNonField(ZxElement *elem, GString *name, GString *fullName,
}
}
+ if (elem->isElement("exclGroup")) {
+ exclGroupName = name;
+ } else {
+ exclGroupName = NULL;
+ }
+
for (child = elem->getFirstChild(); child; child = child->getNextChild()) {
if (child->isElement()) {
scanNode((ZxElement *)child, name, fullName, inPageSet,
newTableInfo, nameCount, nameIdx, fullNameCount, fullNameIdx,
- catalog);
+ exclGroupName, catalog);
}
}
@@ -871,12 +878,14 @@ FormField *XFAForm::getField(int idx) {
XFAFormField::XFAFormField(XFAForm *xfaFormA, ZxElement *xmlA,
GString *nameA, GString *fullNameA,
+ GString *exclGroupNameA,
int pageNumA, double xOffsetA, double yOffsetA,
double columnWidthA, double rowHeightA) {
xfaForm = xfaFormA;
xml = xmlA;
name = nameA;
fullName = fullNameA;
+ exclGroupName = exclGroupNameA;
pageNum = pageNumA;
xOffset = xOffsetA;
yOffset = yOffsetA;
@@ -887,6 +896,9 @@ XFAFormField::XFAFormField(XFAForm *xfaFormA, ZxElement *xmlA,
XFAFormField::~XFAFormField() {
delete name;
delete fullName;
+ if (exclGroupName) {
+ delete exclGroupName;
+ }
}
int XFAFormField::getPageNum() {
@@ -943,7 +955,9 @@ Unicode *XFAFormField::getValue(int *length) {
s = getFieldValue("text");
break;
} else if (node->isElement("checkButton")) {
- s = getFieldValue("integer");
+ if (!(s = getFieldValue("integer"))) {
+ s = getFieldValue("text");
+ }
break;
} else if (node->isElement("barcode")) {
s = getFieldValue("text");
@@ -1921,6 +1935,22 @@ GString *XFAFormField::getFieldValue(const char *valueChildType) {
}
}
}
+ if (exclGroupName) {
+ p = exclGroupName->getCString();
+ if (xfaForm->xml->getRoot() && !strncmp(p, "form.", 5)) {
+ if ((datasets =
+ xfaForm->xml->getRoot()->findFirstChildElement("xfa:datasets")) &&
+ (data = datasets->findFirstChildElement("xfa:data"))) {
+ elem = findFieldInDatasets(data, p + 5);
+ if (elem &&
+ elem->getFirstChild() &&
+ elem->getFirstChild()->isCharData() &&
+ ((ZxCharData *)elem->getFirstChild())->getData()->getLength() > 0) {
+ return ((ZxCharData *)elem->getFirstChild())->getData();
+ }
+ }
+ }
+ }
// check the <form> element
p = fullName->getCString();
@@ -1955,7 +1985,9 @@ GString *XFAFormField::getFieldValue(const char *valueChildType) {
ZxElement *XFAFormField::findFieldInDatasets(ZxElement *elem, char *partName) {
ZxNode *node;
+ ZxElement *result;
GString *nodeName;
+ char *next;
int curIdx, idx, n;
curIdx = 0;
@@ -1976,11 +2008,21 @@ ZxElement *XFAFormField::findFieldInDatasets(ZxElement *elem, char *partName) {
if (!partName[n]) {
return (ZxElement *)node;
} else if (partName[n] == '.') {
- return findFieldInDatasets((ZxElement *)node, partName + n + 1);
+ if ((result = findFieldInDatasets((ZxElement *)node,
+ partName + n + 1))) {
+ return result;
+ }
+ break;
}
}
}
}
+
+ // search for an "ancestor match"
+ if ((next = strchr(partName, '.'))) {
+ return findFieldInDatasets(elem, next + 1);
+ }
+
return NULL;
}
@@ -2054,14 +2096,26 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
double x, double y, double w, double h,
GBool whiteBackground,
GfxFontDict *fontDict, GString *appearBuf) {
+ GString *text2;
GfxFont *font;
const char *fontTag;
GString *s;
+ Unicode u;
double yTop, xx, yy, tw, charWidth, lineHeight;
double ascent, descent, rectX, rectY, rectW, rectH, blkH;
int nLines, line, i, j, k, c, rectI;
- //~ deal with Unicode text (is it UTF-8?)
+ // convert UTF-8 to Latin1
+ //~ this currently drops all non-Latin1 characters
+ text2 = new GString();
+ i = 0;
+ while (getUTF8(text, &i, &u)) {
+ if (u <= 0xff) {
+ text2->append((char)u);
+ } else {
+ text2->append('?');
+ }
+ }
// find the font
if ((font = findFont(fontDict, fontName, bold, italic))) {
@@ -2093,8 +2147,8 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
if (vAlign == xfaVAlignBottom || vAlign == xfaVAlignMiddle) {
nLines = 0;
i = 0;
- while (i < text->getLength()) {
- getNextLine(text, i, font, fontSize, w, &j, &tw, &k);
+ while (i < text2->getLength()) {
+ getNextLine(text2, i, font, fontSize, w, &j, &tw, &k);
++nLines;
i = k;
}
@@ -2114,9 +2168,9 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
// write a series of lines of text
line = 0;
i = 0;
- while (i < text->getLength()) {
+ while (i < text2->getLength()) {
- getNextLine(text, i, font, fontSize, w, &j, &tw, &k);
+ getNextLine(text2, i, font, fontSize, w, &j, &tw, &k);
if (tw > rectW) {
rectW = tw;
}
@@ -2140,7 +2194,7 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", xx, yy);
appearBuf->append('(');
for (; i < j; ++i) {
- c = text->getChar(i) & 0xff;
+ c = text2->getChar(i) & 0xff;
if (c == '(' || c == ')' || c == '\\') {
appearBuf->append('\\');
appearBuf->append((char)c);
@@ -2172,13 +2226,13 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
xx = x;
break;
case xfaHAlignCenter:
- xx = x + (int)(0.5 * (combCells - text->getLength())) * tw;
+ xx = x + (int)(0.5 * (combCells - text2->getLength())) * tw;
break;
case xfaHAlignRight:
- xx = x + w - text->getLength() * tw;
+ xx = x + w - text2->getLength() * tw;
break;
}
- rectW = text->getLength() * tw;
+ rectW = text2->getLength() * tw;
switch (vAlign) {
case xfaVAlignTop:
default:
@@ -2195,8 +2249,8 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
rectH = ascent - descent;
// write the text string
- for (i = 0; i < text->getLength(); ++i) {
- c = text->getChar(i) & 0xff;
+ for (i = 0; i < text2->getLength(); ++i) {
+ c = text2->getChar(i) & 0xff;
if (font && !font->isCIDFont()) {
charWidth = fontSize * ((Gfx8BitFont *)font)->getWidth((Guchar)c);
appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n",
@@ -2223,12 +2277,12 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
// compute string width
if (font && !font->isCIDFont()) {
tw = 0;
- for (i = 0; i < text->getLength(); ++i) {
- tw += ((Gfx8BitFont *)font)->getWidth(text->getChar(i));
+ for (i = 0; i < text2->getLength(); ++i) {
+ tw += ((Gfx8BitFont *)font)->getWidth(text2->getChar(i));
}
} else {
// otherwise, make a crude estimate
- tw = text->getLength() * 0.5;
+ tw = text2->getLength() * 0.5;
}
tw *= fontSize;
rectW = tw;
@@ -2264,8 +2318,8 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
// write the text string
appearBuf->append('(');
- for (i = 0; i < text->getLength(); ++i) {
- c = text->getChar(i) & 0xff;
+ for (i = 0; i < text2->getLength(); ++i) {
+ c = text2->getChar(i) & 0xff;
if (c == '(' || c == ')' || c == '\\') {
appearBuf->append('\\');
appearBuf->append((char)c);
@@ -2304,6 +2358,8 @@ void XFAFormField::drawText(GString *text, GBool multiLine, int combCells,
appearBuf->insert(rectI, s);
delete s;
}
+
+ delete text2;
}
// Searches <fontDict> for a font matching(<fontName>, <bold>,
@@ -2734,7 +2790,7 @@ GString *XFAFormField::pictureFormatDateTime(GString *value, GString *picture) {
u <<= 4;
if (c >= '0' && c <= '9') {
u += c - '0';
- } else if (c >= 'a' && c <= 'F') {
+ } else if (c >= 'a' && c <= 'f') {
u += c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
u += c - 'A' + 10;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.h b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.h
index 8e0b363386a..2f56e728a98 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAForm.h
@@ -63,11 +63,11 @@ private:
GBool inPageSet, XFATableInfo *tableInfo,
GHash *nameCount, GHash *nameIdx,
GHash *fullNameCount, GHash *fullNameIdx,
- Catalog *catalog);
+ GString *exclGroupName, Catalog *catalog);
void scanNames(ZxElement *elem, GHash *nameCount);
void scanFullNames(ZxElement *elem, GHash *fullNameCount);
void scanField(ZxElement *elem, GString *name, GString *fullName,
- GBool inPageSet,
+ GString *exclGroupName, GBool inPageSet,
XFATableInfo *tableInfo, int colSpan,
Catalog *catalog);
void scanNonField(ZxElement *elem, GString *name, GString *fullName,
@@ -102,7 +102,7 @@ class XFAFormField: public FormField {
public:
XFAFormField(XFAForm *xfaFormA, ZxElement *xmlA,
- GString *nameA, GString *fullNameA,
+ GString *nameA, GString *fullNameA, GString *exclGroupNameA,
int pageNumA, double xOffsetA, double yOffsetA,
double columnWidthA, double rowHeightA);
@@ -166,6 +166,7 @@ private:
ZxElement *xml;
GString *name;
GString *fullName;
+ GString *exclGroupName;
int pageNum;
double xOffset, yOffset;
double columnWidth; // column width, if this field is in a
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/config.h b/Build/source/libs/xpdf/xpdf-src/xpdf/config.h
index f5c566e9696..3dbed2ae93c 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/config.h
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/config.h
@@ -14,14 +14,14 @@
//------------------------------------------------------------------------
// xpdf version
-#define xpdfVersion "4.01.01"
-#define xpdfVersionNum 4.01
+#define xpdfVersion "4.02"
+#define xpdfVersionNum 4.02
#define xpdfMajorVersion 4
-#define xpdfMinorVersion 1
-#define xpdfUpdateVersion 1
+#define xpdfMinorVersion 2
+#define xpdfUpdateVersion 0
#define xpdfMajorVersionStr "4"
-#define xpdfMinorVersionStr "1"
-#define xpdfUpdateVersionStr "1"
+#define xpdfMinorVersionStr "2"
+#define xpdfUpdateVersionStr "0"
// supported PDF version
#define supportedPDFVersionStr "2.0"
@@ -31,7 +31,7 @@
#define xpdfCopyright "Copyright 1996-2019 Glyph & Cog, LLC"
// Windows resource file stuff
-#define winxpdfVersion "WinXpdf 4.01.01"
+#define winxpdfVersion "WinXpdf 4.02"
#define xpdfCopyrightAmp "Copyright 1996-2019 Glyph && Cog, LLC"
//------------------------------------------------------------------------
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc
index 7df38cc11d7..22298b138c5 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc
@@ -159,11 +159,11 @@ int main(int argc, char *argv[]) {
// scan the fonts
if (showFontLoc || showFontLocPS) {
- printf("name type emb sub uni prob object ID location\n");
- printf("------------------------------------ ----------------- --- --- --- ---- --------- --------\n");
+ printf("name type emb sub uni prob object ID location\n");
+ printf("---------------------------------------------- ----------------- --- --- --- ---- --------- --------\n");
} else {
- printf("name type emb sub uni prob object ID\n");
- printf("------------------------------------ ----------------- --- --- --- ---- ---------\n");
+ printf("name type emb sub uni prob object ID\n");
+ printf("---------------------------------------------- ----------------- --- --- --- ---- ---------\n");
}
fonts = NULL;
fontsLen = fontsSize = 0;
@@ -302,7 +302,7 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) {
resDict->lookupNF("ExtGState", &gsDict1);
if (checkObject(&gsDict1, &gsDict2) && gsDict2.isDict()) {
for (i = 0; i < gsDict2.dictGetLength(); ++i) {
- gsDict1.dictGetValNF(i, &gs1);
+ gsDict2.dictGetValNF(i, &gs1);
if (checkObject(&gs1, &gs2) && gs2.isDict()) {
gs2.dictLookupNF("SMask", &smask1);
if (checkObject(&smask1, &smask2) && smask2.isDict()) {
@@ -375,7 +375,7 @@ static void scanFont(GfxFont *font, PDFDoc *doc) {
}
// print the font info
- printf("%-36s %-17s %-3s %-3s %-3s %-4s",
+ printf("%-46s %-17s %-3s %-3s %-3s %-4s",
name ? name->getCString() : "[none]",
fontTypeNames[font->getType()],
emb ? "yes" : "no",
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc
index b458202effb..29095509bed 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc
@@ -171,6 +171,7 @@ int main(int argc, char *argv[]) {
htmlGen->setZoom(zoom);
htmlGen->setDrawInvisibleText(!skipInvisible);
htmlGen->setAllTextInvisible(allInvisible);
+ htmlGen->setExtractFontFiles(gTrue);
htmlGen->startDoc(doc);
// convert the pages
@@ -191,7 +192,7 @@ int main(int argc, char *argv[]) {
goto err2;
}
pngURL = GString::format("page{0:d}.png", pg);
- err = htmlGen->convertPage(pg, pngURL->getCString(),
+ err = htmlGen->convertPage(pg, pngURL->getCString(), htmlDir,
&writeToFile, htmlFile,
&writeToFile, pngFile);
delete pngURL;
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc
index 720066d32a8..64a0087c7d3 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc
@@ -352,6 +352,7 @@ static void writePNGData(png_structp png, SplashBitmap *bitmap) {
+
static void finishPNG(png_structp *png, png_infop *pngInfo) {
if (setjmp(png_jmpbuf(*png))) {
exit(2);
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc
index 0496c6442ff..aa74fb68612 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc
@@ -50,6 +50,10 @@ static char textEncName[128] = "";
static char textEOL[16] = "";
static GBool noPageBreaks = gFalse;
static GBool insertBOM = gFalse;
+static double marginLeft = 0;
+static double marginRight = 0;
+static double marginTop = 0;
+static double marginBottom = 0;
static char ownerPassword[33] = "\001";
static char userPassword[33] = "\001";
static GBool quiet = gFalse;
@@ -88,6 +92,14 @@ static ArgDesc argDesc[] = {
"don't insert page breaks between pages"},
{"-bom", argFlag, &insertBOM, 0,
"insert a Unicode BOM at the start of the text file"},
+ {"-marginl", argFP, &marginLeft, 0,
+ "left page margin"},
+ {"-marginr", argFP, &marginRight, 0,
+ "right page margin"},
+ {"-margint", argFP, &marginTop, 0,
+ "top page margin"},
+ {"-marginb", argFP, &marginBottom, 0,
+ "bottom page margin"},
{"-opw", argString, ownerPassword, sizeof(ownerPassword),
"owner password (for encrypted files)"},
{"-upw", argString, userPassword, sizeof(userPassword),
@@ -247,6 +259,10 @@ int main(int argc, char *argv[]) {
textOutControl.clipText = clipText;
textOutControl.discardDiagonalText = discardDiag;
textOutControl.insertBOM = insertBOM;
+ textOutControl.marginLeft = marginLeft;
+ textOutControl.marginRight = marginRight;
+ textOutControl.marginTop = marginTop;
+ textOutControl.marginBottom = marginBottom;
textOut = new TextOutputDev(textFileName->getCString(), &textOutControl,
gFalse);
if (textOut->isOk()) {