diff options
105 files changed, 5031 insertions, 1570 deletions
diff --git a/Build/source/libs/README b/Build/source/libs/README index 4f4ef10fccb..5b46bf55f05 100644 --- a/Build/source/libs/README +++ b/Build/source/libs/README @@ -58,7 +58,7 @@ pplib 2.05.0 - checked 21apr20 teckit 2.5.11 - checked 09nov21 https://github.com/silnrsi/teckit/archive/2.5.11.tar.gz -xpdf 4.03 - checked 01feb21 +xpdf 4.04 - checked 24apr22 http://www.xpdfreader.com/download.html with modifications for pdftex diff --git a/Build/source/libs/xpdf/ChangeLog b/Build/source/libs/xpdf/ChangeLog index 981ef4a53cf..ad36056044e 100644 --- a/Build/source/libs/xpdf/ChangeLog +++ b/Build/source/libs/xpdf/ChangeLog @@ -1,3 +1,8 @@ +2022-04-24 Akira Kakuto <kakuto@jcom.zaq.ne.jp> + + * Import xpdf-4.04. + * version.ac: Adjust. + 2021-05-10 Karl Berry <karl@freefriends.org> * xpdf-src/xpdf/Error.cc (error): label error messages diff --git a/Build/source/libs/xpdf/TLpatches/ChangeLog b/Build/source/libs/xpdf/TLpatches/ChangeLog index c0fed972499..1b2e8497313 100644 --- a/Build/source/libs/xpdf/TLpatches/ChangeLog +++ b/Build/source/libs/xpdf/TLpatches/ChangeLog @@ -1,3 +1,7 @@ +2022-04-24 Akira Kakuto <kakuto@jcom.zaq.ne.jp> + + * patch-bunched: Adjust. + 2021-02-01 Akira Kakuto <kakuto@w32tex.org> * patch-bunched: Adjust. diff --git a/Build/source/libs/xpdf/TLpatches/TL-Changes b/Build/source/libs/xpdf/TLpatches/TL-Changes index c0b5e4aeb54..aab26569f98 100644 --- a/Build/source/libs/xpdf/TLpatches/TL-Changes +++ b/Build/source/libs/xpdf/TLpatches/TL-Changes @@ -1,4 +1,4 @@ -Changes applied to the xpdf-4.03/ tree as obtained from: +Changes applied to the xpdf-4.04/ tree as obtained from: http://www.xpdfreader.com/download.html Removed: diff --git a/Build/source/libs/xpdf/TLpatches/patch-bunched b/Build/source/libs/xpdf/TLpatches/patch-bunched index 07b3f05a983..bb36d99d8f7 100644 --- a/Build/source/libs/xpdf/TLpatches/patch-bunched +++ b/Build/source/libs/xpdf/TLpatches/patch-bunched @@ -1,6 +1,6 @@ -diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc ---- xpdf-4.03/goo/gfile.cc Thu Jan 28 07:23:51 2021 -+++ xpdf-src/goo/gfile.cc Mon Feb 01 13:13:50 2021 +diff -ur xpdf-4.04/goo/gfile.cc xpdf-src/goo/gfile.cc +--- xpdf-4.04/goo/gfile.cc Tue Apr 19 06:11:23 2022 ++++ xpdf-src/goo/gfile.cc Sun Apr 24 10:45:35 2022 @@ -7,6 +7,9 @@ // Copyright 1996-2003 Glyph & Cog, LLC // @@ -11,19 +11,7 @@ diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc #include <aconf.h> -@@ -56,7 +59,11 @@ - char *s; - GString *ret; - -+#ifdef _WIN32 -+ if ((s = getenv("USERPROFILE"))) -+#else - if ((s = getenv("HOME"))) -+#endif - ret = new GString(s); - else - ret = new GString("."); -@@ -405,6 +412,7 @@ +@@ -429,6 +432,7 @@ #endif } @@ -31,7 +19,7 @@ diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext) { #if defined(_WIN32) -@@ -519,10 +527,11 @@ +@@ -543,6 +547,7 @@ return gTrue; #endif } @@ -39,29 +27,24 @@ diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc GBool createDir(char *path, int mode) { #ifdef _WIN32 -- return !mkdir(path); -+ return !_mkdir(path); - #else - return !mkdir(path, mode); - #endif -@@ -602,6 +611,8 @@ +@@ -626,6 +631,8 @@ FILE *openFile(const char *path, const char *mode) { #if defined(_WIN32) + return fopen(path, mode); +#if 0 - wchar_t wPath[_MAX_PATH + 1]; + wchar_t wPath[winMaxLongPath + 1]; wchar_t wMode[8]; int i; -@@ -613,6 +624,7 @@ +@@ -637,6 +644,7 @@ wMode[i] = (wchar_t)0; - readWindowsShortcut(wPath, _MAX_PATH + 1); + readWindowsShortcut(wPath, winMaxLongPath + 1); return _wfopen(wPath, wMode); +#endif /* 0 */ #elif defined(VMS) return fopen(path, mode, "ctx=stm"); #else -@@ -620,6 +632,7 @@ +@@ -644,6 +652,7 @@ #endif } @@ -69,7 +52,7 @@ diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc #ifdef _WIN32 void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) { size_t n = wcslen(wPath); -@@ -665,11 +678,11 @@ +@@ -689,11 +698,15 @@ wcscpy(wPath, target); } #endif @@ -77,13 +60,15 @@ diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc int makeDir(const char *path, int mode) { #ifdef _WIN32 -- wchar_t wPath[_MAX_PATH + 1]; -- return _wmkdir(fileNameToUCS2(path, wPath, sizeof(wPath) / sizeof(wchar_t))); ++ /* + wchar_t wPath[winMaxLongPath + 1]; + return _wmkdir(fileNameToUCS2(path, wPath, winMaxLongPath + 1)); ++ */ + return _mkdir(path); #else return mkdir(path, (mode_t)mode); #endif -@@ -728,6 +741,7 @@ +@@ -752,6 +765,7 @@ #endif } @@ -91,28 +76,29 @@ diff -ur xpdf-4.03/goo/gfile.cc xpdf-src/goo/gfile.cc void fixCommandLine(int *argc, char **argv[]) { #ifdef _WIN32 int argcw; -@@ -753,3 +767,4 @@ +@@ -777,3 +791,4 @@ LocalFree(argvw); #endif } +#endif /* !PDF_PARSER_ONLY */ -diff -ur xpdf-4.03/goo/gfile.h xpdf-src/goo/gfile.h ---- xpdf-4.03/goo/gfile.h Thu Jan 28 07:23:51 2021 -+++ xpdf-src/goo/gfile.h Mon Feb 01 13:14:50 2021 -@@ -91,12 +91,6 @@ +diff -ur xpdf-4.04/goo/gfile.h xpdf-src/goo/gfile.h +--- xpdf-4.04/goo/gfile.h Tue Apr 19 06:11:23 2022 ++++ xpdf-src/goo/gfile.h Sun Apr 24 10:48:58 2022 +@@ -100,11 +100,13 @@ // UCS-2 and calls _wfopen(). On other OSes, this simply calls fopen(). extern FILE *openFile(const char *path, const char *mode); --#ifdef _WIN32 --// If [wPath] is a Windows shortcut (.lnk file), read the target path --// and store it back into [wPath]. --extern void readWindowsShortcut(wchar_t *wPath, size_t wPathSize); --#endif -- ++#if 0 + #ifdef _WIN32 + // If [wPath] is a Windows shortcut (.lnk file), read the target path + // and store it back into [wPath]. + extern void readWindowsShortcut(wchar_t *wPath, size_t wPathSize); + #endif ++#endif /* 0 */ + // Create a directory. On Windows, this converts the path from UTF-8 // to UCS-2 and calls _wmkdir(), ignoring the mode argument. On other - // OSes, this simply calls mkdir(). -@@ -130,6 +124,8 @@ +@@ -139,6 +141,8 @@ // On Windows, this gets the Unicode command line and converts it to // UTF-8. On other systems, this is a nop. @@ -121,20 +107,30 @@ diff -ur xpdf-4.03/goo/gfile.h xpdf-src/goo/gfile.h +#endif /* !PDF_PARSER_ONLY */ #endif -diff -ur xpdf-4.03/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc ---- xpdf-4.03/xpdf/GlobalParams.cc Thu Jan 28 07:23:51 2021 -+++ xpdf-src/xpdf/GlobalParams.cc Mon Feb 01 12:20:24 2021 -@@ -5,6 +5,9 @@ - // Copyright 2001-2003 Glyph & Cog, LLC - // - //======================================================================== -+// Modified for TeX Live by Peter Breitenlohner <tex-live@tug.org> -+// See top-level ChangeLog for a list of all modifications -+//======================================================================== - - #include <aconf.h> - -@@ -44,8 +47,12 @@ +diff -ur xpdf-4.04/xpdf/Error.cc xpdf-src/xpdf/Error.cc +--- xpdf-4.04/xpdf/Error.cc Tue Apr 19 06:11:23 2022 ++++ xpdf-src/xpdf/Error.cc Sun Apr 24 11:27:58 2022 +@@ -77,11 +77,14 @@ + (*errorCbk)(errorCbkData, category, (int)pos, sanitized->getCString()); + } else { + fflush(stdout); ++ /* Label the error messages for pdftex's use as libxpdf. ++ It would be cleaner to use the callback feature, but seems ++ like too much trouble at this late date. */ + if (pos >= 0) { +- fprintf(stderr, "%s (%d): %s\n", ++ fprintf(stderr, "\nlibxpdf: %s (%d): %s\n", + errorCategoryNames[category], (int)pos, sanitized->getCString()); + } else { +- fprintf(stderr, "%s: %s\n", ++ fprintf(stderr, "\nlibxpdf: %s: %s\n", + errorCategoryNames[category], sanitized->getCString()); + } + fflush(stderr); +diff -ur xpdf-4.04/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc +--- xpdf-4.04/xpdf/GlobalParams.cc Tue Apr 19 06:11:23 2022 ++++ xpdf-src/xpdf/GlobalParams.cc Sun Apr 24 11:07:30 2022 +@@ -44,8 +44,12 @@ #include "GlobalParams.h" #ifdef _WIN32 @@ -149,7 +145,7 @@ diff -ur xpdf-4.03/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc #endif #if MULTITHREADED -@@ -787,6 +794,7 @@ +@@ -794,6 +798,7 @@ f = NULL; fileName = NULL; if (cfgFileName && cfgFileName[0]) { @@ -157,7 +153,7 @@ diff -ur xpdf-4.03/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc fileName = new GString(cfgFileName); if (!(f = fopen(fileName->getCString(), "r"))) { delete fileName; -@@ -819,6 +827,7 @@ +@@ -826,6 +831,7 @@ parseFile(fileName, f); delete fileName; fclose(f); @@ -165,7 +161,7 @@ diff -ur xpdf-4.03/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc } } -@@ -2358,8 +2367,11 @@ +@@ -2378,8 +2384,11 @@ base14->fontNum, displayFontTab[i].obliqueFactor)); } else { @@ -177,9 +173,9 @@ diff -ur xpdf-4.03/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc } } } -diff -ur xpdf-4.03/xpdf/GlobalParams.h xpdf-src/xpdf/GlobalParams.h ---- xpdf-4.03/xpdf/GlobalParams.h Thu Jan 28 07:23:51 2021 -+++ xpdf-src/xpdf/GlobalParams.h Mon Feb 01 12:23:07 2021 +diff -ur xpdf-4.04/xpdf/GlobalParams.h xpdf-src/xpdf/GlobalParams.h +--- xpdf-4.04/xpdf/GlobalParams.h Tue Apr 19 06:11:23 2022 ++++ xpdf-src/xpdf/GlobalParams.h Sun Apr 24 11:08:50 2022 @@ -5,6 +5,9 @@ // Copyright 2001-2003 Glyph & Cog, LLC // @@ -199,9 +195,9 @@ diff -ur xpdf-4.03/xpdf/GlobalParams.h xpdf-src/xpdf/GlobalParams.h ~GlobalParams(); -diff -ur xpdf-4.03/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc ---- xpdf-4.03/xpdf/PDFDoc.cc Thu Jan 28 07:23:51 2021 -+++ xpdf-src/xpdf/PDFDoc.cc Mon Feb 01 13:01:20 2021 +diff -ur xpdf-4.04/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc +--- xpdf-4.04/xpdf/PDFDoc.cc Tue Apr 19 06:11:23 2022 ++++ xpdf-src/xpdf/PDFDoc.cc Sun Apr 24 11:19:50 2022 @@ -114,6 +114,7 @@ ok = setup(ownerPassword, userPassword); } @@ -210,7 +206,7 @@ diff -ur xpdf-4.03/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc #ifdef _WIN32 PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, GString *userPassword, PDFCore *coreA) { -@@ -161,23 +162,29 @@ +@@ -161,23 +162,28 @@ ok = setup(ownerPassword, userPassword); } #endif @@ -218,29 +214,29 @@ diff -ur xpdf-4.03/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword, GString *userPassword, PDFCore *coreA) { -+/* ++#if 0 #ifdef _WIN32 OSVERSIONINFO version; #endif -+*/ ++#endif /* 0 */ Object obj; -+/* ++#if 0 #ifdef _WIN32 Unicode u; int i, j; #endif -+*/ - +- ++#endif /* 0 */ init(coreA); fileName = new GString(fileNameA); #if defined(_WIN32) +#if 0 - wchar_t wPath[MAX_PATH + 1]; + wchar_t wPath[winMaxLongPath + 1]; i = 0; j = 0; -@@ -197,8 +204,11 @@ +@@ -197,8 +203,11 @@ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { file = _wfopen(fileNameU, wfopenReadMode); } else { @@ -252,34 +248,34 @@ diff -ur xpdf-4.03/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc #elif defined(VMS) file = fopen(fileName->getCString(), fopenReadMode, "ctx=stm"); #else -@@ -603,6 +613,7 @@ +@@ -608,6 +617,7 @@ GBool ret; // NB: _wfopen is only available in NT -+/* ++#if 0 version.dwOSVersionInfoSize = sizeof(version); GetVersionEx(&version); if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { -@@ -612,12 +623,15 @@ +@@ -617,12 +627,15 @@ path2w[i] = 0; f = _wfopen(path2w, L"wb"); } else { -+*/ - for (i = 0; i < pathLen && i < _MAX_PATH; ++i) { ++#endif /* 0 */ + for (i = 0; i < pathLen && i < MAX_PATH; ++i) { path2c[i] = (char)path[i]; } path2c[i] = 0; f = fopen(path2c, "wb"); -+/* ++#if 0 } -+*/ ++#endif /* 0 */ if (!f) { return gFalse; } -diff -ur xpdf-4.03/xpdf/Page.cc xpdf-src/xpdf/Page.cc ---- xpdf-4.03/xpdf/Page.cc Thu Jan 28 07:23:51 2021 -+++ xpdf-src/xpdf/Page.cc Mon Feb 01 12:31:27 2021 -@@ -485,9 +485,9 @@ +diff -ur xpdf-4.04/xpdf/Page.cc xpdf-src/xpdf/Page.cc +--- xpdf-4.04/xpdf/Page.cc Tue Apr 19 06:11:23 2022 ++++ xpdf-src/xpdf/Page.cc Sun Apr 24 11:22:49 2022 +@@ -531,9 +531,9 @@ delete links; } @@ -290,16 +286,16 @@ diff -ur xpdf-4.03/xpdf/Page.cc xpdf-src/xpdf/Page.cc GfxState *state; int i; -@@ -504,5 +504,5 @@ +@@ -550,5 +550,5 @@ ctm[i] = state->getCTM()[i]; } delete state; -} #endif +} -diff -ur xpdf-4.03/xpdf/config.h xpdf-src/xpdf/config.h ---- xpdf-4.03/xpdf/config.h Thu Jan 28 07:23:52 2021 -+++ xpdf-src/xpdf/config.h Mon Feb 01 12:34:28 2021 +diff -ur xpdf-4.04/xpdf/config.h xpdf-src/xpdf/config.h +--- xpdf-4.04/xpdf/config.h Tue Apr 19 06:11:23 2022 ++++ xpdf-src/xpdf/config.h Sun Apr 24 11:24:23 2022 @@ -80,11 +80,6 @@ // popen //------------------------------------------------------------------------ @@ -312,23 +308,3 @@ diff -ur xpdf-4.03/xpdf/config.h xpdf-src/xpdf/config.h #if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(_WIN32) || defined(__DJGPP__) #define POPEN_READ_MODE "rb" #else -diff -ur xpdf-4.03/xpdf/Error.cc xpdf-src/xpdf/Error.cc ---- xpdf-4.03/xpdf/Error.cc Thu Jan 28 07:23:52 2021 -+++ xpdf-src/xpdf/Error.cc Mon Feb 01 12:34:28 2021 -@@ -77,11 +77,14 @@ - (*errorCbk)(errorCbkData, category, (int)pos, sanitized->getCString()); - } else { - fflush(stdout); -+ /* Label the error messages for pdftex's use as libxpdf. -+ It would be cleaner to use the callback feature, but seems -+ like too much trouble at this late date. */ - if (pos >= 0) { -- fprintf(stderr, "%s (%d): %s\n", -+ fprintf(stderr, "\nlibxpdf: %s (%d): %s\n", - errorCategoryNames[category], (int)pos, sanitized->getCString()); - } else { -- fprintf(stderr, "%s: %s\n", -+ fprintf(stderr, "\nlibxpdf: %s: %s\n", - errorCategoryNames[category], sanitized->getCString()); - } - fflush(stderr); diff --git a/Build/source/libs/xpdf/configure b/Build/source/libs/xpdf/configure index fe781453b03..2a2d1b60d43 100755 --- a/Build/source/libs/xpdf/configure +++ b/Build/source/libs/xpdf/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for xpdf (TeX Live) 4.03. +# Generated by GNU Autoconf 2.71 for xpdf (TeX Live) 4.04. # # Report bugs to <tex-k@tug.org>. # @@ -610,8 +610,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='xpdf (TeX Live)' PACKAGE_TARNAME='xpdf--tex-live-' -PACKAGE_VERSION='4.03' -PACKAGE_STRING='xpdf (TeX Live) 4.03' +PACKAGE_VERSION='4.04' +PACKAGE_STRING='xpdf (TeX Live) 4.04' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' @@ -1324,7 +1324,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures xpdf (TeX Live) 4.03 to adapt to many kinds of systems. +\`configure' configures xpdf (TeX Live) 4.04 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1391,7 +1391,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of xpdf (TeX Live) 4.03:";; + short | recursive ) echo "Configuration of xpdf (TeX Live) 4.04:";; esac cat <<\_ACEOF @@ -1495,7 +1495,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -xpdf (TeX Live) configure 4.03 +xpdf (TeX Live) configure 4.04 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -1752,7 +1752,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by xpdf (TeX Live) $as_me 4.03, which was +It was created by xpdf (TeX Live) $as_me 4.04, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -4511,7 +4511,7 @@ fi # Define the identity of the package. PACKAGE='xpdf--tex-live-' - VERSION='4.03' + VERSION='4.04' # Some tools Automake needs. @@ -7419,7 +7419,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by xpdf (TeX Live) $as_me 4.03, which was +This file was extended by xpdf (TeX Live) $as_me 4.04, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7491,7 +7491,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -xpdf (TeX Live) config.status 4.03 +xpdf (TeX Live) config.status 4.04 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/xpdf/version.ac b/Build/source/libs/xpdf/version.ac index 64e2f3e635e..9e02a92b491 100644 --- a/Build/source/libs/xpdf/version.ac +++ b/Build/source/libs/xpdf/version.ac @@ -8,4 +8,4 @@ dnl dnl -------------------------------------------------------- dnl dnl m4-include this file to define the current xpdf version -m4_define([xpdf_version], [4.03]) +m4_define([xpdf_version], [4.04]) diff --git a/Build/source/libs/xpdf/xpdf-src/ANNOUNCE b/Build/source/libs/xpdf/xpdf-src/ANNOUNCE index e070ad95d5b..c20dcaf47ae 100644 --- a/Build/source/libs/xpdf/xpdf-src/ANNOUNCE +++ b/Build/source/libs/xpdf/xpdf-src/ANNOUNCE @@ -1,4 +1,4 @@ -Subject: ANNOUNCE: Xpdf 4.03 - a PDF viewer and related tools +Subject: ANNOUNCE: Xpdf 4.04 - a PDF viewer and related tools Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the open source Portable Document Format (PDF) viewer. The Xpdf project @@ -10,7 +10,7 @@ non-graphical components (pdftops, pdftotext, etc.) run on Linux, Unix, Windows, MacOSX, and pretty much any other system with a decent C++ compiler. -4.03 is primarily a bug fix release. There are some new features: +4.04 is primarily a bug fix release. There are some new features: * XpdfReader improvements: - Implemented selection extension via shift-click, and word/line diff --git a/Build/source/libs/xpdf/xpdf-src/CHANGES b/Build/source/libs/xpdf/xpdf-src/CHANGES index f2dccc095fd..564aff32b4f 100644 --- a/Build/source/libs/xpdf/xpdf-src/CHANGES +++ b/Build/source/libs/xpdf/xpdf-src/CHANGES @@ -2740,3 +2740,73 @@ Check for invalid AcroForm ListBox field top index. [Thanks to Chengbin for the bug report.] Check for invalid mesh shading parameters. [Thanks to Chengbin for the bug report.] + +4.04 (2022-apr-18) +------------------ +When closing a file, save the current page number in ~/.xpdf.pages, + and restore it next time the file is opened. This can be disabled + with "savePageNumbers no" in your xpdfrc file. +Allow the tab list to be reordered, using drag-and-drop. +Added a document information dialog, with metadata and fonts, to xpdf. +Pdftohtml now generates HTML links for URI links anchored on text. +Added the useTrueTypeUnicodeMapping xpdfrc setting. +Added the 'enableXFA' xpdfrc setting back: if set to 'no', xpdf will + not read an XFA form, meaning all form info comes from the AcroForm. +Add support for long paths on Windows 10. +Added the "-formfields" option to pdftohtml. +Added the "-embedbackground" and "-embedfonts" options to pdftohtml. +Added the "-vstretch" option to pdftohtml. +Added the "-verbose" flag to pdfimages, pdftohtml, pdftopng, pdftoppm, + pdftops, and pdftotext. +Added the showAttachmentsPane, showLayersPane, and showOutlinePane + commands. +Added the 'openFile2' command to xpdf. +Added the showMenuBar, hideMenuBar, and toggleMenuBar commands to + xpdf. +Rearrange file names in the tab list to "foo.pdf [/full/path/]", to + improve the usability of the (narrow) tab list. +Added the 'imageMaskAntialias' xpdfrc setting. +Added the '-table' switch to pdftohtml. +Fixed a couple of progression order bugs in the JPEG 2000 decoder. + [Thanks to shellway for the bug reports.] +Fixed a problem with subsampled pixel index computations in the JPEG + 2000 decoder. [Thanks to shellway for the bug report.] +Fixed a couple of memory leaks triggered by fuzzed PDF files. [Thanks + to shellway for the bug report.] +Changed pdftohtml to generate spans with 'class=' instead of 'id=', so + there aren't duplicate ids. Also removed the unused id in the + background img element. +Optimized SplashOutputDev::drawTilingPattern for the case where the + tile is much larger than the area being drawn (i.e., the clipping + bbox). In this case, we can render just the needed portion of the + tile. +Added a missing zero check for precinct size in the JPEG 2000 decoder. + [Thanks to shellway for the bug report.] +Added a missing null check in the XFA form scanner. [Thanks to Taolaw + for the bug report.] +Deal with xref streams that include a free entry with gen=0xffffffff. +Fixed a problematic corner case in looking up XObject resources. + [Thanks to shellway for the bug report.] +The unicodeRemapping config command wasn't correctly handling unsorted + remapping files. +Improved handling of RTL text in the text extractor. +Extended the saveTabState/loadTabState commands to save/restore + display mode, zoom, rotation, and scroll position for each tab. +Added support for Qt6. +Added a missing bounds check on stream DecodeParms arrays. [Thanks to + minipython for the bug report.] +Fixed an integer overflow check in XRef::readXRefTable. [Thanks to + yangshufan for the bug report.] +The builtin Latin1 encoding was mapping 'endash' instead of + 'softhyphen' to 0xad. [Thanks to Jach Fong for the bug report.] +Fixed a bug in PSOutputDev::checkPageSlice() when built without + SPLASH_CMYK. [Thanks to irfanariq for the bug report.] +Added missing array length and type checks in Gfx::doForm(). [Thanks + to shaohua for the bug report.] +Fixed an integer overflow security hole in the JBIG2 decoder. +Substitute Helvetica for undefined fonts and bad font objects. +Added an integer overflow check in JPXStream. (JPXStream issue) + [Thanks to Shin Ando @ Ricera Security for the bug report.] +The DCT (JPEG) decoder was allowing the 'interleaved' flag to be + changed after the first scan of the image. (CVE-2022-24106) [Thanks + to Shin Ando @ Ricera Security for the bug report.] diff --git a/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt index a99cd253231..90cefe33dac 100644 --- a/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt +++ b/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt @@ -4,11 +4,11 @@ # # CMake script for the Xpdf package. # -# Copyright 2015 Glyph & Cog, LLC +# Copyright 2021 Glyph & Cog, LLC # #======================================================================== -cmake_minimum_required(VERSION 2.8.8) +cmake_minimum_required(VERSION 2.8.12) project(xpdf) @@ -28,8 +28,8 @@ if (NOT PNG_FOUND) message(WARNING "Couldn't find libpng -- will not build pdftopng or pdftohtml.") endif () -if (NOT QT4_FOUND AND NOT Qt5Widgets_FOUND) - message(WARNING "Couldn't find Qt4 or Qt5 -- will not build xpdf.") +if (NOT QT4_FOUND AND NOT Qt5Widgets_FOUND AND NOT Qt6Widgets_FOUND) + message(WARNING "Couldn't find Qt4/5/6 -- will not build xpdf.") endif () if (NOT MULTITHREADED) diff --git a/Build/source/libs/xpdf/xpdf-src/INSTALL b/Build/source/libs/xpdf/xpdf-src/INSTALL index 5a7eb6423f4..57ff61f2156 100644 --- a/Build/source/libs/xpdf/xpdf-src/INSTALL +++ b/Build/source/libs/xpdf/xpdf-src/INSTALL @@ -1,11 +1,11 @@ Xpdf ==== -version 4.03 -2021-jan-28 +version 4.04 +2022-apr-18 The Xpdf software and documentation are -copyright 1996-2021 Glyph & Cog, LLC. +copyright 1996-2022 Glyph & Cog, LLC. Email: xpdf@xpdfreader.com WWW: http://www.xpdfreader.com/ @@ -33,7 +33,7 @@ different systems. - CMake 2.8.8 or newer - FreeType 2.0.5 or newer - - Qt 4.8.x or 5.x (for xpdf only) + - Qt 5.x or 6.x (for xpdf only) - libpng (for pdftoppm and pdftohtml) - zlib (for pdftoppm and pdftohtml) diff --git a/Build/source/libs/xpdf/xpdf-src/README b/Build/source/libs/xpdf/xpdf-src/README index e5a114262f0..026460dd24b 100644 --- a/Build/source/libs/xpdf/xpdf-src/README +++ b/Build/source/libs/xpdf/xpdf-src/README @@ -1,11 +1,11 @@ Xpdf ==== -version 4.03 -2021-jan-28 +version 4.04 +2022-apr-18 The Xpdf software and documentation are -copyright 1996-2021 Glyph & Cog, LLC. +copyright 1996-2022 Glyph & Cog, LLC. Email: xpdf@xpdfreader.com WWW: http://www.xpdfreader.com/ @@ -154,6 +154,7 @@ Xpdf uses the following libraries: * libpng [http://www.libpng.com/pub/png/libpng.html] (used by pdftohtml and pdftopng) * zlib [http://zlib.net/] (used by pdftohtml) +* Qt [https://www.qt.io/] Acknowledgments diff --git a/Build/source/libs/xpdf/xpdf-src/cmake-config.txt b/Build/source/libs/xpdf/xpdf-src/cmake-config.txt index e4b3650fcb3..f9339b9fc81 100644 --- a/Build/source/libs/xpdf/xpdf-src/cmake-config.txt +++ b/Build/source/libs/xpdf/xpdf-src/cmake-config.txt @@ -4,7 +4,7 @@ # # CMake script to do misc cmake config and platform-specific config. # -# Copyright 2015 Glyph & Cog, LLC +# Copyright 2021 Glyph & Cog, LLC # #======================================================================== @@ -25,38 +25,32 @@ include(GNUInstallDirs) enable_language(CXX) -#--- set default C/C++ compiler flags for Unix -# and add a 'Profiling' build mode +#--- add a 'Profiling' build mode if (CMAKE_GENERATOR STREQUAL "Unix Makefiles") - if (CYGWIN) - set(PIC_FLAG "") - elseif (CMAKE_HOST_SYSTEM_NAME MATCHES "AIX") - set(PIC_FLAG "-qPIC") - else () - set(PIC_FLAG "-fPIC") - endif () - set(CMAKE_C_FLAGS_DEBUG "-g -O -Wall ${PIC_FLAG}") - set(CMAKE_CXX_FLAGS_DEBUG "-g -O -Wall ${PIC_FLAG}") - set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g -O -Wall ${PIC_FLAG}") - set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall ${PIC_FLAG}") - set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall ${PIC_FLAG}") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O2 -Wall ${PIC_FLAG}") - set(CMAKE_C_FLAGS_PROFILING "-g -pg -O -Wall ${PIC_FLAG}" - CACHE STRING "C compiler flags for profiling mode") - set(CMAKE_CXX_FLAGS_PROFILING "-g -pg -O -Wall ${PIC_FLAG}" - CACHE STRING "C++ compiler flags for profiling mode") - set(CMAKE_EXE_LINKER_FLAGS_PROFILING "-g -pg -O -Wall ${PIC_FLAG}" - CACHE STRING "linker flags for profiling mode") + set(CMAKE_C_FLAGS_PROFILING "-g -pg -O -Wall" + CACHE STRING "C compiler flags for profiling mode" + FORCE) + set(CMAKE_CXX_FLAGS_PROFILING "-g -pg -O -Wall" + CACHE STRING "C++ compiler flags for profiling mode" + FORCE) + set(CMAKE_EXE_LINKER_FLAGS_PROFILING "-g -pg -O -Wall" + CACHE STRING "linker flags for profiling mode" + FORCE) + set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-g -pg -O -Wall" + CACHE STRING "shared linker flags for profiling mode" + FORCE) mark_as_advanced( CMAKE_C_FLAGS_PROFILING CMAKE_CXX_FLAGS_PROFILING - CMAKE_EXE_LINKER_FLAGS_PROFILING) + CMAKE_EXE_LINKER_FLAGS_PROFILING + CMAKE_SHARED_LINKER_FLAGS_PROFILING) set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING - "Choose build mode - options are: None Debug Release RelWithDebInfo MinSizeRel Profiling") + "Choose build mode - options are: None Debug Release RelWithDebInfo MinSizeRel Profiling" + FORCE) endif () #--- set default C/C++ compiler flags for Windows -if (WIN32) +if (MSVC) option(USE_MT_IN_DEBUG "use /MT instead of /MTd in debug builds" OFF) foreach (var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE @@ -108,7 +102,7 @@ option(XPDFRC_DATADIR "directory to use for the DATADIR xpdfrc variable" "") if (XPDFRC_DATADIR) set(XPDFRC_DATADIR_DEFINE "#define XPDFRC_DATADIR \"${XPDFRC_DATADIR}\"") else () - set(XPDFRC_DATADIR_DEFINE "/* #undef SYSTEM_XPDFRC */") + set(XPDFRC_DATADIR_DEFINE "/* #undef XPDFRC_DATADIR */") endif () if (WIN32) option(XPDFWIDGET_PRINTING "include printing support in XpdfWidget" OFF) @@ -211,14 +205,20 @@ find_package(PNG) #--- look for Qt -find_package(Qt5Widgets QUIET) -if (Qt5Widgets_FOUND) - find_package(Qt5Network) - find_package(Qt5PrintSupport) +find_package(Qt6Widgets QUIET) +if (Qt6Widgets_FOUND) + find_package(Qt6Network) + find_package(Qt6PrintSupport) else () - find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork) + find_package(Qt5Widgets QUIET) + if (Qt5Widgets_FOUND) + find_package(Qt5Network) + find_package(Qt5PrintSupport) + else () + find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork) + endif () endif () -if(Qt5Widgets_FOUND) +if (Qt5Widgets_FOUND) message(STATUS "Qt5 found") if (XPDFWIDGET_PRINTING) set(QT_INCLUDES "${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5PrintSupport_INCLUDE_DIRS}") @@ -245,7 +245,34 @@ if(Qt5Widgets_FOUND) endif () # remove "-fPIE" here because we added "-fPIC" above string(REPLACE "-fPIE" "" QT_CFLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") -elseif(QT4_FOUND) +elseif (Qt6Widgets_FOUND) + message(STATUS "Qt6 found") + if (XPDFWIDGET_PRINTING) + set(QT_INCLUDES "${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS} ${Qt6PrintSupport_INCLUDE_DIRS}") + set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6PrintSupport_DEFINITIONS}") + set(QT_LIBRARIES Qt6::Widgets Qt6::Network Qt6::PrintSupport) + else () + set(QT_INCLUDES "${Qt6Widgets_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS}") + set(QT_DEFINITIONS "${Qt6Widgets_DEFINITIONS} ${Qt6Network_DEFINITIONS}") + set(QT_LIBRARIES Qt6::Widgets Qt6::Network) + endif () + if (XPDFWIDGET_PRINTING) + if (APPLE) + set(EXTRA_QT_LIBRARIES "-framework ApplicationServices") + elseif (UNIX) + find_package(Cups) + if (CUPS_FOUND) + set(EXTRA_QT_LIBRARIES ${CUPS_LIBRARIES}) + else () + set (XPDFWIDGET_PRINTING OFF) + endif () + else () + set(EXTRA_QT_LIBRARIES "") + endif () + endif () + # remove "-fPIE" here because we added "-fPIC" above + string(REPLACE "-fPIE" "" QT_CFLAGS "${Qt6Widgets_EXECUTABLE_COMPILE_FLAGS}") +elseif (QT4_FOUND) message(STATUS "Qt4 found") if (XPDFWIDGET_PRINTING) if (APPLE) @@ -261,9 +288,9 @@ elseif(QT4_FOUND) set(EXTRA_QT_LIBRARIES "") endif () endif () -else() +else () message(STATUS "No Qt library found") -endif() +endif () #--- look for libpaper find_library(PAPER_LIBRARY diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1 index 7fd3b8a5231..4d00f3722d6 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1 @@ -1,8 +1,8 @@ -.\" Copyright 2013-2021 Glyph & Cog, LLC -.TH pdfdetach 1 "28 Jan 2021" +.\" Copyright 2013-2022 Glyph & Cog, LLC +.TH pdfdetach 1 "18 Apr 2022" .SH NAME pdfdetach \- Portable Document Format (PDF) document embedded file -extractor (version 4.03) +extractor (version 4.04) .SH SYNOPSIS .B pdfdetach [options] @@ -14,9 +14,8 @@ Document Format (PDF) file. .SH CONFIGURATION FILE Pdfdetach reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdfinfo -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdfinfo is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -90,7 +89,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdfinfo software and documentation are copyright 1996-2021 Glyph & +The pdfinfo software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat index 000eb66e5ae..220bb752467 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat @@ -4,7 +4,7 @@ pdfdetach(1) General Commands Manual pdfdetach(1) NAME pdfdetach - Portable Document Format (PDF) document embedded file - extractor (version 4.03) + extractor (version 4.04) SYNOPSIS pdfdetach [options] [PDF-file] @@ -16,9 +16,9 @@ DESCRIPTION CONFIGURATION FILE Pdfdetach reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, - it looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdfinfo is built). See the - xpdfrc(5) man page for details. + it looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdfinfo is built). See the xpdfrc(5) man + page for details. OPTIONS Some of the following options can be set with configuration file com- @@ -79,7 +79,7 @@ EXIT CODES 99 Other error. AUTHOR - The pdfinfo software and documentation are copyright 1996-2021 Glyph & + The pdfinfo software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -89,4 +89,4 @@ SEE ALSO - 28 Jan 2021 pdfdetach(1) + 18 Apr 2022 pdfdetach(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1 index 0192bd3247e..6ee0226e677 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1 @@ -1,8 +1,8 @@ -.\" Copyright 1999-2021 Glyph & Cog, LLC -.TH pdffonts 1 "28 Jan 2021" +.\" Copyright 1999-2022 Glyph & Cog, LLC +.TH pdffonts 1 "18 Apr 2022" .SH NAME pdffonts \- Portable Document Format (PDF) font analyzer (version -4.03) +4.04) .SH SYNOPSIS .B pdffonts [options] @@ -84,9 +84,8 @@ CID TrueType (OT) -- OpenType with CID TrueType data .SH CONFIGURATION FILE Pdffonts reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdffonts -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdffonts is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -147,7 +146,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdffonts software and documentation are copyright 1996-2021 Glyph +The pdffonts software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat index 59f4dd90ca9..77fef55fd64 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat @@ -3,7 +3,7 @@ pdffonts(1) General Commands Manual pdffonts(1) NAME - pdffonts - Portable Document Format (PDF) font analyzer (version 4.03) + pdffonts - Portable Document Format (PDF) font analyzer (version 4.04) SYNOPSIS pdffonts [options] [PDF-file] @@ -53,9 +53,9 @@ DESCRIPTION CONFIGURATION FILE Pdffonts reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it - looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdffonts is built). See the - xpdfrc(5) man page for details. + looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdffonts is built). See the xpdfrc(5) man + page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -105,7 +105,7 @@ EXIT CODES 99 Other error. AUTHOR - The pdffonts software and documentation are copyright 1996-2021 Glyph & + The pdffonts software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -115,4 +115,4 @@ SEE ALSO - 28 Jan 2021 pdffonts(1) + 18 Apr 2022 pdffonts(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1 index 2d95ac79b66..06a9c1fc85c 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1 @@ -1,8 +1,8 @@ -.\" Copyright 1998-2021 Glyph & Cog, LLC -.TH pdfimages 1 "28 Jan 2021" +.\" Copyright 1998-2022 Glyph & Cog, LLC +.TH pdfimages 1 "18 Apr 2022" .SH NAME pdfimages \- Portable Document Format (PDF) image extractor -(version 4.03) +(version 4.04) .SH SYNOPSIS .B pdfimages [options] @@ -29,9 +29,8 @@ color inversion, etc. done by the PDF content stream is ignored. .SH CONFIGURATION FILE Pdfimages reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdfimages -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdfimages is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -71,6 +70,10 @@ bypass all security restrictions. .BI \-upw " password" Specify the user password for the PDF file. .TP +.B \-verbose +Print a status message (to stdout) before processing each page. +.RB "[config file: " printStatusInfo ] +.TP .B \-q Don't print any messages or errors. .RB "[config file: " errQuiet ] @@ -102,7 +105,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdfimages software and documentation are copyright 1998-2021 Glyph +The pdfimages software and documentation are copyright 1998-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat index 97a0371573b..7361a3bb11c 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat @@ -4,7 +4,7 @@ pdfimages(1) General Commands Manual pdfimages(1) NAME pdfimages - Portable Document Format (PDF) image extractor (version - 4.03) + 4.04) SYNOPSIS pdfimages [options] PDF-file image-root @@ -26,9 +26,9 @@ DESCRIPTION CONFIGURATION FILE Pdfimages reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, - it looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdfimages is built). See the - xpdfrc(5) man page for details. + it looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdfimages is built). See the xpdfrc(5) + man page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -65,6 +65,10 @@ OPTIONS -upw password Specify the user password for the PDF file. + -verbose + Print a status message (to stdout) before processing each page. + [config file: printStatusInfo] + -q Don't print any messages or errors. [config file: errQuiet] -v Print copyright and version information. @@ -85,14 +89,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdfimages software and documentation are copyright 1998-2021 Glyph + The pdfimages software and documentation are copyright 1998-2022 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- fonts(1), pdfdetach(1), pdftoppm(1), pdftopng(1), xpdfrc(5) http://www.xpdfreader.com/ - 28 Jan 2021 pdfimages(1) + 18 Apr 2022 pdfimages(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1 index f84badc9814..66f3e70bf3a 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1 @@ -1,8 +1,8 @@ -.\" Copyright 1999-2021 Glyph & Cog, LLC -.TH pdfinfo 1 "28 Jan 2021" +.\" Copyright 1999-2022 Glyph & Cog, LLC +.TH pdfinfo 1 "18 Apr 2022" .SH NAME pdfinfo \- Portable Document Format (PDF) document information -extractor (version 4.03) +extractor (version 4.04) .SH SYNOPSIS .B pdfinfo [options] @@ -74,8 +74,8 @@ metadata (only if requested) .SH CONFIGURATION FILE Pdfinfo reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it -looks for a system-wide config file, typically /usr/local/etc/xpdfrc -(but this location can be changed when pdfinfo is built). See the +looks for a system-wide config file, typically /etc/xpdfrc (but this +location can be changed when pdfinfo is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -150,7 +150,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdfinfo software and documentation are copyright 1996-2021 Glyph & +The pdfinfo software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat index 0478db677c4..05dbc38f18b 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat @@ -4,7 +4,7 @@ pdfinfo(1) General Commands Manual pdfinfo(1) NAME pdfinfo - Portable Document Format (PDF) document information extractor - (version 4.03) + (version 4.04) SYNOPSIS pdfinfo [options] [PDF-file] @@ -40,9 +40,9 @@ DESCRIPTION CONFIGURATION FILE Pdfinfo reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it - looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdfinfo is built). See the - xpdfrc(5) man page for details. + looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdfinfo is built). See the xpdfrc(5) man + page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -104,7 +104,7 @@ EXIT CODES 99 Other error. AUTHOR - The pdfinfo software and documentation are copyright 1996-2021 Glyph & + The pdfinfo software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -114,4 +114,4 @@ SEE ALSO - 28 Jan 2021 pdfinfo(1) + 18 Apr 2022 pdfinfo(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1 index 4618a7a77a9..5129f0dd4b9 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1 @@ -1,8 +1,8 @@ -.\" Copyright 1997-2021 Glyph & Cog, LLC -.TH pdftohtml 1 "28 Jan 2021" +.\" Copyright 1997-2022 Glyph & Cog, LLC +.TH pdftohtml 1 "18 Apr 2022" .SH NAME pdftohtml \- Portable Document Format (PDF) to HTML converter -(version 4.03) +(version 4.04) .SH SYNOPSIS .B pdftohtml [options] @@ -22,9 +22,8 @@ will report an error. .SH CONFIGURATION FILE Pdftohtml reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdftohtml -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdftohtml is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -50,11 +49,24 @@ zoom level is controlled by the \'-z' option. Specifying a larger \'-r' value will allow the viewer to zoom in farther without upscaling artifacts in the background. .TP +.BI \-vstretch " number" +Specifies a vertical stretch factor. Setting this to a value greater +than 1.0 will stretch each page vertically, spreading out the lines. +This also stretches the background image to match. +.TP +.B \-embedbackground +Embeds the background image as base64-encoded data directly in the +HTML file, rather than storing it as a separate file. +.TP .B \-nofonts Disable extraction of embedded fonts. By default, pdftohtml extracts TrueType and OpenType fonts. Disabling extraction can work around problems with buggy fonts. .TP +.B \-embedfonts +Embeds any extracted fonts as base64-encoded data directly in the HTML +file, rather than storing them as separate files. +.TP .B \-skipinvisible Don't draw invisible text. By default, invisible text (commonly used in OCR'ed PDF files) is drawn as transparent (alpha=0) HTML text. @@ -67,6 +79,17 @@ on top of the image. This option tells pdftohtml to include the regular text in the background image, and then draw it as transparent (alpha=0) HTML text. .TP +.B \-formfields +Convert AcroForm text and checkbox fields to HTML input elements. +This also removes text (e.g., underscore characters) and erases +background image content (e.g., lines or boxes) in the field areas. +.TP +.B \-table +Use table mode when performing the underlying text extraction. This +will generally produce better output when the PDF content is a +full-page table. NB: This does not generate HTML tables; it just +changes the way text is split up. +.TP .BI \-opw " password" Specify the owner password for the PDF file. Providing this will bypass all security restrictions. @@ -74,6 +97,10 @@ bypass all security restrictions. .BI \-upw " password" Specify the user password for the PDF file. .TP +.B \-verbose +Print a status message (to stdout) before processing each page. +.RB "[config file: " printStatusInfo ] +.TP .B \-q Don't print any messages or errors. .RB "[config file: " errQuiet ] @@ -114,7 +141,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftohtml software and documentation are copyright 1996-2021 Glyph +The pdftohtml software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat index 3eea2e32ec1..5ddbfa0c9fb 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat @@ -4,7 +4,7 @@ pdftohtml(1) General Commands Manual pdftohtml(1) NAME pdftohtml - Portable Document Format (PDF) to HTML converter (version - 4.03) + 4.04) SYNOPSIS pdftohtml [options] PDF-file HTML-dir @@ -20,9 +20,9 @@ DESCRIPTION CONFIGURATION FILE Pdftohtml reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, - it looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdftohtml is built). See the - xpdfrc(5) man page for details. + it looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdftohtml is built). See the xpdfrc(5) + man page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -48,31 +48,60 @@ OPTIONS larger '-r' value will allow the viewer to zoom in farther with- out upscaling artifacts in the background. + -vstretch number + Specifies a vertical stretch factor. Setting this to a value + greater than 1.0 will stretch each page vertically, spreading + out the lines. This also stretches the background image to + match. + + -embedbackground + Embeds the background image as base64-encoded data directly in + the HTML file, rather than storing it as a separate file. + -nofonts Disable extraction of embedded fonts. By default, pdftohtml extracts TrueType and OpenType fonts. Disabling extraction can work around problems with buggy fonts. + -embedfonts + Embeds any extracted fonts as base64-encoded data directly in + the HTML file, rather than storing them as separate files. + -skipinvisible Don't draw invisible text. By default, invisible text (commonly used in OCR'ed PDF files) is drawn as transparent (alpha=0) HTML - text. This option tells pdftohtml to discard invisible text + text. This option tells pdftohtml to discard invisible text entirely. -allinvisible - Treat all text as invisible. By default, regular (non-invisi- - ble) text is not drawn in the background image, and is instead - drawn with HTML on top of the image. This option tells pdfto- - html to include the regular text in the background image, and + Treat all text as invisible. By default, regular (non-invisi- + ble) text is not drawn in the background image, and is instead + drawn with HTML on top of the image. This option tells pdfto- + html to include the regular text in the background image, and then draw it as transparent (alpha=0) HTML text. + -formfields + Convert AcroForm text and checkbox fields to HTML input ele- + ments. This also removes text (e.g., underscore characters) and + erases background image content (e.g., lines or boxes) in the + field areas. + + -table Use table mode when performing the underlying text extraction. + This will generally produce better output when the PDF content + is a full-page table. NB: This does not generate HTML tables; + it just changes the way text is split up. + -opw password - Specify the owner password for the PDF file. Providing this + Specify the owner password for the PDF file. Providing this will bypass all security restrictions. -upw password Specify the user password for the PDF file. + -verbose + Print a status message (to stdout) before processing each page. + [config file: printStatusInfo] + -q Don't print any messages or errors. [config file: errQuiet] -cfg config-file @@ -102,7 +131,7 @@ EXIT CODES 99 Other error. AUTHOR - The pdftohtml software and documentation are copyright 1996-2021 Glyph + The pdftohtml software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -112,4 +141,4 @@ SEE ALSO - 28 Jan 2021 pdftohtml(1) + 18 Apr 2022 pdftohtml(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1 index bd8f517358f..1193120a54d 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1 @@ -1,8 +1,8 @@ -.\" Copyright 2017-2021 Glyph & Cog, LLC -.TH pdftopng 1 "28 Jan 2021" +.\" Copyright 2017-2022 Glyph & Cog, LLC +.TH pdftopng 1 "18 Apr 2022" .SH NAME pdftopng \- Portable Document Format (PDF) to Portable Network Graphics -(PNG) converter (version 4.03) +(PNG) converter (version 4.04) .SH SYNOPSIS .B pdftopng [options] @@ -26,9 +26,8 @@ when converting a single page). .SH CONFIGURATION FILE Pdftopng reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdftopng -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdftopng is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -79,6 +78,10 @@ bypass all security restrictions. .BI \-upw " password" Specify the user password for the PDF file. .TP +.B \-verbose +Print a status message (to stdout) before processing each page. +.RB "[config file: " printStatusInfo ] +.TP .B \-q Don't print any messages or errors. .RB "[config file: " errQuiet ] @@ -110,7 +113,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftopng software and documentation are copyright 1996-2021 Glyph +The pdftopng software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat index 7e17c504b4b..10a4408496f 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat @@ -4,7 +4,7 @@ pdftopng(1) General Commands Manual pdftopng(1) NAME pdftopng - Portable Document Format (PDF) to Portable Network Graphics - (PNG) converter (version 4.03) + (PNG) converter (version 4.04) SYNOPSIS pdftopng [options] PDF-file PNG-root @@ -22,9 +22,9 @@ DESCRIPTION CONFIGURATION FILE Pdftopng reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it - looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdftopng is built). See the - xpdfrc(5) man page for details. + looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdftopng is built). See the xpdfrc(5) man + page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -70,6 +70,10 @@ OPTIONS -upw password Specify the user password for the PDF file. + -verbose + Print a status message (to stdout) before processing each page. + [config file: printStatusInfo] + -q Don't print any messages or errors. [config file: errQuiet] -v Print copyright and version information. @@ -90,14 +94,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdftopng software and documentation are copyright 1996-2021 Glyph & + The pdftopng software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- fonts(1), pdfdetach(1), pdftoppm(1), pdfimages(1), xpdfrc(5) http://www.xpdfreader.com/ - 28 Jan 2021 pdftopng(1) + 18 Apr 2022 pdftopng(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1 index 23b5b06980c..d485b2bc48f 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1 @@ -1,8 +1,8 @@ -.\" Copyright 2005-2021 Glyph & Cog, LLC -.TH pdftoppm 1 "28 Jan 2021" +.\" Copyright 2005-2022 Glyph & Cog, LLC +.TH pdftoppm 1 "18 Apr 2022" .SH NAME pdftoppm \- Portable Document Format (PDF) to Portable Pixmap (PPM) -converter (version 4.03) +converter (version 4.04) .SH SYNOPSIS .B pdftoppm [options] @@ -28,9 +28,8 @@ when converting a single page). .SH CONFIGURATION FILE Pdftoppm reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdftoppm -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdftoppm is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -79,6 +78,10 @@ bypass all security restrictions. .BI \-upw " password" Specify the user password for the PDF file. .TP +.B \-verbose +Print a status message (to stdout) before processing each page. +.RB "[config file: " printStatusInfo ] +.TP .B \-q Don't print any messages or errors. .RB "[config file: " errQuiet ] @@ -110,7 +113,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftoppm software and documentation are copyright 1996-2021 Glyph +The pdftoppm software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat index 9621be3c3b0..30d012df246 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat @@ -4,7 +4,7 @@ pdftoppm(1) General Commands Manual pdftoppm(1) NAME pdftoppm - Portable Document Format (PDF) to Portable Pixmap (PPM) con- - verter (version 4.03) + verter (version 4.04) SYNOPSIS pdftoppm [options] PDF-file PPM-root @@ -23,9 +23,9 @@ DESCRIPTION CONFIGURATION FILE Pdftoppm reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it - looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdftoppm is built). See the - xpdfrc(5) man page for details. + looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdftoppm is built). See the xpdfrc(5) man + page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -69,6 +69,10 @@ OPTIONS -upw password Specify the user password for the PDF file. + -verbose + Print a status message (to stdout) before processing each page. + [config file: printStatusInfo] + -q Don't print any messages or errors. [config file: errQuiet] -v Print copyright and version information. @@ -89,14 +93,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdftoppm software and documentation are copyright 1996-2021 Glyph & + The pdftoppm software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- fonts(1), pdfdetach(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.xpdfreader.com/ - 28 Jan 2021 pdftoppm(1) + 18 Apr 2022 pdftoppm(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1 index e23425d5bad..028e983aec9 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1 @@ -1,8 +1,8 @@ -.\" Copyright 1996-2021 Glyph & Cog, LLC -.TH pdftops 1 "28 Jan 2021" +.\" Copyright 1996-2022 Glyph & Cog, LLC +.TH pdftops 1 "18 Apr 2022" .SH NAME pdftops \- Portable Document Format (PDF) to PostScript converter -(version 4.03) +(version 4.04) .SH SYNOPSIS .B pdftops [options] @@ -31,8 +31,8 @@ is \'-', the PostScript is sent to stdout. .SH CONFIGURATION FILE Pdftops reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it -looks for a system-wide config file, typically /usr/local/etc/xpdfrc -(but this location can be changed when pdftops is built). See the +looks for a system-wide config file, typically /etc/xpdfrc (but this +location can be changed when pdftops is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -200,6 +200,10 @@ bypass all security restrictions. .BI \-upw " password" Specify the user password for the PDF file. .TP +.B \-verbose +Print a status message (to stdout) before processing each page. +.RB "[config file: " printStatusInfo ] +.TP .B \-q Don't print any messages or errors. .RB "[config file: " errQuiet ] @@ -236,7 +240,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftops software and documentation are copyright 1996-2021 Glyph & +The pdftops software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat index c985d686fea..ed1c8b718cc 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat @@ -4,7 +4,7 @@ pdftops(1) General Commands Manual pdftops(1) NAME pdftops - Portable Document Format (PDF) to PostScript converter (ver- - sion 4.03) + sion 4.04) SYNOPSIS pdftops [options] [PDF-file [PS-file]] @@ -21,9 +21,9 @@ DESCRIPTION CONFIGURATION FILE Pdftops reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it - looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdftops is built). See the - xpdfrc(5) man page for details. + looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdftops is built). See the xpdfrc(5) man + page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -177,6 +177,10 @@ OPTIONS -upw password Specify the user password for the PDF file. + -verbose + Print a status message (to stdout) before processing each page. + [config file: printStatusInfo] + -q Don't print any messages or errors. [config file: errQuiet] -cfg config-file @@ -201,14 +205,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdftops software and documentation are copyright 1996-2021 Glyph & + The pdftops software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde- + xpdf(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde- tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.xpdfreader.com/ - 28 Jan 2021 pdftops(1) + 18 Apr 2022 pdftops(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1 b/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1 index d1e81d01f25..e5e7d655bda 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1 @@ -1,8 +1,8 @@ -.\" Copyright 1997-2021 Glyph & Cog, LLC -.TH pdftotext 1 "28 Jan 2021" +.\" Copyright 1997-2022 Glyph & Cog, LLC +.TH pdftotext 1 "18 Apr 2022" .SH NAME pdftotext \- Portable Document Format (PDF) to text converter -(version 4.03) +(version 4.04) .SH SYNOPSIS .B pdftotext [options] @@ -28,9 +28,8 @@ is \'-', the text is sent to stdout. .SH CONFIGURATION FILE Pdftotext reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't -exist, it looks for a system-wide config file, typically -/usr/local/etc/xpdfrc (but this location can be changed when pdftotext -is built). See the +exist, it looks for a system-wide config file, typically /etc/xpdfrc +(but this location can be changed when pdftotext is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -124,7 +123,8 @@ Sets the end-of-line convention to use for text output. .RB "[config file: " textEOL ] .TP .B \-nopgbrk -Don't insert page breaks (form feed characters) between pages. +Don't insert a page breaks (form feed character) at the end of each +page. .RB "[config file: " textPageBreaks ] .TP .B \-bom @@ -158,6 +158,10 @@ bypass all security restrictions. .BI \-upw " password" Specify the user password for the PDF file. .TP +.B \-verbose +Print a status message (to stdout) before processing each page. +.RB "[config file: " printStatusInfo ] +.TP .B \-q Don't print any messages or errors. .RB "[config file: " errQuiet ] @@ -201,7 +205,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftotext software and documentation are copyright 1996-2021 Glyph +The pdftotext software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat b/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat index d4a001d7c63..face2575a3f 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat @@ -4,7 +4,7 @@ pdftotext(1) General Commands Manual pdftotext(1) NAME pdftotext - Portable Document Format (PDF) to text converter (version - 4.03) + 4.04) SYNOPSIS pdftotext [options] [PDF-file [text-file]] @@ -19,9 +19,9 @@ DESCRIPTION CONFIGURATION FILE Pdftotext reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, - it looks for a system-wide config file, typically /usr/local/etc/xpdfrc - (but this location can be changed when pdftotext is built). See the - xpdfrc(5) man page for details. + it looks for a system-wide config file, typically /etc/xpdfrc (but this + location can be changed when pdftotext is built). See the xpdfrc(5) + man page for details. OPTIONS Many of the following options can be set with configuration file com- @@ -101,8 +101,8 @@ OPTIONS file: textEOL] -nopgbrk - Don't insert page breaks (form feed characters) between pages. - [config file: textPageBreaks] + Don't insert a page breaks (form feed character) at the end of + each page. [config file: textPageBreaks] -bom Insert a Unicode byte order marker (BOM) at the start of the text output. @@ -134,6 +134,10 @@ OPTIONS -upw password Specify the user password for the PDF file. + -verbose + Print a status message (to stdout) before processing each page. + [config file: printStatusInfo] + -q Don't print any messages or errors. [config file: errQuiet] -cfg config-file @@ -145,11 +149,11 @@ OPTIONS -v Print copyright and version information, then exit. - -h Print usage information, then exit. (-help and --help are + -h Print usage information, then exit. (-help and --help are equivalent.) BUGS - Some PDF files contain fonts whose encodings have been mangled beyond + Some PDF files contain fonts whose encodings have been mangled beyond recognition. There is no way (short of OCR) to extract text from these files. @@ -167,7 +171,7 @@ EXIT CODES 99 Other error. AUTHOR - The pdftotext software and documentation are copyright 1996-2021 Glyph + The pdftotext software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -177,4 +181,4 @@ SEE ALSO - 28 Jan 2021 pdftotext(1) + 18 Apr 2022 pdftotext(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1 b/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1 index 7cf06315f88..2eaa95af69b 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1 +++ b/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1 @@ -1,7 +1,7 @@ -.\" Copyright 1996-2021 Glyph & Cog, LLC -.TH xpdf 1 "28 Jan 2021" +.\" Copyright 1996-2022 Glyph & Cog, LLC +.TH xpdf 1 "18 Apr 2022" .SH NAME -xpdf \- Portable Document Format (PDF) file viewer (version 4.03) +xpdf \- Portable Document Format (PDF) file viewer (version 4.04) .SH SYNOPSIS .B xpdf [options] @@ -61,8 +61,8 @@ xpdf .SH CONFIGURATION FILE Xpdf reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it -looks for a system-wide config file, typically /usr/local/etc/xpdfrc -(but this location can be changed when xpdf is built). See the +looks for a system-wide config file, typically /etc/xpdfrc (but this +location can be changed when xpdf is built). See the .BR xpdfrc (5) man page for details. .SH OPTIONS @@ -551,6 +551,9 @@ Go to the specified page. .BI help Open the help URL. .TP +.B hideMenuBar +Hide the menu bar. +.TP .B hideToolbar Hide the toolbar. .TP @@ -591,6 +594,25 @@ Open the error window. .BI openFile( file ) Open the specified file in the current tab. .TP +.BI openFile2( file, page, dest, passwd, location ) +Open the specified file. If +.I dest +is not empty, go to the specified named destination. Else, if +.I page +is not empty, go to the specified page number. If +.I password +is not empty, it is used as the PDF password. If +.I location +is "win", open the file in a new window; if it is "tab", open in a new +tab; if it is "check", open in the current tab, but only if the +specified PDF file isn't already open; else open in the current tab. +Any/all of the arguments, other than +.IR file , +can be empty strings. For example: +.nf +openFile2(test.pdf,7,,,tab) +.fi +.TP .BI openFileAtDest( file, dest ) Open the specified file in the current tab at the specified named destination. @@ -787,9 +809,24 @@ Set the selection to the word at the current mouse position. .BI setSelection( pg , ulx , uly , lrx , lry ) Set the selection to the specified coordinates on the specified page. .TP +.B showAttachmentsPane +Shows the attachments in the outline/layers/attachments pane. +.TP +.B showDocumentInfo +Open the document information dialog. +.TP .B showKeyBindings Open the key bindings dialog. .TP +.B showLayersPane +Shows the layers in the outline/layers/attachments pane. +.TP +.B showMenuBar +Show the menu bar. +.TP +.B showOutlinePane +Shows the outline in the outline/layers/attachments pane. +.TP .B showToolbar Show the toolbar. .TP @@ -826,6 +863,9 @@ Toggle between continuous and single page view modes. .B toggleFullScreenMode Toggle between full-screen and window modes. .TP +.B toggleMenuBar +Toggle the menu bar between shown and hidden. +.TP .B toggleSelectMode Toggle between block and linear selection mode. .TP @@ -908,7 +948,7 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The xpdf software and documentation are copyright 1996-2021 Glyph & +The xpdf software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR pdftops (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat b/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat index 3b71667f055..ba20911962d 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat @@ -3,7 +3,7 @@ xpdf(1) General Commands Manual xpdf(1) NAME - xpdf - Portable Document Format (PDF) file viewer (version 4.03) + xpdf - Portable Document Format (PDF) file viewer (version 4.04) SYNOPSIS xpdf [options] [PDF-file [:page | +dest]] ... @@ -44,9 +44,9 @@ DESCRIPTION CONFIGURATION FILE Xpdf reads a configuration file at startup. It first tries to find the user's private config file, ~/.xpdfrc. If that doesn't exist, it looks - for a system-wide config file, typically /usr/local/etc/xpdfrc (but - this location can be changed when xpdf is built). See the xpdfrc(5) - man page for details. + for a system-wide config file, typically /etc/xpdfrc (but this location + can be changed when xpdf is built). See the xpdfrc(5) man page for + details. OPTIONS The following command line options are available. All command line @@ -500,6 +500,9 @@ COMMANDS help Open the help URL. + hideMenuBar + Hide the menu bar. + hideToolbar Hide the toolbar. @@ -538,6 +541,18 @@ COMMANDS openFile(file) Open the specified file in the current tab. + openFile2(file,page,dest,passwd,location) + Open the specified file. If dest is not empty, go to the speci- + fied named destination. Else, if page is not empty, go to the + specified page number. If password is not empty, it is used as + the PDF password. If location is "win", open the file in a new + window; if it is "tab", open in a new tab; if it is "check", + open in the current tab, but only if the specified PDF file + isn't already open; else open in the current tab. Any/all of + the arguments, other than file, can be empty strings. For exam- + ple: + openFile2(test.pdf,7,,,tab) + openFileAtDest(file,dest) Open the specified file in the current tab at the specified named destination. @@ -711,9 +726,24 @@ COMMANDS Set the selection to the specified coordinates on the specified page. + showAttachmentsPane + Shows the attachments in the outline/layers/attachments pane. + + showDocumentInfo + Open the document information dialog. + showKeyBindings Open the key bindings dialog. + showLayersPane + Shows the layers in the outline/layers/attachments pane. + + showMenuBar + Show the menu bar. + + showOutlinePane + Shows the outline in the outline/layers/attachments pane. + showToolbar Show the toolbar. @@ -748,6 +778,9 @@ COMMANDS toggleFullScreenMode Toggle between full-screen and window modes. + toggleMenuBar + Toggle the menu bar between shown and hidden. + toggleSelectMode Toggle between block and linear selection mode. @@ -825,7 +858,7 @@ EXIT CODES 99 Other error. AUTHOR - The xpdf software and documentation are copyright 1996-2021 Glyph & + The xpdf software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -835,4 +868,4 @@ SEE ALSO - 28 Jan 2021 xpdf(1) + 18 Apr 2022 xpdf(1) diff --git a/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5 b/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5 index 07639316ec7..1c47e2ebb29 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5 +++ b/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5 @@ -1,17 +1,22 @@ -.\" Copyright 2002-2021 Glyph & Cog, LLC -.TH xpdfrc 5 "28 Jan 2021" +.\" Copyright 2002-2022 Glyph & Cog, LLC +.TH xpdfrc 5 "18 Apr 202" .SH NAME -xpdfrc \- configuration file for Xpdf tools (version 4.03) +xpdfrc \- configuration file for Xpdf tools (version 4.04) .SH DESCRIPTION -All of the Xpdf tools read a single configuration file. If you have a +All of the Xpdf tools read a single configuration file. +.PP +On Linux/Unix/MacOS: if you have a .I .xpdfrc file in your home directory, it will be read. Otherwise, a system-wide configuration file will be read from -.IR /usr/local/etc/xpdfrc , +.IR /etc/xpdfrc , if it exists. (This is its default location; depending on build -options, it may be placed elsewhere.) On Win32 systems, the +options, it may be placed elsewhere.) +.PP +On Windows: the file must be named .I xpdfrc -file should be placed in the same directory as the executables. +(no leading dot, no extension), and must be placed in the same +directory as the executable (pdftotext.exe, xpdf.exe, etc.) .PP The xpdfrc file consists of a series of configuration options, one per line. Blank lines and lines starting with a \'#' (comments) are @@ -437,6 +442,12 @@ mapExtTrueTypeFontsViaUnicode is set to "no", Xpdf will assume the character codes are GIDs (i.e., use an identity mapping). This defaults to "yes". .TP +.BI useTrueTypeUnicodeMapping " yes | no" +If set to "yes", the Xpdf tools will use the Unicode encoding +information in TrueType fonts (16-bit only), if avaiable, to override +the PDF ToUnicode maps. Otherwise, the ToUnicode maps are always used +when present. This defaults to "no". +.TP .BI dropFont " font-name" Drop all text drawn in the specified font. To drop text drawn in unnamed fonts, use: @@ -468,6 +479,10 @@ anti-aliasing control provided by the old "t1libControl" and Enables or disables anti-aliasing of vector graphics in the PDF rasterizer. This defaults to "yes". .TP +.BR imageMaskAntialias " yes | no" +Enables or disables anti-aliasing of image masks (when downsampling or +upsampling) in the PDF rasterizer. This defaults to "yes". +.TP .BR antialiasPrinting " yes | no" If this is "yes", bitmaps sent to the printer will be antialiased (according to the "antialias" and "vectorAntialias" settings). If @@ -736,10 +751,26 @@ value is "yes". If set to "no", form fields will not be drawn or printed. The default value is "yes". .TP +.BI enableXFA " yes | no" +If an XFA form is present, and this option is set to "yes", Xpdf will +parse the XFA form and use certain XFA information to override +AcroForm information. If set to "no", the XFA form will not be read. +The default value is "yes". +.TP +.BI savePageNumbers " yes | no" +If set to "yes", xpdf will save the current page numbers of all open +files in ~/.xpdf.pages when the files are closed (or when quitting +xpdf). Next time the file is opened, the last-viewed page number will +be restored. The default value is "yes". +.TP .BI printCommands " yes | no" If set to "yes", drawing commands are printed as they're executed (useful for debugging). This defaults to "no". .TP +.BI printStatusInfo +If set to "yes", print a status message (to stdout) before each page +is processed. This defaults to "no". +.TP .BI errQuiet " yes | no" If set to "yes", this suppresses all error and warning messages from all of the Xpdf tools. This defaults to "no". @@ -798,7 +829,7 @@ launchCommand viewer-script .fi .SH FILES .TP -.B /usr/local/etc/xpdfrc +.B /etc/xpdfrc This is the default location for the system-wide configuration file. Depending on build options, it may be placed elsewhere. .TP @@ -806,7 +837,7 @@ Depending on build options, it may be placed elsewhere. This is the user's configuration file. If it exists, it will be read in place of the system-wide file. .SH AUTHOR -The Xpdf software and documentation are copyright 1996-2021 Glyph & +The Xpdf software and documentation are copyright 1996-2022 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), diff --git a/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat b/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat index c43e8005e2b..c38791eaa28 100644 --- a/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat +++ b/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat @@ -3,15 +3,19 @@ xpdfrc(5) File Formats Manual xpdfrc(5) NAME - xpdfrc - configuration file for Xpdf tools (version 4.03) + xpdfrc - configuration file for Xpdf tools (version 4.04) DESCRIPTION - All of the Xpdf tools read a single configuration file. If you have a - .xpdfrc file in your home directory, it will be read. Otherwise, a - system-wide configuration file will be read from /usr/local/etc/xpdfrc, - if it exists. (This is its default location; depending on build - options, it may be placed elsewhere.) On Win32 systems, the xpdfrc - file should be placed in the same directory as the executables. + All of the Xpdf tools read a single configuration file. + + On Linux/Unix/MacOS: if you have a .xpdfrc file in your home directory, + it will be read. Otherwise, a system-wide configuration file will be + read from /etc/xpdfrc, if it exists. (This is its default location; + depending on build options, it may be placed elsewhere.) + + On Windows: the file must be named xpdfrc (no leading dot, no exten- + sion), and must be placed in the same directory as the executable + (pdftotext.exe, xpdf.exe, etc.) The xpdfrc file consists of a series of configuration options, one per line. Blank lines and lines starting with a '#' (comments) are @@ -385,8 +389,14 @@ TEXT CONTROL AND CHARACTER MAPPING character codes are GIDs (i.e., use an identity mapping). This defaults to "yes". + useTrueTypeUnicodeMapping yes | no + If set to "yes", the Xpdf tools will use the Unicode encoding + information in TrueType fonts (16-bit only), if avaiable, to + override the PDF ToUnicode maps. Otherwise, the ToUnicode maps + are always used when present. This defaults to "no". + dropFont font-name - Drop all text drawn in the specified font. To drop text drawn + Drop all text drawn in the specified font. To drop text drawn in unnamed fonts, use: dropFont "" @@ -395,114 +405,119 @@ TEXT CONTROL AND CHARACTER MAPPING RASTERIZER SETTINGS enableFreeType yes | no - Enables or disables use of FreeType (a TrueType / Type 1 font + Enables or disables use of FreeType (a TrueType / Type 1 font rasterizer). This is only relevant if the Xpdf tools were built with FreeType support. ("enableFreeType" replaces the old "freetypeControl" option.) This option defaults to "yes". disableFreeTypeHinting yes | no - If this is set to "yes", FreeType hinting will be forced off. + If this is set to "yes", FreeType hinting will be forced off. This option defaults to "no". antialias yes | no - Enables or disables font anti-aliasing in the PDF rasterizer. + Enables or disables font anti-aliasing in the PDF rasterizer. This option affects all font rasterizers. ("antialias" replaces the anti-aliasing control provided by the old "t1libControl" and "freetypeControl" options.) This default to "yes". vectorAntialias yes | no - Enables or disables anti-aliasing of vector graphics in the PDF + Enables or disables anti-aliasing of vector graphics in the PDF rasterizer. This defaults to "yes". + imageMaskAntialias yes | no + Enables or disables anti-aliasing of image masks (when downsam- + pling or upsampling) in the PDF rasterizer. This defaults to + "yes". + antialiasPrinting yes | no - If this is "yes", bitmaps sent to the printer will be - antialiased (according to the "antialias" and "vectorAntialias" - settings). If this is "no", printed bitmaps will not be + If this is "yes", bitmaps sent to the printer will be + antialiased (according to the "antialias" and "vectorAntialias" + settings). If this is "no", printed bitmaps will not be antialiased. This defaults to "no". strokeAdjust yes | no | cad - Sets the stroke adjustment mode. If set to "no", no stroke + Sets the stroke adjustment mode. If set to "no", no stroke adjustment will be done. If set to "yes", normal stroke adjust- - ment will be done: horizontal and vertical lines will be moved - by up to half a pixel to make them look cleaner when vector + ment will be done: horizontal and vertical lines will be moved + by up to half a pixel to make them look cleaner when vector anti-aliasing is enabled. If set to "cad", a slightly different stroke adjustment algorithm will be used to ensure that lines of the same original width will always have the same adjusted width - (at the expense of allowing gaps and overlaps between adjacent + (at the expense of allowing gaps and overlaps between adjacent lines). This defaults to "yes". forceAccurateTiling yes | no - If this is set to "yes", the TilingType is forced to 2 (no dis- - tortion) for all tiling patterns, regardless of the setting in + If this is set to "yes", the TilingType is forced to 2 (no dis- + tortion) for all tiling patterns, regardless of the setting in the pattern dictionary. This defaults to "no". screenType dispersed | clustered | stochasticClustered - Sets the halftone screen type, which will be used when generat- - ing a monochrome (1-bit) bitmap. The three options are dis- - persed-dot dithering, clustered-dot dithering (with a round dot - and 45-degree screen angle), and stochastic clustered-dot - dithering. By default, "stochasticClustered" is used for reso- + Sets the halftone screen type, which will be used when generat- + ing a monochrome (1-bit) bitmap. The three options are dis- + persed-dot dithering, clustered-dot dithering (with a round dot + and 45-degree screen angle), and stochastic clustered-dot + dithering. By default, "stochasticClustered" is used for reso- lutions of 300 dpi and higher, and "dispersed" is used for reso- lutions lower then 300 dpi. screenSize integer - Sets the size of the (square) halftone screen threshold matrix. - By default, this is 4 for dispersed-dot dithering, 10 for clus- - tered-dot dithering, and 100 for stochastic clustered-dot + Sets the size of the (square) halftone screen threshold matrix. + By default, this is 4 for dispersed-dot dithering, 10 for clus- + tered-dot dithering, and 100 for stochastic clustered-dot dithering. screenDotRadius integer - Sets the halftone screen dot radius. This is only used when - screenType is set to stochasticClustered, and it defaults to 2. - In clustered-dot mode, the dot radius is half of the screen + Sets the halftone screen dot radius. This is only used when + screenType is set to stochasticClustered, and it defaults to 2. + In clustered-dot mode, the dot radius is half of the screen size. Dispersed-dot dithering doesn't have a dot radius. screenGamma float Sets the halftone screen gamma correction parameter. Gamma val- - ues greater than 1 make the output brighter; gamma values less + ues greater than 1 make the output brighter; gamma values less than 1 make it darker. The default value is 1. screenBlackThreshold float - When halftoning, all values below this threshold are forced to + When halftoning, all values below this threshold are forced to solid black. This parameter is a floating point value between 0 (black) and 1 (white). The default value is 0. screenWhiteThreshold float - When halftoning, all values above this threshold are forced to + When halftoning, all values above this threshold are forced to solid white. This parameter is a floating point value between 0 (black) and 1 (white). The default value is 1. minLineWidth float - Set the minimum line width, in device pixels. This affects the - rasterizer only, not the PostScript converter (except when it - uses rasterization to handle transparency). The default value + Set the minimum line width, in device pixels. This affects the + rasterizer only, not the PostScript converter (except when it + uses rasterization to handle transparency). The default value is 0 (no minimum). enablePathSimplification yes | no - If set to "yes", simplify paths by removing points where it - won't make a significant difference to the shape. The default + If set to "yes", simplify paths by removing points where it + won't make a significant difference to the shape. The default value is "no". overprintPreview yes | no If set to "yes", generate overprint preview output, honoring the - OP/op/OPM settings in the PDF file. Ignored for non-CMYK out- + OP/op/OPM settings in the PDF file. Ignored for non-CMYK out- put. The default value is "no". VIEWER SETTINGS These settings only apply to the Xpdf GUI PDF viewer. initialZoom percentage | page | width - Sets the initial zoom factor. A number specifies a zoom per- - centage, where 100 means 72 dpi. You may also specify 'page', - to fit the page to the window size, or 'width', to fit the page + Sets the initial zoom factor. A number specifies a zoom per- + centage, where 100 means 72 dpi. You may also specify 'page', + to fit the page to the window size, or 'width', to fit the page width to the window width. defaultFitZoom percentage If xpdf is started with fit-page or fit-width zoom and no window - geometry, it will calculate a desired window size based on the - PDF page size and this defaultFitZoom value. I.e., the window - size will be chosen such that exactly one page will fit in the - window at this zoom factor (which must be a percentage). The + geometry, it will calculate a desired window size based on the + PDF page size and this defaultFitZoom value. I.e., the window + size will be chosen such that exactly one page will fit in the + window at this zoom factor (which must be a percentage). The default value is based on the screen resolution. initialDisplayMode single | continuous | sideBySideSingle | sideBySide- @@ -515,23 +530,23 @@ VIEWER SETTINGS "no", xpdf opens with the toolbar hidden. The default is "yes". initialSidebarState yes | no - If set to "yes", xpdf opens with the sidebar (tabs, outline, - etc.) visible. If set to "no", xpdf opens with the sidebar + If set to "yes", xpdf opens with the sidebar (tabs, outline, + etc.) visible. If set to "no", xpdf opens with the sidebar collapsed. The default is "yes". initialSidebarWidth width - Sets the initial sidebar width, in pixels. This is only rele- - vant if initialSidebarState is "yes". The default value is + Sets the initial sidebar width, in pixels. This is only rele- + vant if initialSidebarState is "yes". The default value is zero, which tells xpdf to use an internal default size. initialSelectMode block | linear - Sets the initial selection mode. The default setting is "lin- + Sets the initial selection mode. The default setting is "lin- ear". paperColor color Set the "paper color", i.e., the background of the page display. - The color can be #RRGGBB (hexadecimal) or a named color. This - option will not work well with PDF files that do things like + The color can be #RRGGBB (hexadecimal) or a named color. This + option will not work well with PDF files that do things like filling in white behind the text. matteColor color @@ -540,7 +555,7 @@ VIEWER SETTINGS a named color. fullScreenMatteColor color - Set the matte color for full-screen mode. The color can be + Set the matte color for full-screen mode. The color can be #RRGGBB (hexadecimal) or a named color. selectionColor color @@ -548,14 +563,14 @@ VIEWER SETTINGS or a named color. reverseVideoInvertImages yes | no - If set to "no", xpdf's reverse-video mode inverts text and vec- - tor graphic content, but not images. If set to "yes", xpdf + If set to "no", xpdf's reverse-video mode inverts text and vec- + tor graphic content, but not images. If set to "yes", xpdf inverts images as well. The default is "no". popupMenuCmd title command ... - Add a command to the popup menu. Title is the text to be dis- - played in the menu. Command is an Xpdf command (see the COM- - MANDS section of the xpdf(1) man page for details). Multiple + Add a command to the popup menu. Title is the text to be dis- + played in the menu. Command is an Xpdf command (see the COM- + MANDS section of the xpdf(1) man page for details). Multiple commands are separated by whitespace. maxTileWidth pixels @@ -563,11 +578,11 @@ VIEWER SETTINGS ing pages. This defaults to 1500. maxTileHeight pixels - Set the maximum height of tiles to be used by xpdf when raster- + Set the maximum height of tiles to be used by xpdf when raster- izing pages. This defaults to 1500. tileCacheSize tiles - Set the maximum number of tiles to be cached by xpdf when ras- + Set the maximum number of tiles to be cached by xpdf when ras- terizing pages. This defaults to 10. workerThreads numThreads @@ -575,16 +590,16 @@ VIEWER SETTINGS izing pages. This defaults to 1. launchCommand command - Sets the command executed when you click on a "launch"-type - link. The intent is for the command to be a program/script - which determines the file type and runs the appropriate viewer. - The command line will consist of the file to be launched, fol- - lowed by any parameters specified with the link. Do not use - "%s" in "command". By default, this is unset, and Xpdf will + Sets the command executed when you click on a "launch"-type + link. The intent is for the command to be a program/script + which determines the file type and runs the appropriate viewer. + The command line will consist of the file to be launched, fol- + lowed by any parameters specified with the link. Do not use + "%s" in "command". By default, this is unset, and Xpdf will simply try to execute the file (after prompting the user). movieCommand command - Sets the command executed when you click on a movie annotation. + Sets the command executed when you click on a movie annotation. The string "%s" will be replaced with the movie file name. This has no default value. @@ -592,7 +607,7 @@ VIEWER SETTINGS Sets the default printer used in the viewer's print dialog. bind modifiers-key context command ... - Add a key or mouse button binding. Modifiers can be zero or + Add a key or mouse button binding. Modifiers can be zero or more of: shift- @@ -628,14 +643,14 @@ VIEWER SETTINGS overLink / offLink (mouse over link or not) scrLockOn / scrLockOff (scroll lock on/off) - The context string can include only one of each pair in the + The context string can include only one of each pair in the above list. - Command is an Xpdf command (see the COMMANDS section of the - xpdf(1) man page for details). Multiple commands are separated + Command is an Xpdf command (see the COMMANDS section of the + xpdf(1) man page for details). Multiple commands are separated by whitespace. - The bind command replaces any existing binding, but only if it + The bind command replaces any existing binding, but only if it was defined for the exact same modifiers, key, and context. All tokens (modifiers, key, context, commands) are case-sensitive. @@ -653,10 +668,10 @@ VIEWER SETTINGS See the xpdf(1) man page for more examples. unbind modifiers-key context - Removes a key binding established with the bind command. This - is most useful to remove default key bindings before establish- - ing new ones (e.g., if the default key binding is given for - "any" context, and you want to create new key bindings for mul- + Removes a key binding established with the bind command. This + is most useful to remove default key bindings before establish- + ing new ones (e.g., if the default key binding is given for + "any" context, and you want to create new key bindings for mul- tiple contexts). tabStateFile path @@ -665,17 +680,33 @@ VIEWER SETTINGS MISCELLANEOUS SETTINGS drawAnnotations yes | no - If set to "no", annotations will not be drawn or printed. The + If set to "no", annotations will not be drawn or printed. The default value is "yes". drawFormFields yes | no - If set to "no", form fields will not be drawn or printed. The + If set to "no", form fields will not be drawn or printed. The default value is "yes". + enableXFA yes | no + If an XFA form is present, and this option is set to "yes", Xpdf + will parse the XFA form and use certain XFA information to over- + ride AcroForm information. If set to "no", the XFA form will + not be read. The default value is "yes". + + savePageNumbers yes | no + If set to "yes", xpdf will save the current page numbers of all + open files in ~/.xpdf.pages when the files are closed (or when + quitting xpdf). Next time the file is opened, the last-viewed + page number will be restored. The default value is "yes". + printCommands yes | no - If set to "yes", drawing commands are printed as they're exe- + If set to "yes", drawing commands are printed as they're exe- cuted (useful for debugging). This defaults to "no". + printStatusInfo + If set to "yes", print a status message (to stdout) before each + page is processed. This defaults to "no". + errQuiet yes | no If set to "yes", this suppresses all error and warning messages from all of the Xpdf tools. This defaults to "no". @@ -733,7 +764,7 @@ EXAMPLES FILES - /usr/local/etc/xpdfrc + /etc/xpdfrc This is the default location for the system-wide configuration file. Depending on build options, it may be placed elsewhere. @@ -742,7 +773,7 @@ FILES read in place of the system-wide file. AUTHOR - The Xpdf software and documentation are copyright 1996-2021 Glyph & + The Xpdf software and documentation are copyright 1996-2022 Glyph & Cog, LLC. SEE ALSO @@ -752,4 +783,4 @@ SEE ALSO - 28 Jan 2021 xpdfrc(5) + 18 Apr 202 xpdfrc(5) diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt index 076cfafb247..fd61b25903c 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt +++ b/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt @@ -20,6 +20,8 @@ add_library(fofi_objs OBJECT FoFiType1.cc FoFiType1C.cc ) +set_property(TARGET fofi_objs + PROPERTY POSITION_INDEPENDENT_CODE True) add_library(fofi $<TARGET_OBJECTS:fofi_objs> diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc index b4f0a061be9..b6a13390b40 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc @@ -405,7 +405,9 @@ void FoFiType1C::convertToType1(char *psName, const char **newEncoding, eexecWrite(&eb, "/password 5839 def\n"); if (privateDicts[0].nBlueValues) { eexecWrite(&eb, "/BlueValues ["); - for (i = 0; i < privateDicts[0].nBlueValues; ++i) { + // number of entries must be even + int n = privateDicts[0].nBlueValues & ~1; + for (i = 0; i < n; ++i) { buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "", privateDicts[0].blueValues[i]); eexecWrite(&eb, buf->getCString()); @@ -415,7 +417,9 @@ void FoFiType1C::convertToType1(char *psName, const char **newEncoding, } if (privateDicts[0].nOtherBlues) { eexecWrite(&eb, "/OtherBlues ["); - for (i = 0; i < privateDicts[0].nOtherBlues; ++i) { + // number of entries must be even + int n = privateDicts[0].nOtherBlues & ~1; + for (i = 0; i < n; ++i) { buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "", privateDicts[0].otherBlues[i]); eexecWrite(&eb, buf->getCString()); @@ -425,7 +429,9 @@ void FoFiType1C::convertToType1(char *psName, const char **newEncoding, } if (privateDicts[0].nFamilyBlues) { eexecWrite(&eb, "/FamilyBlues ["); - for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) { + // number of entries must be even + int n = privateDicts[0].nFamilyBlues & ~1; + for (i = 0; i < n; ++i) { buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "", privateDicts[0].familyBlues[i]); eexecWrite(&eb, buf->getCString()); @@ -435,7 +441,9 @@ void FoFiType1C::convertToType1(char *psName, const char **newEncoding, } if (privateDicts[0].nFamilyOtherBlues) { eexecWrite(&eb, "/FamilyOtherBlues ["); - for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) { + // number of entries must be even + int n = privateDicts[0].nFamilyOtherBlues & ~1; + for (i = 0; i < n; ++i) { buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "", privateDicts[0].familyOtherBlues[i]); eexecWrite(&eb, buf->getCString()); diff --git a/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt index 0a1c56b0ebd..f3f6932eaed 100644 --- a/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt +++ b/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt @@ -22,6 +22,8 @@ add_library(goo_objs OBJECT parseargs.c Trace.cc ) +set_property(TARGET goo_objs + PROPERTY POSITION_INDEPENDENT_CODE True) add_library(goo $<TARGET_OBJECTS:goo_objs> diff --git a/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc b/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc index 570f4e7ab13..c2e7512e188 100644 --- a/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc +++ b/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc @@ -54,16 +54,23 @@ GString *getHomeDir() { //---------- VMS ---------- return new GString("SYS$LOGIN:"); -#elif defined(__EMX__) || defined(_WIN32) - //---------- OS/2+EMX and Win32 ---------- +#elif defined(_WIN32) + //---------- Win32 ---------- char *s; GString *ret; -#ifdef _WIN32 if ((s = getenv("USERPROFILE"))) -#else + ret = new GString(s); + else + ret = new GString("."); + return ret; + +#elif defined(__EMX__) + //---------- OS/2+EMX ---------- + char *s; + GString *ret; + if ((s = getenv("HOME"))) -#endif ret = new GString(s); else ret = new GString("."); @@ -335,11 +342,11 @@ GString *makePathAbsolute(GString *path) { #elif defined(_WIN32) //---------- Win32 ---------- - char buf[_MAX_PATH]; + char buf[MAX_PATH]; char *fp; buf[0] = '\0'; - if (!GetFullPathNameA(path->getCString(), _MAX_PATH, buf, &fp)) { + if (!GetFullPathNameA(path->getCString(), MAX_PATH, buf, &fp)) { path->clear(); return path; } @@ -398,6 +405,19 @@ GString *makePathAbsolute(GString *path) { #endif } +GBool pathIsFile(const char *path) { +#ifdef _WIN32 + wchar_t wPath[winMaxLongPath + 1]; + fileNameToUCS2(path, wPath, winMaxLongPath + 1); + DWORD attr = GetFileAttributesW(wPath); + return attr != INVALID_FILE_ATTRIBUTES && + !(attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)); +#else + struct stat statBuf; + return stat(path, &statBuf) == 0 && S_ISREG(statBuf.st_mode); +#endif +} + time_t getModTime(char *fileName) { #ifdef _WIN32 //~ should implement this, but it's (currently) only used in xpdf @@ -613,16 +633,16 @@ FILE *openFile(const char *path, const char *mode) { #if defined(_WIN32) return fopen(path, mode); #if 0 - wchar_t wPath[_MAX_PATH + 1]; + wchar_t wPath[winMaxLongPath + 1]; wchar_t wMode[8]; int i; - fileNameToUCS2(path, wPath, sizeof(wPath) / sizeof(wchar_t)); + fileNameToUCS2(path, wPath, winMaxLongPath + 1); for (i = 0; mode[i] && i < sizeof(wMode)/sizeof(wchar_t) - 1; ++i) { wMode[i] = (wchar_t)(mode[i] & 0xff); } wMode[i] = (wchar_t)0; - readWindowsShortcut(wPath, _MAX_PATH + 1); + readWindowsShortcut(wPath, winMaxLongPath + 1); return _wfopen(wPath, wMode); #endif /* 0 */ #elif defined(VMS) @@ -663,8 +683,8 @@ void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) { fprintf(stderr, "IPersistFile.Load failed: 0x%08x\n", hres); exit(1); } - wchar_t target[_MAX_PATH + 1]; - hres = shellLink->GetPath(target, _MAX_PATH + 1, NULL, 0); + wchar_t target[winMaxLongPath + 1]; + hres = shellLink->GetPath(target, winMaxLongPath + 1, NULL, 0); if (FAILED(hres)) { return; } @@ -682,6 +702,10 @@ void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) { int makeDir(const char *path, int mode) { #ifdef _WIN32 + /* + wchar_t wPath[winMaxLongPath + 1]; + return _wmkdir(fileNameToUCS2(path, wPath, winMaxLongPath + 1)); + */ return _mkdir(path); #else return mkdir(path, (mode_t)mode); diff --git a/Build/source/libs/xpdf/xpdf-src/goo/gfile.h b/Build/source/libs/xpdf/xpdf-src/goo/gfile.h index 2075d731a6c..d0d2ad6f9e1 100644 --- a/Build/source/libs/xpdf/xpdf-src/goo/gfile.h +++ b/Build/source/libs/xpdf/xpdf-src/goo/gfile.h @@ -30,6 +30,12 @@ #endif #include "gtypes.h" +// Windows 10 supports long paths - with a registry setting, and only +// with Unicode (...W) functions. +#ifdef _WIN32 +# define winMaxLongPath 32767 +#endif + class GString; //------------------------------------------------------------------------ @@ -55,6 +61,9 @@ extern GBool isAbsolutePath(char *path); // relative) or prepending user's directory (if path starts with '~'). extern GString *makePathAbsolute(GString *path); +// Returns true if [path] exists and is a regular file. +extern GBool pathIsFile(const char *path); + // Get the modification time for <fileName>. Returns 0 if there is an // error. extern time_t getModTime(char *fileName); @@ -91,6 +100,14 @@ extern wchar_t *fileNameToUCS2(const char *path, wchar_t *out, size_t outSize); // UCS-2 and calls _wfopen(). On other OSes, this simply calls fopen(). extern FILE *openFile(const char *path, const char *mode); +#if 0 +#ifdef _WIN32 +// If [wPath] is a Windows shortcut (.lnk file), read the target path +// and store it back into [wPath]. +extern void readWindowsShortcut(wchar_t *wPath, size_t wPathSize); +#endif +#endif /* 0 */ + // Create a directory. On Windows, this converts the path from UTF-8 // to UCS-2 and calls _wmkdir(), ignoring the mode argument. On other // OSes, this simply calls mkdir(). diff --git a/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt index f84968cfb2a..4ac14edc459 100644 --- a/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt +++ b/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt @@ -40,6 +40,8 @@ if (HAVE_SPLASH) SplashXPathScanner.cc ${DTYPE_SRCS} ) + set_property(TARGET splash_objs + PROPERTY POSITION_INDEPENDENT_CODE True) add_library(splash $<TARGET_OBJECTS:splash_objs> diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc b/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc index 343db796fb2..4afe21b4a25 100644 --- a/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc +++ b/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc @@ -469,6 +469,12 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, if (pipe->noTransparency && !state->blendFunc) { + //----- handle overprint + + if (overprintMaskPtr) { + *overprintMaskPtr++ = 0xffffffff; + } + //----- result color switch (bitmap->mode) { @@ -650,7 +656,19 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, // This path is only used when Splash::composite() is called to // composite a non-isolated group onto the backdrop. In this // case, shape is the source (group) alpha. - t = (aDest * 255) / shape - aDest; + // + // In a nested non-isolated group, i.e., if the destination is + // also a non-isolated group (state->inNonIsolatedGroup), we + // need to compute the corrected alpha, because the + // destination is is storing group alpha (same computation as + // blitCorrectedAlpha). + if (alpha0Ptr) { + t = *alpha0Ptr; + t = (Guchar)(aDest + t - div255(aDest * t)); + } else { + t = aDest; + } + t = (t * 255) / shape - t; switch (bitmap->mode) { #if SPLASH_CMYK case splashModeCMYK8: @@ -3916,10 +3934,13 @@ class ImageMaskScaler { public: // Set up a MaskScaler to scale from [srcWidth]x[srcHeight] to - // [scaledWidth]x[scaledHeight]. + // [scaledWidth]x[scaledHeight]. The [interpolate] flag controls + // filtering on upsampling, and the [antialias] flag controls + // filtering on downsampling. ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, int aSrcWidth, int aSrcHeight, - int aScaledWidth, int aScaledHeight, GBool aInterpolate); + int aScaledWidth, int aScaledHeight, + GBool aInterpolate, GBool aAntialias); ~ImageMaskScaler(); @@ -3934,10 +3955,13 @@ public: private: void vertDownscaleHorizDownscale(); + void vertDownscaleHorizDownscaleThresh(); void vertDownscaleHorizUpscaleNoInterp(); void vertDownscaleHorizUpscaleInterp(); + void vertDownscaleHorizUpscaleThresh(); void vertUpscaleHorizDownscaleNoInterp(); void vertUpscaleHorizDownscaleInterp(); + void vertUpscaleHorizDownscaleThresh(); void vertUpscaleHorizUpscaleNoInterp(); void vertUpscaleHorizUpscaleInterp(); @@ -3979,7 +4003,7 @@ private: ImageMaskScaler::ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, int aSrcWidth, int aSrcHeight, int aScaledWidth, int aScaledHeight, - GBool aInterpolate) { + GBool aInterpolate, GBool aAntialias) { tmpBuf0 = NULL; tmpBuf1 = NULL; tmpBuf2 = NULL; @@ -4002,9 +4026,15 @@ ImageMaskScaler::ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, tmpBuf0 = (Guchar *)gmalloc(srcWidth); accBuf = (Guint *)gmallocn(srcWidth, sizeof(Guint)); if (scaledWidth <= srcWidth) { - scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscale; + if (!aAntialias) { + scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscaleThresh; + } else { + scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscale; + } } else { - if (aInterpolate) { + if (!aAntialias) { + scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleThresh; + } else if (aInterpolate) { scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleInterp; } else { scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp; @@ -4016,7 +4046,14 @@ ImageMaskScaler::ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, yq = scaledHeight % srcHeight; yt = 0; yn = 0; - if (aInterpolate) { + if (!aAntialias) { + tmpBuf0 = (Guchar *)gmalloc(srcWidth); + if (scaledWidth <= srcWidth) { + scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleThresh; + } else { + scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp; + } + } else if (aInterpolate) { yInvScale = (SplashCoord)srcHeight / (SplashCoord)scaledHeight; tmpBuf0 = (Guchar *)gmalloc(srcWidth); tmpBuf1 = (Guchar *)gmalloc(srcWidth); @@ -4099,6 +4136,43 @@ void ImageMaskScaler::vertDownscaleHorizDownscale() { } } +void ImageMaskScaler::vertDownscaleHorizDownscaleThresh() { + //--- vert downscale + int yStep = yp; + yt += yq; + if (yt >= scaledHeight) { + yt -= scaledHeight; + ++yStep; + } + memset(accBuf, 0, srcWidth * sizeof(Guint)); + for (int i = 0; i < yStep; ++i) { + (*src)(srcData, tmpBuf0); + for (int j = 0; j < srcWidth; ++j) { + accBuf[j] += tmpBuf0[j]; + } + } + + //--- horiz downscale + int acc; + int xt = 0; + int unscaledIdx = 0; + for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) { + int xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + acc = 0; + for (int i = 0; i < xStep; ++i) { + acc += accBuf[unscaledIdx]; + ++unscaledIdx; + } + line[scaledIdx] = acc > ((xStep * yStep) >> 1) ? (Guchar)255 : (Guchar)0; + } +} + void ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp() { //--- vert downscale int yStep = yp; @@ -4169,6 +4243,40 @@ void ImageMaskScaler::vertDownscaleHorizUpscaleInterp() { } } +void ImageMaskScaler::vertDownscaleHorizUpscaleThresh() { + //--- vert downscale + int yStep = yp; + yt += yq; + if (yt >= scaledHeight) { + yt -= scaledHeight; + ++yStep; + } + memset(accBuf, 0, srcWidth * sizeof(Guint)); + for (int i = 0; i < yStep; ++i) { + (*src)(srcData, tmpBuf0); + for (int j = 0; j < srcWidth; ++j) { + accBuf[j] += tmpBuf0[j]; + } + } + + //--- horiz upscale + int xt = 0; + int scaledIdx = 0; + for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) { + int xStep = xp; + xt += xq; + if (xt >= srcWidth) { + xt -= srcWidth; + ++xStep; + } + Guchar buf = accBuf[srcIdx] > (Guint)(yStep >> 1) ? (Guchar)255 : (Guchar)0; + for (int i = 0; i < xStep; ++i) { + line[scaledIdx] = buf; + ++scaledIdx; + } + } +} + void ImageMaskScaler::vertUpscaleHorizDownscaleNoInterp() { //--- vert upscale if (yn == 0) { @@ -4256,6 +4364,40 @@ void ImageMaskScaler::vertUpscaleHorizDownscaleInterp() { } } +void ImageMaskScaler::vertUpscaleHorizDownscaleThresh() { + //--- vert upscale + if (yn == 0) { + yn = yp; + yt += yq; + if (yt >= srcHeight) { + yt -= srcHeight; + ++yn; + } + (*src)(srcData, tmpBuf0); + } + --yn; + + //--- horiz downscale + int acc; + int xt = 0; + int unscaledIdx = 0; + for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) { + int xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + acc = 0; + for (int i = 0; i < xStep; ++i) { + acc += tmpBuf0[unscaledIdx]; + ++unscaledIdx; + } + line[scaledIdx] = acc > (xStep >> 1) ? (Guchar)255 : (Guchar)0; + } +} + void ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp() { //--- vert upscale if (yn == 0) { @@ -4585,8 +4727,8 @@ SplashError Splash::clipToPath(SplashPath *path, GBool eo) { return state->clipToPath(path, eo); } -void Splash::setSoftMask(SplashBitmap *softMask) { - state->setSoftMask(softMask); +void Splash::setSoftMask(SplashBitmap *softMask, GBool deleteBitmap) { + state->setSoftMask(softMask, deleteBitmap); } void Splash::setInTransparencyGroup(SplashBitmap *groupBackBitmapA, @@ -4608,6 +4750,41 @@ void Splash::forceDeferredInit(int y, int h) { useDestRow(y + h - 1); } +// Check that alpha is 0 in the specified rectangle. +// NB: This doesn't work correctly in a non-isolated group, because +// the rasterizer temporarily stores alpha_g instead of alpha. +GBool Splash::checkTransparentRect(int x, int y, int w, int h) { + if (state->inNonIsolatedGroup) { + return gFalse; + } + + + if (!bitmap->alpha) { + return gFalse; + } + int yy0, yy1; + if (groupDestInitMode == splashGroupDestPreInit) { + yy0 = y; + yy1 = y + h - 1; + } else { + // both splashGroupDestInitZero and splashGroupDestInitCopy set + // alpha to zero, so anything outside of groupDestInit[YMin,YMax] + // will have alpha=0 + yy0 = (y > groupDestInitYMin) ? y : groupDestInitYMin; + yy1 = (y + h - 1 < groupDestInitYMax) ? y + h - 1 : groupDestInitYMax; + } + Guchar *alphaP = &bitmap->alpha[yy0 * bitmap->alphaRowSize + x]; + for (int yy = yy0; yy <= yy1; ++yy) { + for (int xx = 0; xx < w; ++xx) { + if (alphaP[xx] != 0) { + return gFalse; + } + } + alphaP += bitmap->getAlphaRowSize(); + } + return gTrue; +} + void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray) { state->setTransfer(red, green, blue, gray); @@ -5749,7 +5926,8 @@ struct SplashDrawImageMaskRowData { SplashError Splash::fillImageMask(GString *imageTag, SplashImageMaskSource src, void *srcData, int w, int h, SplashCoord *mat, - GBool glyphMode, GBool interpolate) { + GBool glyphMode, GBool interpolate, + GBool antialias) { if (debugMode) { printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", w, h, (double)mat[0], (double)mat[1], (double)mat[2], @@ -5763,28 +5941,35 @@ SplashError Splash::fillImageMask(GString *imageTag, //--- compute image bbox, check clipping GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; + GBool rot90Only = splashAbs(mat[0]) <= 0.0001 && splashAbs(mat[3]) <= 0.0001; GBool horizFlip = gFalse; GBool vertFlip = gFalse; int xMin, yMin, xMax, yMax; if (flipsOnly) { horizFlip = mat[0] < 0; vertFlip = mat[3] < 0; + if (horizFlip) { + getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); + } else { + getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); + } if (vertFlip) { - if (horizFlip) { // bottom-up, mirrored - getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); - getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); - } else { // bottom-up - getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); - getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); - } + getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); } else { - if (horizFlip) { // top-down, mirrored - getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); - getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); - } else { // top-down - getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); - getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); - } + getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); + } + } else if (rot90Only) { + horizFlip = mat[2] < 0; + vertFlip = mat[1] < 0; + if (horizFlip) { + getImageBounds(mat[2] + mat[4], mat[4], &xMin, &xMax); + } else { + getImageBounds(mat[4], mat[2] + mat[4], &xMin, &xMax); + } + if (vertFlip) { + getImageBounds(mat[1] + mat[5], mat[5], &yMin, &yMax); + } else { + getImageBounds(mat[5], mat[1] + mat[5], &yMin, &yMax); } } else { int xx = splashRound(mat[4]); // (0,0) @@ -5860,7 +6045,7 @@ SplashError Splash::fillImageMask(GString *imageTag, if (clipRes == splashClipAllInside) { drawRowFunc = &Splash::drawImageMaskRowNoClip; } else { - if (vectorAntialias) { + if (antialias) { drawRowFunc = &Splash::drawImageMaskRowClipAA; } else { drawRowFunc = &Splash::drawImageMaskRowClipNoAA; @@ -5873,7 +6058,7 @@ SplashError Splash::fillImageMask(GString *imageTag, int scaledWidth = xMax - xMin; int scaledHeight = yMax - yMin; ImageMaskScaler scaler(src, srcData, w, h, - scaledWidth, scaledHeight, interpolate); + scaledWidth, scaledHeight, interpolate, antialias); Guchar *tmpLine = NULL; if (horizFlip) { tmpLine = (Guchar *)gmalloc(scaledWidth); @@ -5912,6 +6097,50 @@ SplashError Splash::fillImageMask(GString *imageTag, gfree(tmpLine); } + //--- 90/270 rotation + } else if (rot90Only && !veryLarge) { + if (clipRes != splashClipAllOutside) { + + // scale the mask + int scaledWidth = yMax - yMin; + int scaledHeight = xMax - xMin; + ImageMaskScaler scaler(src, srcData, w, h, + scaledWidth, scaledHeight, interpolate, antialias); + Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); + Guchar *ptr = scaledMask; + for (int y = 0; y < scaledHeight; ++y) { + scaler.nextLine(); + memcpy(ptr, scaler.data(), scaledWidth); + ptr += scaledWidth; + } + + // draw it + Guchar *tmpLine = (Guchar *)gmalloc(scaledHeight); + for (int y = 0; y < scaledWidth; ++y) { + if (vertFlip) { + ptr = scaledMask + (scaledWidth - 1 - y); + } else { + ptr = scaledMask + y; + } + if (horizFlip) { + ptr += (scaledHeight - 1) * scaledWidth; + for (int x = 0; x < scaledHeight; ++x) { + tmpLine[x] = *ptr; + ptr -= scaledWidth; + } + } else { + for (int x = 0; x < scaledHeight; ++x) { + tmpLine[x] = *ptr; + ptr += scaledWidth; + } + } + (this->*drawRowFunc)(&dd, tmpLine, xMin, yMin + y, scaledHeight); + } + + gfree(tmpLine); + gfree(scaledMask); + } + //--- arbitrary transform } else { // estimate of size of scaled image @@ -5963,7 +6192,7 @@ SplashError Splash::fillImageMask(GString *imageTag, Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); if (downscaling) { ImageMaskScaler scaler(src, srcData, w, h, - scaledWidth, scaledHeight, interpolate); + scaledWidth, scaledHeight, interpolate, antialias); Guchar *ptr = scaledMask; for (int y = 0; y < scaledHeight; ++y) { scaler.nextLine(); @@ -5982,7 +6211,7 @@ SplashError Splash::fillImageMask(GString *imageTag, } // draw it - if (interpolate) { + if (interpolate && antialias) { drawImageMaskArbitraryInterp(scaledMask, &dd, drawRowFunc, invMat, scaledWidth, scaledHeight, @@ -6259,28 +6488,35 @@ SplashError Splash::drawImage(GString *imageTag, //--- compute image bbox, check clipping GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; + GBool rot90Only = splashAbs(mat[0]) <= 0.0001 && splashAbs(mat[3]) <= 0.0001; GBool horizFlip = gFalse; GBool vertFlip = gFalse; int xMin, yMin, xMax, yMax; if (flipsOnly) { horizFlip = mat[0] < 0; vertFlip = mat[3] < 0; + if (horizFlip) { + getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); + } else { + getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); + } if (vertFlip) { - if (horizFlip) { // bottom-up, mirrored - getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); - getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); - } else { // bottom-up - getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); - getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); - } + getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); } else { - if (horizFlip) { // top-down, mirrored - getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); - getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); - } else { // top-down - getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); - getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); - } + getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); + } + } else if (rot90Only) { + horizFlip = mat[2] < 0; + vertFlip = mat[1] < 0; + if (horizFlip) { + getImageBounds(mat[2] + mat[4], mat[4], &xMin, &xMax); + } else { + getImageBounds(mat[4], mat[2] + mat[4], &xMin, &xMax); + } + if (vertFlip) { + getImageBounds(mat[1] + mat[5], mat[5], &yMin, &yMax); + } else { + getImageBounds(mat[5], mat[1] + mat[5], &yMin, &yMax); } } else { int xx = splashRound(mat[4]); // (0,0) @@ -6435,6 +6671,83 @@ SplashError Splash::drawImage(GString *imageTag, delete scaler; } + //--- 90/270 rotation + } else if (rot90Only && !veryLarge) { + if (clipRes != splashClipAllOutside) { + + // scale the image + int scaledWidth = yMax - yMin; + int scaledHeight = xMax - xMin; + Guchar *scaledColor, *scaledAlpha; + GBool freeScaledImage; + getScaledImage(imageTag, src, srcData, w, h, nComps, + scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate, + &scaledColor, &scaledAlpha, &freeScaledImage); + + // draw it + Guchar *tmpLine = (Guchar *)gmallocn(scaledHeight, nComps); + Guchar *tmpAlphaLine = NULL; + if (srcAlpha) { + tmpAlphaLine = (Guchar *)gmalloc(scaledHeight); + } + for (int y = 0; y < scaledWidth; ++y) { + Guchar *ptr, *alphaPtr; + if (vertFlip) { + ptr = scaledColor + (scaledWidth - 1 - y) * nComps; + if (srcAlpha) { + alphaPtr = scaledAlpha + (scaledWidth - 1 - y); + } + } else { + ptr = scaledColor + y * nComps; + if (srcAlpha) { + alphaPtr = scaledAlpha + y; + } + } + if (horizFlip) { + ptr += (scaledHeight - 1) * scaledWidth * nComps; + Guchar *q = tmpLine; + for (int x = 0; x < scaledHeight; ++x) { + for (int i = 0; i < nComps; ++i) { + *q++ = ptr[i]; + } + ptr -= scaledWidth * nComps; + } + if (srcAlpha) { + alphaPtr += (scaledHeight - 1) * scaledWidth; + q = tmpAlphaLine; + for (int x = 0; x < scaledHeight; ++x) { + *q++ = *alphaPtr; + alphaPtr -= scaledWidth; + } + } + } else { + Guchar *q = tmpLine; + for (int x = 0; x < scaledHeight; ++x) { + for (int i = 0; i < nComps; ++i) { + *q++ = ptr[i]; + } + ptr += scaledWidth * nComps; + } + if (srcAlpha) { + q = tmpAlphaLine; + for (int x = 0; x < scaledHeight; ++x) { + *q++ = *alphaPtr; + alphaPtr += scaledWidth; + } + } + } + (this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, + xMin, yMin + y, scaledHeight); + } + + gfree(tmpLine); + gfree(tmpAlphaLine); + if (freeScaledImage) { + gfree(scaledColor); + gfree(scaledAlpha); + } + } + //--- arbitrary transform } else { // estimate of size of scaled image @@ -6518,14 +6831,13 @@ ImageScaler *Splash::getImageScaler(GString *imageTag, GBool srcAlpha, GBool interpolate) { // Notes: // - // * If the scaled image width or height is greater than 2000, we - // don't cache it. + // * If the scaled image is more than 8 Mpixels, we don't cache it. // // * Caching is done on the third consecutive use (second // consecutive reuse) of an image; this avoids overhead on the // common case of single-use images. - if (scaledWidth < 2000 && scaledHeight < 2000 && + if (scaledWidth < 8000000 / scaledHeight && imageCache->match(imageTag, scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate)) { if (imageCache->colorData) { @@ -6570,13 +6882,12 @@ void Splash::getScaledImage(GString *imageTag, GBool *freeScaledImage) { // Notes: // - // * If the scaled image width or height is greater than 2000, we - // don't cache it. + // * If the scaled image is more than 8 Mpixels, we don't cache it. // // * This buffers the whole image anyway, so there's no reason to // skip caching on the first reuse. - if (scaledWidth >= 2000 || scaledHeight >= 2000) { + if (scaledWidth >= 8000000 / scaledHeight) { int lineSize; if (scaledWidth < INT_MAX / nComps) { lineSize = scaledWidth * nComps; diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Splash.h b/Build/source/libs/xpdf/xpdf-src/splash/Splash.h index d6cc33a5fad..9622b07fc27 100644 --- a/Build/source/libs/xpdf/xpdf-src/splash/Splash.h +++ b/Build/source/libs/xpdf/xpdf-src/splash/Splash.h @@ -182,12 +182,13 @@ public: SplashCoord x1, SplashCoord y1); // NB: uses untransformed coordinates. SplashError clipToPath(SplashPath *path, GBool eo); - void setSoftMask(SplashBitmap *softMask); + void setSoftMask(SplashBitmap *softMask, GBool deleteBitmap = gTrue); void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, int groupBackXA, int groupBackYA, SplashGroupDestInitMode groupDestInitModeA, GBool nonIsolated, GBool knockout); void forceDeferredInit(int y, int h); + GBool checkTransparentRect(int x, int y, int w, int h); void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); void setOverprintMask(Guint overprintMask); void setEnablePathSimplification(GBool en); @@ -228,11 +229,15 @@ public: // [x' y' 1] = [x y 1] * mat // Note that the Splash y axis points downward, and the image source // is assumed to produce pixels in raster order, starting from the - // top line. + // top line. If [interpolate] is false, no filtering is done when + // upsampling. If [antialias] is false, no filtering is done when + // upsampling (overriding the [interpolate] flag), and threshold + // filtering is done when downsampling. SplashError fillImageMask(GString *imageTag, SplashImageMaskSource src, void *srcData, int w, int h, SplashCoord *mat, - GBool glyphMode, GBool interpolate); + GBool glyphMode, GBool interpolate, + GBool antialias); // Draw an image. This will read <h> lines of <w> pixels from // <src>, starting with the top line. These pixels are assumed to diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc index 74421c48a4a..7fc510439b1 100644 --- a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc +++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc @@ -63,6 +63,21 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, deleteSoftMask = gFalse; inNonIsolatedGroup = gFalse; inKnockoutGroup = gFalse; +#if SPLASH_CMYK + rgbTransferR = (Guchar *)gmalloc(8 * 256); + rgbTransferG = rgbTransferR + 256; + rgbTransferB = rgbTransferG + 256; + grayTransfer = rgbTransferB + 256; + cmykTransferC = grayTransfer + 256; + cmykTransferM = cmykTransferC + 256; + cmykTransferY = cmykTransferM + 256; + cmykTransferK = cmykTransferY + 256; +#else + rgbTransferR = (Guchar *)gmalloc(4 * 256); + rgbTransferG = rgbTransferR + 256; + rgbTransferB = rgbTransferG + 256; + grayTransfer = rgbTransferB + 256; +#endif for (i = 0; i < 256; ++i) { rgbTransferR[i] = (Guchar)i; rgbTransferG[i] = (Guchar)i; @@ -75,6 +90,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, cmykTransferK[i] = (Guchar)i; #endif } + transferIsShared = gFalse; overprintMask = 0xffffffff; enablePathSimplification = gFalse; next = NULL; @@ -110,6 +126,21 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, deleteSoftMask = gFalse; inNonIsolatedGroup = gFalse; inKnockoutGroup = gFalse; +#if SPLASH_CMYK + rgbTransferR = (Guchar *)gmalloc(8 * 256); + rgbTransferG = rgbTransferR + 256; + rgbTransferB = rgbTransferG + 256; + grayTransfer = rgbTransferB + 256; + cmykTransferC = grayTransfer + 256; + cmykTransferM = cmykTransferC + 256; + cmykTransferY = cmykTransferM + 256; + cmykTransferK = cmykTransferY + 256; +#else + rgbTransferR = (Guchar *)gmalloc(4 * 256); + rgbTransferG = rgbTransferR + 256; + rgbTransferB = rgbTransferG + 256; + grayTransfer = rgbTransferB + 256; +#endif for (i = 0; i < 256; ++i) { rgbTransferR[i] = (Guchar)i; rgbTransferG[i] = (Guchar)i; @@ -122,6 +153,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, cmykTransferK[i] = (Guchar)i; #endif } + transferIsShared = gFalse; overprintMask = 0xffffffff; enablePathSimplification = gFalse; next = NULL; @@ -156,16 +188,17 @@ SplashState::SplashState(SplashState *state) { deleteSoftMask = gFalse; inNonIsolatedGroup = state->inNonIsolatedGroup; inKnockoutGroup = state->inKnockoutGroup; - memcpy(rgbTransferR, state->rgbTransferR, 256); - memcpy(rgbTransferG, state->rgbTransferG, 256); - memcpy(rgbTransferB, state->rgbTransferB, 256); - memcpy(grayTransfer, state->grayTransfer, 256); + rgbTransferR = state->rgbTransferR; + rgbTransferG = state->rgbTransferG; + rgbTransferB = state->rgbTransferB; + grayTransfer = state->grayTransfer; #if SPLASH_CMYK - memcpy(cmykTransferC, state->cmykTransferC, 256); - memcpy(cmykTransferM, state->cmykTransferM, 256); - memcpy(cmykTransferY, state->cmykTransferY, 256); - memcpy(cmykTransferK, state->cmykTransferK, 256); + cmykTransferC = state->cmykTransferC; + cmykTransferM = state->cmykTransferM; + cmykTransferY = state->cmykTransferY; + cmykTransferK = state->cmykTransferK; #endif + transferIsShared = gTrue; overprintMask = state->overprintMask; enablePathSimplification = state->enablePathSimplification; next = NULL; @@ -179,6 +212,9 @@ SplashState::~SplashState() { if (!clipIsShared) { delete clip; } + if (!transferIsShared) { + gfree(rgbTransferR); + } if (deleteSoftMask && softMask) { delete softMask; } @@ -265,12 +301,12 @@ SplashError SplashState::clipToPath(SplashPath *path, GBool eo) { enablePathSimplification, strokeAdjust); } -void SplashState::setSoftMask(SplashBitmap *softMaskA) { +void SplashState::setSoftMask(SplashBitmap *softMaskA, GBool deleteBitmap) { if (deleteSoftMask) { delete softMask; } softMask = softMaskA; - deleteSoftMask = gTrue; + deleteSoftMask = deleteBitmap; } void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue, @@ -279,6 +315,24 @@ void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue, int i; #endif + if (transferIsShared) { +#if SPLASH_CMYK + rgbTransferR = (Guchar *)gmalloc(8 * 256); + rgbTransferG = rgbTransferR + 256; + rgbTransferB = rgbTransferG + 256; + grayTransfer = rgbTransferB + 256; + cmykTransferC = grayTransfer + 256; + cmykTransferM = cmykTransferC + 256; + cmykTransferY = cmykTransferM + 256; + cmykTransferK = cmykTransferY + 256; +#else + rgbTransferR = (Guchar *)gmalloc(4 * 256); + rgbTransferG = rgbTransferR + 256; + rgbTransferB = rgbTransferG + 256; + grayTransfer = rgbTransferB + 256; +#endif + transferIsShared = gFalse; + } memcpy(rgbTransferR, red, 256); memcpy(rgbTransferG, green, 256); memcpy(rgbTransferB, blue, 256); diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h index 38cb1188e94..be64b472333 100644 --- a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h +++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h @@ -81,7 +81,7 @@ public: SplashError clipToPath(SplashPath *path, GBool eo); // Set the soft mask bitmap. - void setSoftMask(SplashBitmap *softMaskA); + void setSoftMask(SplashBitmap *softMaskA, GBool deleteBitmap = gTrue); // Set the transfer function. void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); @@ -113,16 +113,17 @@ private: GBool deleteSoftMask; GBool inNonIsolatedGroup; GBool inKnockoutGroup; - Guchar rgbTransferR[256], - rgbTransferG[256], - rgbTransferB[256]; - Guchar grayTransfer[256]; + Guchar *rgbTransferR; + Guchar *rgbTransferG; + Guchar *rgbTransferB; + Guchar *grayTransfer; #if SPLASH_CMYK - Guchar cmykTransferC[256], - cmykTransferM[256], - cmykTransferY[256], - cmykTransferK[256]; + Guchar *cmykTransferC; + Guchar *cmykTransferM; + Guchar *cmykTransferY; + Guchar *cmykTransferK; #endif + GBool transferIsShared; Guint overprintMask; GBool enablePathSimplification; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc index b98ca2f0189..7b2b9855669 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc @@ -18,6 +18,7 @@ #include "gmempp.h" #include "GString.h" #include "GList.h" +#include "GlobalParams.h" #include "Error.h" #include "Object.h" #include "PDFDoc.h" @@ -348,13 +349,15 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { if (acroFormObjA->isDict()) { acroForm = new AcroForm(docA, acroFormObjA); - if (!acroFormObjA->dictLookup("XFA", &xfaObj)->isNull()) { - acroForm->xfaScanner = XFAScanner::load(&xfaObj); - if (!catalog->getNeedsRendering()) { - acroForm->isStaticXFA = gTrue; + if (globalParams->getEnableXFA()) { + if (!acroFormObjA->dictLookup("XFA", &xfaObj)->isNull()) { + acroForm->xfaScanner = XFAScanner::load(&xfaObj); + if (!catalog->getNeedsRendering()) { + acroForm->isStaticXFA = gTrue; + } } + xfaObj.free(); } - xfaObj.free(); if (acroFormObjA->dictLookup("NeedAppearances", &obj1)->isBool()) { acroForm->needAppearances = obj1.getBool(); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc index d7229a2fe86..82ef600be73 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc @@ -224,6 +224,11 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { } } obj1.free(); + // Acrobat ignores borders with unreasonable widths + if (borderWidth > 1 && (borderWidth > xMax - xMin || + borderWidth > yMax - yMin)) { + borderWidth = 0; + } if (dict->lookup("C", &obj1)->isArray() && (obj1.arrayGetLength() == 1 || obj1.arrayGetLength() == 3 || diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt index 7b515d1d036..63a8dec2875 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt @@ -23,6 +23,11 @@ if (HAVE_LCMS) else () set(COLOR_MANAGER_SOURCE "") endif () +if (WIN32) + set(MANIFEST "winLongPath.exe.manifest") +else () + set(MANIFEST "") +endif () add_library(xpdf_objs OBJECT AcroForm.cc @@ -70,10 +75,12 @@ add_library(xpdf_objs OBJECT XRef.cc Zoox.cc ) +set_property(TARGET xpdf_objs + PROPERTY POSITION_INDEPENDENT_CODE True) #--- object files needed by XpdfWidget -if ((QT4_FOUND OR Qt5Widgets_FOUND) +if ((QT4_FOUND OR Qt5Widgets_FOUND OR Qt6Widgets_FOUND) AND HAVE_SPLASH AND MULTITHREADED AND USE_EXCEPTIONS) if (HIGHLIGHTED_REGIONS) @@ -95,6 +102,8 @@ if ((QT4_FOUND OR Qt5Widgets_FOUND) TileMap.cc ${HIGHLIGHT_SRC} ) + set_property(TARGET xpdf_widget_objs + PROPERTY POSITION_INDEPENDENT_CODE True) endif () #--- pdftops @@ -107,6 +116,7 @@ if (HAVE_SPLASH) ShadingImage.cc SplashOutputDev.cc pdftops.cc + ${MANIFEST} ) target_link_libraries(pdftops goo fofi splash ${PAPER_LIBRARY} @@ -121,6 +131,7 @@ else () PreScanOutputDev.cc PSOutputDev.cc pdftops.cc + ${MANIFEST} ) target_link_libraries(pdftops goo fofi ${PAPER_LIBRARY} @@ -137,6 +148,7 @@ add_executable(pdftotext $<TARGET_OBJECTS:xpdf_objs> TextOutputDev.cc pdftotext.cc + ${MANIFEST} ) target_link_libraries(pdftotext goo fofi ${PAPER_LIBRARY} @@ -157,6 +169,7 @@ if (HAVE_SPLASH AND PNG_FOUND) TextOutputDev.cc WebFont.cc pdftohtml.cc + ${MANIFEST} ) target_link_libraries(pdftohtml goo fofi splash ${PAPER_LIBRARY} @@ -175,6 +188,7 @@ endif () add_executable(pdfinfo $<TARGET_OBJECTS:xpdf_objs> pdfinfo.cc + ${MANIFEST} ) target_link_libraries(pdfinfo goo fofi ${PAPER_LIBRARY} @@ -189,6 +203,7 @@ install(FILES ${PROJECT_SOURCE_DIR}/doc/pdfinfo.1 DESTINATION ${CMAKE_INSTALL_MA add_executable(pdffonts $<TARGET_OBJECTS:xpdf_objs> pdffonts.cc + ${MANIFEST} ) target_link_libraries(pdffonts goo fofi ${PAPER_LIBRARY} @@ -203,6 +218,7 @@ install(FILES ${PROJECT_SOURCE_DIR}/doc/pdffonts.1 DESTINATION ${CMAKE_INSTALL_M add_executable(pdfdetach $<TARGET_OBJECTS:xpdf_objs> pdfdetach.cc + ${MANIFEST} ) target_link_libraries(pdfdetach goo fofi ${PAPER_LIBRARY} @@ -220,6 +236,7 @@ if (HAVE_SPLASH) ShadingImage.cc SplashOutputDev.cc pdftoppm.cc + ${MANIFEST} ) target_link_libraries(pdftoppm goo fofi splash ${PAPER_LIBRARY} @@ -240,6 +257,7 @@ if (HAVE_SPLASH AND PNG_FOUND) ShadingImage.cc SplashOutputDev.cc pdftopng.cc + ${MANIFEST} ) target_link_libraries(pdftopng goo fofi splash ${PAPER_LIBRARY} @@ -259,6 +277,7 @@ add_executable(pdfimages $<TARGET_OBJECTS:xpdf_objs> ImageOutputDev.cc pdfimages.cc + ${MANIFEST} ) target_link_libraries(pdfimages goo fofi ${PAPER_LIBRARY} diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc index 6ea8fa89ff4..ddcbad55f07 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc @@ -623,7 +623,7 @@ void Catalog::loadPage2(int pg, int relPg, PageTreeNode *node) { // merge the PageAttrs attrs = new PageAttrs(node->parent ? node->parent->attrs : (PageAttrs *)NULL, - pageObj.getDict()); + pageObj.getDict(), xref); // if "Kids" exists, it's an internal node if (pageObj.dictLookup("Kids", &kidsObj)->isArray()) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc index 5eec7a9fc6c..0a2100fde9b 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc @@ -232,6 +232,10 @@ CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) { return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0); } +CharCodeToUnicode *CharCodeToUnicode::make16BitToUnicode(Unicode *toUnicode) { + return new CharCodeToUnicode(NULL, toUnicode, 65536, gTrue, NULL, 0, 0); +} + CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) { CharCodeToUnicode *ctu; GStringIndex idx; @@ -470,24 +474,17 @@ GBool CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, int offset) { CharCode oldLen, i; -#if 1 //~utf16 Unicode u[maxUnicodeString]; int uLen, j; -#else - Unicode u; - int j; -#endif if (code > 0xffffff) { // This is an arbitrary limit to avoid integer overflow issues. // (I've seen CMaps with mappings for <ffffffff>.) return; } -#if 1 //~utf16 if ((uLen = parseUTF16String(uStr, n, u)) == 0) { return; } -#endif if (code >= mapLen) { oldLen = mapLen; mapLen = mapLen ? 2 * mapLen : 256; @@ -499,7 +496,6 @@ void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, map[i] = 0; } } -#if 1 //~utf16 if (uLen == 1) { map[code] = u[0] + offset; } else { @@ -517,34 +513,6 @@ void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, sMap[sMapLen].len = uLen; ++sMapLen; } -#else //~utf16 - if (n <= 4) { - if (!parseHex(uStr, n, &u)) { - error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap"); - return; - } - map[code] = u + offset; - } else { - if (sMapLen >= sMapSize) { - sMapSize = sMapSize + 16; - sMap = (CharCodeToUnicodeString *) - greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); - } - map[code] = 0; - sMap[sMapLen].c = code; - if ((sMap[sMapLen].len = n / 4) > maxUnicodeString) { - sMap[sMapLen].len = maxUnicodeString; - } - for (j = 0; j < sMap[sMapLen].len; ++j) { - if (!parseHex(uStr + j*4, 4, &sMap[sMapLen].u[j])) { - error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap"); - return; - } - } - sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset; - ++sMapLen; - } -#endif //~utf16 } // Convert a UTF-16BE hex string into a sequence of up to diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h index c390a8c5c50..be9025107aa 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h @@ -49,6 +49,11 @@ public: // reference count to 1. static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode); + // Create the CharCode-to-Unicode mapping for a 16-bit font. + // <toUnicode> is an array of 65536 Unicode indexes. Sets the + // initial reference count to 1. + static CharCodeToUnicode *make16BitToUnicode(Unicode *toUnicode); + // Parse a ToUnicode CMap for an 8- or 16-bit font. static CharCodeToUnicode *parseCMap(GString *buf, int nBits); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc index ed98d9d165f..1539b8404bc 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc @@ -527,6 +527,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, xref = doc->getXRef(); subPage = gFalse; printCommands = globalParams->getPrintCommands(); + defaultFont = NULL; // start the resource stack res = new GfxResources(xref, resDict, NULL); @@ -574,6 +575,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, xref = doc->getXRef(); subPage = gTrue; printCommands = globalParams->getPrintCommands(); + defaultFont = NULL; // start the resource stack res = new GfxResources(xref, resDict, NULL); @@ -609,6 +611,9 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, } Gfx::~Gfx() { + if (defaultFont) { + delete defaultFont; + } if (!subPage) { out->endPage(); } @@ -2080,12 +2085,19 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, // Adobe's behavior state->setFillPattern(NULL); state->setStrokePattern(NULL); + state->setFillOverprint(gFalse); + state->setStrokeOverprint(gFalse); + state->setOverprintMode(0); if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { state->setFillColorSpace(cs->copy()); out->updateFillColorSpace(state); state->setStrokeColorSpace(cs->copy()); out->updateStrokeColorSpace(state); - state->setStrokeColor(state->getFillColor()); + if (stroke) { + state->setFillColor(state->getStrokeColor()); + } else { + state->setStrokeColor(state->getFillColor()); + } out->updateFillColor(state); out->updateStrokeColor(state); state->setIgnoreColorOps(gTrue); @@ -3564,8 +3576,10 @@ void Gfx::opSetFont(Object args[], int numArgs) { void Gfx::doSetFont(GfxFont *font, double size) { if (!font) { - state->setFont(NULL, 0); - return; + if (!defaultFont) { + defaultFont = GfxFont::makeDefaultFont(xref); + } + font = defaultFont; } if (printCommands) { printf(" font: tag=%s name='%s' %g\n", @@ -3847,7 +3861,7 @@ void Gfx::doShowText(GString *s) { newCTM[2] *= state->getFontSize(); newCTM[3] *= state->getFontSize(); newCTM[0] *= state->getHorizScaling(); - newCTM[2] *= state->getHorizScaling(); + newCTM[1] *= state->getHorizScaling(); curX = state->getCurX(); curY = state->getCurY(); oldParser = parser; @@ -4035,7 +4049,7 @@ void Gfx::doIncCharCount(GString *s) { void Gfx::opXObject(Object args[], int numArgs) { char *name; - Object obj1, obj2, obj3, refObj; + Object xObj, refObj, obj2, obj3; GBool ocSaved, oc; #if OPI_SUPPORT Object opiDict; @@ -4045,18 +4059,31 @@ void Gfx::opXObject(Object args[], int numArgs) { return; } name = args[0].getName(); - if (!res->lookupXObject(name, &obj1)) { + // NB: we get both the reference and the object here, to make sure + // they refer to the same object. There's a problematic corner + // case: if the resource dict contains an entry for [name] with a + // reference to a nonexistent object ("/name 99999 0 R", where + // object 99999 doesn't exist), and a parent resource dict contains + // a valid entry with the same name, then lookupXObjectNF() will + // return "99999 0 R", but lookupXObject() will return the valid + // entry. This causes problems for doImage() and doForm(). + if (!res->lookupXObjectNF(name, &refObj)) { + return; + } + if (!refObj.fetch(xref, &xObj)) { + refObj.free(); return; } - if (!obj1.isStream()) { + if (!xObj.isStream()) { error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name); - obj1.free(); + xObj.free(); + refObj.free(); return; } // check for optional content key ocSaved = ocState; - obj1.streamGetDict()->lookupNF("OC", &obj2); + xObj.streamGetDict()->lookupNF("OC", &obj2); if (doc->getOptionalContent()->evalOCObject(&obj2, &oc)) { ocState &= oc; } @@ -4066,32 +4093,28 @@ void Gfx::opXObject(Object args[], int numArgs) { try { #endif #if OPI_SUPPORT - obj1.streamGetDict()->lookup("OPI", &opiDict); + xObj.streamGetDict()->lookup("OPI", &opiDict); if (opiDict.isDict()) { out->opiBegin(state, opiDict.getDict()); } #endif - obj1.streamGetDict()->lookup("Subtype", &obj2); + xObj.streamGetDict()->lookup("Subtype", &obj2); if (obj2.isName("Image")) { if (out->needNonText()) { - res->lookupXObjectNF(name, &refObj); - doImage(&refObj, obj1.getStream(), gFalse); - refObj.free(); + doImage(&refObj, xObj.getStream(), gFalse); } } else if (obj2.isName("Form")) { - res->lookupXObjectNF(name, &refObj); if (out->useDrawForm() && refObj.isRef()) { if (ocState) { out->drawForm(refObj.getRef()); } } else { - doForm(&refObj, &obj1); + doForm(&refObj, &xObj); } - refObj.free(); } else if (obj2.isName("PS")) { if (ocState) { - obj1.streamGetDict()->lookup("Level1", &obj3); - out->psXObject(obj1.getStream(), + xObj.streamGetDict()->lookup("Level1", &obj3); + out->psXObject(xObj.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL); } } else if (obj2.isName()) { @@ -4110,13 +4133,16 @@ void Gfx::opXObject(Object args[], int numArgs) { #endif #if USE_EXCEPTIONS } catch (GMemException e) { - obj1.free(); + xObj.free(); + refObj.free(); throw; } #endif - obj1.free(); ocState = ocSaved; + + xObj.free(); + refObj.free(); } GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { @@ -4144,6 +4170,10 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { return gTrue; } + // images can have arbitrarily high compression ratios, but the + // data size is inherently limited + str->disableDecompressionBombChecking(); + // get info from the stream bits = 0; csMode = streamCSNone; @@ -4248,6 +4278,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { // if drawing is disabled, skip over inline image data if (!ocState) { + str->disableDecompressionBombChecking(); str->reset(); n = height * ((width + 7) / 8); for (i = 0; i < n; ++i) { @@ -4339,6 +4370,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { goto err1; } maskStr = smaskObj.getStream(); + maskStr->disableDecompressionBombChecking(); maskDict = smaskObj.streamGetDict(); maskDict->lookup("Width", &obj1); if (obj1.isNull()) { @@ -4487,6 +4519,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { goto err1; } maskStr = maskObj.getStream(); + maskStr->disableDecompressionBombChecking(); maskDict = maskObj.streamGetDict(); maskDict->lookup("Width", &obj1); if (obj1.isNull()) { @@ -4559,6 +4592,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { " in uncolored Type 3 char or tiling pattern"); } if (inlineImg) { + str->disableDecompressionBombChecking(); str->reset(); n = height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8); @@ -4569,7 +4603,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { // draw it } else { if (haveSoftMask) { - dict->lookupNF("Mask", &maskRef); + dict->lookupNF("SMask", &maskRef); out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, &maskRef, maskStr, maskWidth, maskHeight, maskColorMap, @@ -4654,13 +4688,18 @@ void Gfx::doForm(Object *strRef, Object *str) { // get bounding box dict->lookup("BBox", &bboxObj); - if (!bboxObj.isArray()) { + if (!(bboxObj.isArray() && bboxObj.arrayGetLength() == 4)) { bboxObj.free(); error(errSyntaxError, getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { bboxObj.arrayGet(i, &obj1); + if (!obj1.isNum()) { + bboxObj.free(); + error(errSyntaxError, getPos(), "Bad form bounding box"); + return; + } bbox[i] = obj1.getNum(); obj1.free(); } @@ -4668,10 +4707,14 @@ void Gfx::doForm(Object *strRef, Object *str) { // get matrix dict->lookup("Matrix", &matrixObj); - if (matrixObj.isArray()) { + if (matrixObj.isArray() && matrixObj.arrayGetLength() == 6) { for (i = 0; i < 6; ++i) { matrixObj.arrayGet(i, &obj1); - m[i] = obj1.getNum(); + if (obj1.isNum()) { + m[i] = obj1.getNum(); + } else { + m[i] = 0; + } obj1.free(); } } else { @@ -4769,22 +4812,27 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, groupAttrsObj.free(); strObj.free(); - traceBegin(oldBaseMatrix, softMask ? "begin soft mask" : "begin t-group"); - if (state->getBlendMode() != gfxBlendNormal) { - state->setBlendMode(gfxBlendNormal); - out->updateBlendMode(state); - } - if (state->getFillOpacity() != 1) { - state->setFillOpacity(1); - out->updateFillOpacity(state); + if (!out->beginTransparencyGroup(state, bbox, blendingColorSpace, + isolated, knockout, softMask)) { + transpGroup = gFalse; } - if (state->getStrokeOpacity() != 1) { - state->setStrokeOpacity(1); - out->updateStrokeOpacity(state); + + if (softMask || transpGroup) { + traceBegin(oldBaseMatrix, softMask ? "begin soft mask" : "begin t-group"); + if (state->getBlendMode() != gfxBlendNormal) { + state->setBlendMode(gfxBlendNormal); + out->updateBlendMode(state); + } + if (state->getFillOpacity() != 1) { + state->setFillOpacity(1); + out->updateFillOpacity(state); + } + if (state->getStrokeOpacity() != 1) { + state->setStrokeOpacity(1); + out->updateStrokeOpacity(state); + } + out->clearSoftMask(state); } - out->clearSoftMask(state); - out->beginTransparencyGroup(state, bbox, blendingColorSpace, - isolated, knockout, softMask); } // set new base matrix diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h index 4625ac289d0..14d7a608438 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h @@ -188,6 +188,7 @@ private: GBool subPage; // is this a sub-page object? GBool printCommands; // print the drawing commands (for debugging) GfxResources *res; // resource stack + GfxFont *defaultFont; // font substituted for undefined fonts int opCounter; // operation counter (used to decide when // to check for an abort) diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc index f224ff75b5f..30e8bd1c79c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc @@ -198,6 +198,27 @@ GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA, return font; } +GfxFont *GfxFont::makeDefaultFont(XRef *xref) { + Object type, subtype, baseFont; + type.initName("Font"); + subtype.initName("Type1"); + baseFont.initName("Helvetica"); + Object fontDict; + fontDict.initDict(xref); + fontDict.dictAdd(copyString("Type"), &type); + fontDict.dictAdd(copyString("Subtype"), &subtype); + fontDict.dictAdd(copyString("BaseFont"), &baseFont); + + Ref r; + r.gen = 100000; + r.num = GfxFontDict::hashFontObject(&fontDict); + + GfxFont *font = makeFont(xref, "undef", r, fontDict.getDict()); + fontDict.free(); + + return font; +} + GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA, GfxFontType typeA, Ref embFontIDA) { ok = gFalse; @@ -1701,9 +1722,59 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, obj2.free(); obj1.free(); + // encoding (i.e., CMap) + if (fontDict->lookup("Encoding", &obj1)->isNull()) { + error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font"); + goto err2; + } + if (!(cMap = CMap::parse(NULL, collection, &obj1))) { + goto err2; + } + + // check for fonts that use the Identity-H encoding (cmap), and the + // Adobe-Identity character collection + identityEnc = obj1.isName("Identity-H") && + !collection->cmp("Adobe-Identity"); + + obj1.free(); + + // CIDToGIDMap + // (the PDF 1.7 spec only allows these for TrueType fonts, but + // Acrobat apparently also allows them for OpenType CFF fonts -- and + // the PDF 2.0 spec has removed the prohibition) + hasIdentityCIDToGID = gFalse; + desFontDict->lookup("CIDToGIDMap", &obj1); + if (obj1.isStream()) { + cidToGIDLen = 0; + i = 64; + cidToGID = (int *)gmallocn(i, sizeof(int)); + obj1.streamReset(); + while ((c1 = obj1.streamGetChar()) != EOF && + (c2 = obj1.streamGetChar()) != EOF) { + if (cidToGIDLen == i) { + i *= 2; + cidToGID = (int *)greallocn(cidToGID, i, sizeof(int)); + } + cidToGID[cidToGIDLen++] = (c1 << 8) + c2; + } + obj1.streamClose(); + identityEnc = gFalse; + } else if (obj1.isName("Identity")) { + hasIdentityCIDToGID = gTrue; + } else if (!obj1.isNull()) { + error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font"); + } + obj1.free(); + // look for a ToUnicode CMap hasKnownCollection = gFalse; - if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { + if (globalParams->getUseTrueTypeUnicodeMapping()) { + readTrueTypeUnicodeMapping(xref); + } + if (!ctu) { + ctu = readToUnicodeCMap(fontDict, 16, NULL); + } + if (!ctu) { ctuUsesCharCode = gFalse; // use an identity mapping for the "Adobe-Identity" and @@ -1748,55 +1819,11 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA, } } - // encoding (i.e., CMap) - if (fontDict->lookup("Encoding", &obj1)->isNull()) { - error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font"); - goto err2; - } - if (!(cMap = CMap::parse(NULL, collection, &obj1))) { - goto err2; - } - - // check for fonts that use the Identity-H encoding (cmap), and the - // Adobe-Identity character collection - identityEnc = obj1.isName("Identity-H") && - !collection->cmp("Adobe-Identity"); - - obj1.free(); - - // CIDToGIDMap - // (the PDF 1.7 spec only allows these for TrueType fonts, but - // Acrobat apparently also allows them for OpenType CFF fonts -- and - // the PDF 2.0 spec has removed the prohibition) - hasIdentityCIDToGID = gFalse; - desFontDict->lookup("CIDToGIDMap", &obj1); - if (obj1.isStream()) { - cidToGIDLen = 0; - i = 64; - cidToGID = (int *)gmallocn(i, sizeof(int)); - obj1.streamReset(); - while ((c1 = obj1.streamGetChar()) != EOF && - (c2 = obj1.streamGetChar()) != EOF) { - if (cidToGIDLen == i) { - i *= 2; - cidToGID = (int *)greallocn(cidToGID, i, sizeof(int)); - } - cidToGID[cidToGIDLen++] = (c1 << 8) + c2; - } - obj1.streamClose(); - identityEnc = gFalse; - } else if (obj1.isName("Identity")) { - hasIdentityCIDToGID = gTrue; - } else if (!obj1.isNull()) { - error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font"); - } - obj1.free(); - //----- character metrics ----- // default char width - if (desFontDict->lookup("DW", &obj1)->isInt()) { - widths.defWidth = obj1.getInt() * 0.001; + if (desFontDict->lookup("DW", &obj1)->isNum()) { + widths.defWidth = obj1.getNum() * 0.001; } obj1.free(); @@ -1968,6 +1995,91 @@ GfxCIDFont::~GfxCIDFont() { } } +// Construct a code-to-Unicode mapping, based on the TrueType Unicode +// cmap (if present). Constructs ctu if succesful; leaves ctu = null +// otherwise. Always leaves ctu = null for non-TrueType fonts. +void GfxCIDFont::readTrueTypeUnicodeMapping(XRef *xref) { + char *buf; + FoFiTrueType *ff; + Unicode *gidToUnicode, *codeToUnicode; + Unicode u; + int bufLen, cmapPlatform, cmapEncoding, unicodeCmap; + int nGlyphs, nMappings, gid, i; + + // must be an embedded TrueType font, with an unknown char collection + if ((type != fontCIDType2 && type == fontCIDType2OT) || + embFontID.num < 0 || + hasKnownCollection) { + goto err0; + } + + // read the embedded font and construct a FoFiTrueType + if (!(buf = readEmbFontFile(xref, &bufLen))) { + goto err0; + } + if (!(ff = FoFiTrueType::make(buf, bufLen, 0))) { + goto err1; + } + + // find the TrueType Unicode cmap + unicodeCmap = -1; + for (i = 0; i < ff->getNumCmaps(); ++i) { + cmapPlatform = ff->getCmapPlatform(i); + cmapEncoding = ff->getCmapEncoding(i); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + (cmapPlatform == 0 && cmapEncoding <= 4)) { + unicodeCmap = i; + break; + } + } + if (unicodeCmap < 0) { + goto err2; + } + + // construct reverse GID-to-Unicode map + nGlyphs = ff->getNumGlyphs(); + gidToUnicode = (Unicode *)gmallocn(nGlyphs, sizeof(Unicode)); + memset(gidToUnicode, 0, nGlyphs * sizeof(Unicode)); + nMappings = 0; + for (u = 1; u <= 0xffff; ++u) { + gid = ff->mapCodeToGID(unicodeCmap, (int)u); + if (gid > 0 && gid < nGlyphs) { + gidToUnicode[gid] = u; + ++nMappings; + } + } + // bail out if the Unicode cmap was completely empty + if (nMappings == 0) { + goto err3; + } + + // construct code-to-Unicode map + codeToUnicode = (Unicode *)gmallocn(65536, sizeof(Unicode)); + memset(codeToUnicode, 0, 65536 * sizeof(Unicode)); + for (i = 0; i <= 0xffff; ++i) { + // we've already checked for an identity encoding, so CID = i + if (cidToGID && i < cidToGIDLen) { + gid = cidToGID[i]; + } else { + gid = i; + } + if (gid < nGlyphs && gidToUnicode[gid] > 0) { + codeToUnicode[i] = gidToUnicode[gid]; + } + } + ctu = CharCodeToUnicode::make16BitToUnicode(codeToUnicode); + + gfree(codeToUnicode); + err3: + gfree(gidToUnicode); + err2: + delete ff; + err1: + gfree(buf); + err0: + return; +} + int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, Unicode *u, int uSize, int *uLen, double *dx, double *dy, double *ox, double *oy) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h index ded34bc1ee7..e752ded62f8 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h @@ -135,6 +135,10 @@ public: static GfxFont *makeFont(XRef *xref, const char *tagA, Ref idA, Dict *fontDict); + // Create a simple default font, to substitute for an undefined font + // object. + static GfxFont *makeDefaultFont(XRef *xref); + GfxFont(const char *tagA, Ref idA, GString *nameA, GfxFontType typeA, Ref embFontIDA); @@ -357,6 +361,7 @@ public: private: + void readTrueTypeUnicodeMapping(XRef *xref); void getHorizontalMetrics(CID cid, double *w); void getVerticalMetrics(CID cid, double *h, double *vx, double *vy); @@ -398,8 +403,10 @@ public: private: - int hashFontObject(Object *obj); - void hashFontObject1(Object *obj, FNVHash *h); + friend class GfxFont; + + static int hashFontObject(Object *obj); + static void hashFontObject1(Object *obj, FNVHash *h); GHash *fonts; // hash table of fonts -- this may // include duplicates, i.e., when diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc index 5e9991e1b97..43503aaedb8 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc @@ -2071,6 +2071,7 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict Function *funcsA[gfxColorMaxComps]; int nFuncsA; Object obj1, obj2; + GBool ok; int i; x0A = y0A = 0; @@ -2139,14 +2140,21 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict 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; + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -2241,7 +2249,7 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict double t0A, t1A; Function *funcsA[gfxColorMaxComps]; int nFuncsA; - GBool extend0A, extend1A; + GBool extend0A, extend1A, ok; Object obj1, obj2; int i; @@ -2319,14 +2327,21 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict 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; + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -2420,7 +2435,7 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict double t0A, t1A; Function *funcsA[gfxColorMaxComps]; int nFuncsA; - GBool extend0A, extend1A; + GBool extend0A, extend1A, ok; Object obj1, obj2; int i; @@ -2501,14 +2516,21 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict 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; + ok = gFalse; + if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -2675,6 +2697,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( Guint c[gfxColorMaxComps]; GfxShadingBitBuf *bitBuf; Object obj1, obj2; + GBool ok; int i, j, k, state; if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { @@ -2883,14 +2906,23 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( 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; + ok = gFalse; + if (shading->nFuncs == 0) { + ok = shading->nComps == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -3042,6 +3074,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, Guint ci; GfxShadingBitBuf *bitBuf; Object obj1, obj2; + GBool ok; int i, j; nPatchesA = 0; @@ -3555,14 +3588,23 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, 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; + ok = gFalse; + if (shading->nFuncs == 0) { + ok = shading->nComps == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == 1) { + ok = shading->funcs[0]->getOutputSize() + == shading->getColorSpace()->getNComps(); + } else if (shading->nFuncs == shading->getColorSpace()->getNComps()) { + ok = gTrue; + for (i = 0; i < shading->nFuncs; ++i) { + ok = ok && shading->funcs[i]->getOutputSize() == 1; } } + if (!ok) { + error(errSyntaxError, -1, "Invalid function in shading dictionary"); + delete shading; + return NULL; + } return shading; @@ -4091,6 +4133,26 @@ GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1, subpaths[i] = subpaths1[i]->copy(); } +double GfxPath::getCurX() { + if (justMoved) { + return firstX; + } else if (n > 0) { + return subpaths[n-1]->getLastX(); + } else { + return 0; + } +} + +double GfxPath::getCurY() { + if (justMoved) { + return firstY; + } else if (n > 0) { + return subpaths[n-1]->getLastY(); + } else { + return 0; + } +} + void GfxPath::moveTo(double x, double y) { justMoved = gTrue; firstX = x; @@ -4581,65 +4643,143 @@ void GfxState::clip() { } void GfxState::clipToStrokePath() { - double xMin, yMin, xMax, yMax, x, y, t0, t1; - GfxSubpath *subpath; - int i, j; - - xMin = xMax = yMin = yMax = 0; // make gcc happy - for (i = 0; i < path->getNumSubpaths(); ++i) { - subpath = path->getSubpath(i); - for (j = 0; j < subpath->getNumPoints(); ++j) { - transform(subpath->getX(j), subpath->getY(j), &x, &y); + // We compute the stroke path bbox in user space (line width and + // miter limt are handled in user space), and then transform the + // bbox to device space. This can result in a larger-than-needed + // bbox if the matrix isn't "square", but that's ok. + // + // There are two cases for each point on the path: + // (1) miter join, under miter limit => compute the miter point + // (2) all other joins and caps => use the path point +/- 0.5 * line width + double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double w = 0.5 * lineWidth; + for (int i = 0; i < path->getNumSubpaths(); ++i) { + GfxSubpath *subpath = path->getSubpath(i); + for (int j = 0; j < subpath->getNumPoints(); ++j) { + double x1 = subpath->getX(j); + double y1 = subpath->getY(j); if (i == 0 && j == 0) { - xMin = xMax = x; - yMin = yMax = y; - } else { - if (x < xMin) { - xMin = x; - } else if (x > xMax) { - xMax = x; + xMin = xMax = x1; + yMin = yMax = y1; + } + GBool useMiter = gFalse; + if (lineJoin == 0 && // miter join + ((j > 0 && j < subpath->getNumPoints() - 1) || subpath->isClosed())) { + double x0, y0, x2, y2; + if (j > 0) { + x0 = subpath->getX(j - 1); + y0 = subpath->getY(j - 1); + } else { + x0 = subpath->getLastX(); + y0 = subpath->getLastY(); } - if (y < yMin) { - yMin = y; - } else if (y > yMax) { - yMax = y; + if (j < subpath->getNumPoints() - 1) { + x2 = subpath->getX(j + 1); + y2 = subpath->getY(j + 1); + } else { + x2 = subpath->getX(0); + y2 = subpath->getY(0); + } + if ((fabs(x1 - x0) > 0.0001 || fabs(y1 - y0) > 0.0001) && + (fabs(x2 - x1) > 0.0001 || fabs(y2 - y1) > 0.0001)) { + double d01 = 1 / sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + double ux = (x1 - x0) * d01; + double uy = (y1 - y0) * d01; + double d12 = 1 / sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + double vx = (x2 - x1) * d12; + double vy = (y2 - y1) * d12; + double dot = -ux * vx - uy * vy; + if (dot < 0.9999) { + double miter = sqrt(2 / (1 - dot)); + if (miter <= miterLimit) { + double cross = ux * vy - uy * vx; + double m = sqrt(2 / (1 - dot) - 1); + double ax, ay; + if (cross >= 0) { + ax = x1 + w * uy; + ay = y1 - w * ux; + } else { + ax = x1 - w * uy; + ay = y1 + w * ux; + } + double mx = ax + m * w * ux; + double my = ay + m * w * uy; + if (mx < xMin) { + xMin = mx; + } else if (mx > xMax) { + xMax = mx; + } + if (my < yMin) { + yMin = my; + } else if (my > yMax) { + yMax = my; + } + useMiter = gTrue; + } + } + } + } + if (!useMiter) { + if (x1 - w < xMin) { + xMin = x1 - w; + } + if (x1 + w > xMax) { + xMax = x1 + w; + } + if (y1 - w < yMin) { + yMin = y1 - w; + } + if (y1 + w > yMax) { + yMax = y1 + w; } } } } - // allow for the line width - //~ miter joins can extend farther than this - t0 = fabs(ctm[0]); - t1 = fabs(ctm[2]); - if (t0 > t1) { - xMin -= 0.5 * lineWidth * t0; - xMax += 0.5 * lineWidth * t0; - } else { - xMin -= 0.5 * lineWidth * t1; - xMax += 0.5 * lineWidth * t1; - } - t0 = fabs(ctm[0]); - t1 = fabs(ctm[3]); - if (t0 > t1) { - yMin -= 0.5 * lineWidth * t0; - yMax += 0.5 * lineWidth * t0; - } else { - yMin -= 0.5 * lineWidth * t1; - yMax += 0.5 * lineWidth * t1; - } - - if (xMin > clipXMin) { - clipXMin = xMin; - } - if (yMin > clipYMin) { - clipYMin = yMin; - } - if (xMax < clipXMax) { - clipXMax = xMax; - } - if (yMax < clipYMax) { - clipYMax = yMax; + double xx, yy; + transform(xMin, yMin, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMin, yMax, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMax, yMin, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; + } + transform(xMax, yMax, &xx, &yy); + if (xx < clipXMin) { + clipXMin = xx; + } else if (xx > clipXMax) { + clipXMax = xx; + } + if (yy < clipYMin) { + clipYMin = yy; + } else if (yy > clipYMax) { + clipYMax = yy; } } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h index f9c0cfcad6e..60d48527c29 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h @@ -1076,6 +1076,10 @@ public: double getLastX() { return subpaths[n-1]->getLastX(); } double getLastY() { return subpaths[n-1]->getLastY(); } + // Get the current point + double getCurX(); + double getCurY(); + // Move the current point. void moveTo(double x, double y); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc index 5ff932479d1..e7cc594b12d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc @@ -5,9 +5,6 @@ // Copyright 2001-2003 Glyph & Cog, LLC // //======================================================================== -// Modified for TeX Live by Peter Breitenlohner <tex-live@tug.org> -// See top-level ChangeLog for a list of all modifications -//======================================================================== #include <aconf.h> @@ -219,7 +216,7 @@ GString *SysFontInfo::mungeName1(GString *in) { return out; } -// Remove trailing "Identity-H"/"Identity-V" from the name. +// Remove trailing encoding tags from the name. // Split the name into tokens at space/comma/dash/underscore. // Remove trailing "MT" or "BT" from tokens. // Remove trailing "PS" and "WGL4" from tokens. @@ -229,7 +226,9 @@ GString *SysFontInfo::mungeName2(GString *in) { GString *out = new GString(); char *p0 = in->getCString(); while (*p0) { - if (!strcmp(p0, "Identity-H") || !strcmp(p0, "Identity-V")) { + if (!strcmp(p0, "Identity-H") || !strcmp(p0, "Identity-V") || + !strcmp(p0, "GB2312") || + !strcmp(p0, "UniGB-UCS2-H") || !strcmp(p0, "UniGB-UCS2-V")) { break; } char *p1; @@ -729,6 +728,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) { disableFreeTypeHinting = gFalse; antialias = gTrue; vectorAntialias = gTrue; + imageMaskAntialias = gTrue; antialiasPrinting = gFalse; strokeAdjust = strokeAdjustNormal; screenType = screenUnset; @@ -741,6 +741,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) { enablePathSimplification = gFalse; drawAnnotations = gTrue; drawFormFields = gTrue; + enableXFA = gTrue; overprintPreview = gFalse; paperColor = new GString("#ffffff"); matteColor = new GString("#808080"); @@ -753,11 +754,14 @@ GlobalParams::GlobalParams(const char *cfgFileName) { mapNumericCharNames = gTrue; mapUnknownCharNames = gFalse; mapExtTrueTypeFontsViaUnicode = gTrue; + useTrueTypeUnicodeMapping = gFalse; droppedFonts = new GHash(gTrue); createDefaultKeyBindings(); popupMenuCmds = new GList(); tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state"); + savePageNumbers = gTrue; printCommands = gFalse; + printStatusInfo = gFalse; errQuiet = gFalse; debugLogFile = NULL; @@ -1186,6 +1190,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("vectorAntialias")) { parseYesNo("vectorAntialias", &vectorAntialias, tokens, fileName, line); + } else if (!cmd->cmp("imageMaskAntialias")) { + parseYesNo("imageMaskAntialias", &imageMaskAntialias, + tokens, fileName, line); } else if (!cmd->cmp("antialiasPrinting")) { parseYesNo("antialiasPrinting", &antialiasPrinting, tokens, fileName, line); @@ -1219,6 +1226,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("drawFormFields")) { parseYesNo("drawFormFields", &drawFormFields, tokens, fileName, line); + } else if (!cmd->cmp("enableXFA")) { + parseYesNo("enableXFA", &enableXFA, + tokens, fileName, line); } else if (!cmd->cmp("overprintPreview")) { parseYesNo("overprintPreview", &overprintPreview, tokens, fileName, line); @@ -1250,6 +1260,10 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parseYesNo("mapExtTrueTypeFontsViaUnicode", &mapExtTrueTypeFontsViaUnicode, tokens, fileName, line); + } else if (!cmd->cmp("useTrueTypeUnicodeMapping")) { + parseYesNo("useTrueTypeUnicodeMapping", + &useTrueTypeUnicodeMapping, + tokens, fileName, line); } else if (!cmd->cmp("dropFont")) { parseDropFont(tokens, fileName, line); } else if (!cmd->cmp("bind")) { @@ -1260,8 +1274,12 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parsePopupMenuCmd(tokens, fileName, line); } else if (!cmd->cmp("tabStateFile")) { parseString("tabStateFile", &tabStateFile, tokens, fileName, line); + } else if (!cmd->cmp("savePageNumbers")) { + parseYesNo("savePageNumbers", &savePageNumbers, tokens, fileName, line); } else if (!cmd->cmp("printCommands")) { parseYesNo("printCommands", &printCommands, tokens, fileName, line); + } else if (!cmd->cmp("printStatusInfo")) { + parseYesNo("printStatusInfo", &printStatusInfo, tokens, fileName, line); } else if (!cmd->cmp("errQuiet")) { parseYesNo("errQuiet", &errQuiet, tokens, fileName, line); } else if (!cmd->cmp("debugLogFile")) { @@ -1281,8 +1299,6 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) { error(errConfig, -1, "The config file format has changed since Xpdf 0.9x"); - } else if (!cmd->cmp("enableXFA")) { - error(errConfig, -1, "The enableXFA option is no longer used"); } } } @@ -2115,6 +2131,7 @@ GlobalParams::~GlobalParams() { deleteGList(keyBindings, KeyBinding); deleteGList(popupMenuCmds, PopupMenuCmd); delete tabStateFile; + delete debugLogFile; cMapDirs->startIter(&iter); while (cMapDirs->getNext(&iter, &key, (void **)&list)) { @@ -3060,6 +3077,15 @@ GBool GlobalParams::getVectorAntialias() { return f; } +GBool GlobalParams::getImageMaskAntialias() { + GBool f; + + lockGlobalParams; + f = imageMaskAntialias; + unlockGlobalParams; + return f; +} + GBool GlobalParams::getAntialiasPrinting() { GBool f; @@ -3168,6 +3194,15 @@ GBool GlobalParams::getDrawFormFields() { return draw; } +GBool GlobalParams::getEnableXFA() { + GBool xfa; + + lockGlobalParams; + xfa = enableXFA; + unlockGlobalParams; + return xfa; +} + GString *GlobalParams::getPaperColor() { @@ -3251,6 +3286,15 @@ GBool GlobalParams::getMapExtTrueTypeFontsViaUnicode() { return map; } +GBool GlobalParams::getUseTrueTypeUnicodeMapping() { + GBool use; + + lockGlobalParams; + use = useTrueTypeUnicodeMapping; + unlockGlobalParams; + return use; +} + GBool GlobalParams::isDroppedFont(const char *fontName) { GBool isDropped; @@ -3321,6 +3365,15 @@ GString *GlobalParams::getTabStateFile() { return s; } +GBool GlobalParams::getSavePageNumbers() { + GBool s; + + lockGlobalParams; + s = savePageNumbers; + unlockGlobalParams; + return s; +} + GBool GlobalParams::getPrintCommands() { GBool p; @@ -3330,6 +3383,15 @@ GBool GlobalParams::getPrintCommands() { return p; } +GBool GlobalParams::getPrintStatusInfo() { + GBool p; + + lockGlobalParams; + p = printStatusInfo; + unlockGlobalParams; + return p; +} + GBool GlobalParams::getErrQuiet() { // no locking -- this function may get called from inside a locked // section @@ -3759,6 +3821,12 @@ void GlobalParams::setPrintCommands(GBool printCommandsA) { unlockGlobalParams; } +void GlobalParams::setPrintStatusInfo(GBool printStatusInfoA) { + lockGlobalParams; + printStatusInfo = printStatusInfoA; + unlockGlobalParams; +} + void GlobalParams::setErrQuiet(GBool errQuietA) { lockGlobalParams; errQuiet = errQuietA; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h index 2823ea59421..d72473f2a46 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h @@ -316,6 +316,7 @@ public: GBool getDisableFreeTypeHinting(); GBool getAntialias(); GBool getVectorAntialias(); + GBool getImageMaskAntialias(); GBool getAntialiasPrinting(); StrokeAdjustMode getStrokeAdjust(); ScreenType getScreenType(); @@ -328,6 +329,7 @@ public: GBool getEnablePathSimplification(); GBool getDrawAnnotations(); GBool getDrawFormFields(); + GBool getEnableXFA(); GBool getOverprintPreview() { return overprintPreview; } GString *getPaperColor(); GString *getMatteColor(); @@ -340,13 +342,16 @@ public: GBool getMapNumericCharNames(); GBool getMapUnknownCharNames(); GBool getMapExtTrueTypeFontsViaUnicode(); + GBool getUseTrueTypeUnicodeMapping(); GBool isDroppedFont(const char *fontName); GList *getKeyBinding(int code, int mods, int context); GList *getAllKeyBindings(); int getNumPopupMenuCmds(); PopupMenuCmd *getPopupMenuCmd(int idx); GString *getTabStateFile(); + GBool getSavePageNumbers(); GBool getPrintCommands(); + GBool getPrintStatusInfo(); GBool getErrQuiet(); GString *getDebugLogFile(); void debugLogPrintf(const char *fmt, ...); @@ -401,6 +406,7 @@ public: void setMapExtTrueTypeFontsViaUnicode(GBool map); void setTabStateFile(char *tabStateFileA); void setPrintCommands(GBool printCommandsA); + void setPrintStatusInfo(GBool printStatusInfoA); void setErrQuiet(GBool errQuietA); #ifdef _WIN32 @@ -559,6 +565,7 @@ private: GBool disableFreeTypeHinting; // FreeType hinting disable flag GBool antialias; // font anti-aliasing enable flag GBool vectorAntialias; // vector anti-aliasing enable flag + GBool imageMaskAntialias; // image mask anti-aliasing enable flag GBool antialiasPrinting; // allow anti-aliasing when printing StrokeAdjustMode strokeAdjust; // stroke adjustment mode ScreenType screenType; // halftone screen type @@ -572,6 +579,7 @@ private: enablePathSimplification; GBool drawAnnotations; // draw annotations or not GBool drawFormFields; // draw form fields or not + GBool enableXFA; // enable XFA form parsing GBool overprintPreview; // enable overprint preview GString *paperColor; // paper (page background) color GString *matteColor; // matte (background outside of page) color @@ -586,11 +594,17 @@ private: GBool mapUnknownCharNames; // map unknown char names? GBool mapExtTrueTypeFontsViaUnicode; // map char codes to GID via Unicode // for external TrueType fonts? + GBool useTrueTypeUnicodeMapping; // use the Unicode cmaps in TrueType + // fonts, rather than the PDF + // ToUnicode mapping GHash *droppedFonts; // dropped fonts [int] GList *keyBindings; // key & mouse button bindings [KeyBinding] GList *popupMenuCmds; // popup menu commands [PopupMenuCmd] GString *tabStateFile; // path for the tab state save file + GBool savePageNumbers; // save page number when file is closed + // and restore page number when opened GBool printCommands; // print the drawing commands + GBool printStatusInfo; // print status info for each page GBool errQuiet; // suppress error messages? GString *debugLogFile; // path for debug log file diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc index 6f51ad85190..a077655ef43 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc @@ -2,7 +2,7 @@ // // HTMLGen.cc // -// Copyright 2010 Glyph & Cog, LLC +// Copyright 2010-2021 Glyph & Cog, LLC // //======================================================================== @@ -13,9 +13,8 @@ //~ generic serif/sans-serif/monospace name) //~ - check that htmlDir exists and is a directory //~ - links: -//~ - links to pages -//~ - links to named destinations -//~ - links to URLs +//~ - internal links (to pages, to named destinations) +//~ - links from non-text content //~ - rotated text should go in the background image //~ - metadata //~ - PDF outline @@ -35,6 +34,7 @@ #include "SplashBitmap.h" #include "PDFDoc.h" #include "GfxFont.h" +#include "AcroForm.h" #include "TextOutputDev.h" #include "SplashOutputDev.h" #include "ErrorCodes.h" @@ -196,10 +196,93 @@ public: //------------------------------------------------------------------------ +class HTMLGenFormFieldInfo { +public: + + HTMLGenFormFieldInfo(AcroFormField *acroFormFieldA) + : acroFormField(acroFormFieldA) {} + + AcroFormField *acroFormField; +}; + +//------------------------------------------------------------------------ + +class Base64Encoder { +public: + + Base64Encoder(int (*writeFuncA)(void *stream, const char *data, int size), + void *streamA); + void encode(const unsigned char *data, size_t size); + void flush(); + +private: + + int (*writeFunc)(void *stream, const char *data, int size); + void *stream; + unsigned char buf[3]; + int bufLen; +}; + +static char base64Chars[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +Base64Encoder::Base64Encoder(int (*writeFuncA)(void *stream, const char *data, + int size), + void *streamA) { + writeFunc = writeFuncA; + stream = streamA; + bufLen = 0; +} + +void Base64Encoder::encode(const unsigned char *data, size_t size) { + size_t i = 0; + while (1) { + while (bufLen < 3) { + if (i >= size) { + return; + } + buf[bufLen++] = data[i++]; + } + char out[4]; + out[0] = base64Chars[(buf[0] >> 2) & 0x3f]; + out[1] = base64Chars[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f]; + out[2] = base64Chars[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f]; + out[3] = base64Chars[buf[2] & 0x3f]; + writeFunc(stream, out, 4); + bufLen = 0; + } +} + +void Base64Encoder::flush() { + // if bufLen == 0, this does nothing + // bufLen should never be 3 here + char out[4]; + if (bufLen == 1) { + out[0] = base64Chars[(buf[0] >> 2) & 0x3f]; + out[1] = base64Chars[(buf[0] << 4) & 0x3f]; + out[2] = '='; + out[3] = '='; + writeFunc(stream, out, 4); + } else if (bufLen == 2) { + out[0] = base64Chars[(buf[0] >> 2) & 0x3f]; + out[1] = base64Chars[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f]; + out[2] = base64Chars[(buf[1] << 2) & 0x3f]; + out[3] = '='; + writeFunc(stream, out, 4); + } +} + +static int writeToString(void *stream, const char *data, int size) { + ((GString *)stream)->append(data, size); + return size; +} + +//------------------------------------------------------------------------ + //------------------------------------------------------------------------ -HTMLGen::HTMLGen(double backgroundResolutionA) { +HTMLGen::HTMLGen(double backgroundResolutionA, GBool tableMode) { TextOutputControl textOutControl; SplashColor paperColor; @@ -207,12 +290,16 @@ HTMLGen::HTMLGen(double backgroundResolutionA) { backgroundResolution = backgroundResolutionA; zoom = 1.0; + vStretch = 1.0; drawInvisibleText = gTrue; allTextInvisible = gFalse; extractFontFiles = gFalse; + convertFormFields = gFalse; + embedBackgroundImage = gFalse; + embedFonts = gFalse; // set up the TextOutputDev - textOutControl.mode = textOutReadingOrder; + textOutControl.mode = tableMode ? textOutTableLayout : textOutReadingOrder; textOutControl.html = gTrue; textOutControl.splitRotatedWords = gTrue; textOut = new TextOutputDev(NULL, &textOutControl, gFalse); @@ -266,15 +353,18 @@ static int pf(int (*writeFunc)(void *stream, const char *data, int size), } struct PNGWriteInfo { + Base64Encoder *base64; int (*writePNG)(void *stream, const char *data, int size); void *pngStream; }; static void pngWriteFunc(png_structp png, png_bytep data, png_size_t size) { - PNGWriteInfo *info; - - info = (PNGWriteInfo *)png_get_progressive_ptr(png); - info->writePNG(info->pngStream, (char *)data, (int)size); + PNGWriteInfo *info = (PNGWriteInfo *)png_get_progressive_ptr(png); + if (info->base64) { + info->base64->encode(data, size); + } else { + info->writePNG(info->pngStream, (char *)data, (int)size); + } } int HTMLGen::convertPage( @@ -304,31 +394,10 @@ int HTMLGen::convertPage( // generate the background bitmap splashOut->setSkipText(!allTextInvisible, gFalse); - doc->displayPage(splashOut, pg, backgroundResolution, backgroundResolution, + doc->displayPage(splashOut, pg, + backgroundResolution, backgroundResolution * vStretch, 0, gFalse, gTrue, gFalse); bitmap = splashOut->getBitmap(); - if (!(png = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL)) || - !(pngInfo = png_create_info_struct(png))) { - return errFileIO; - } - if (setjmp(png_jmpbuf(png))) { - return errFileIO; - } - writeInfo.writePNG = writePNG; - writeInfo.pngStream = pngStream; - png_set_write_fn(png, &writeInfo, pngWriteFunc, NULL); - png_set_IHDR(png, pngInfo, bitmap->getWidth(), bitmap->getHeight(), - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, pngInfo); - p = bitmap->getDataPtr(); - for (y = 0; y < bitmap->getHeight(); ++y) { - png_write_row(png, (png_bytep)p); - p += bitmap->getRowSize(); - } - png_write_end(png, pngInfo); - png_destroy_write_struct(&png, &pngInfo); // page size if (doc->getPageRotate(pg) == 90 || doc->getPageRotate(pg) == 270) { @@ -345,12 +414,86 @@ int HTMLGen::convertPage( text = textOut->takeText(); primaryDir = text->primaryDirectionIsLR() ? 1 : -1; + // insert a special character for each form field; + // remove existing characters inside field bboxes; + // erase background content inside field bboxes + formFieldFont = NULL; + formFieldInfo = NULL; + if (convertFormFields) { + AcroForm *form = doc->getCatalog()->getForm(); + if (form) { + formFieldInfo = new GList(); + formFieldFont = new TextFontInfo(); + double yTop = doc->getCatalog()->getPage(pg)->getMediaBox()->y2; + for (i = 0; i < form->getNumFields(); ++i) { + AcroFormField *field = form->getField(i); + AcroFormFieldType fieldType = field->getAcroFormFieldType(); + if (field->getPageNum() == pg && + (fieldType == acroFormFieldText || + fieldType == acroFormFieldCheckbox)) { + double llx, lly, urx, ury; + field->getBBox(&llx, &lly, &urx, &ury); + lly = yTop - lly; + ury = yTop - ury; + + // add the field info + int fieldIdx = formFieldInfo->getLength(); + formFieldInfo->append(new HTMLGenFormFieldInfo(field)); + + // remove exsting chars + text->removeChars(llx, ury, urx, lly, 0.75, 0.5); + + // erase background content + int llxI = (int)(llx * backgroundResolution / 72 + 0.5); + int llyI = (int)(lly * backgroundResolution * vStretch / 72 + 0.5); + int urxI = (int)(urx * backgroundResolution / 72 + 0.5); + int uryI = (int)(ury * backgroundResolution * vStretch / 72 + 0.5); + llyI += (int)(backgroundResolution * vStretch / 20); + if (llxI < 0) { + llxI = 0; + } + if (urxI >= bitmap->getWidth()) { + urxI = bitmap->getWidth() - 1; + } + if (uryI < 0) { + uryI = 0; + } + if (llyI > bitmap->getHeight()) { + llyI = bitmap->getHeight() - 1; + } + if (uryI <= llyI && llxI <= urxI) { + SplashColorPtr p = bitmap->getDataPtr() + + uryI * bitmap->getRowSize() + llxI * 3; + for (int y = uryI; y <= llyI; ++y) { + memset(p, 0xff, (urxI - llxI + 1) * 3); + p += bitmap->getRowSize(); + } + } + + // add a special char + // (the font size is unused -- 10 is an arbitrary value) + text->addSpecialChar(llx, ury, urx, lly, + 0, formFieldFont, 10, 0x80000000 + fieldIdx); + } + } + } + } + // HTML header pr(writeHTML, htmlStream, "<html>\n"); pr(writeHTML, htmlStream, "<head>\n"); pr(writeHTML, htmlStream, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); pr(writeHTML, htmlStream, "<style type=\"text/css\">\n"); pr(writeHTML, htmlStream, ".txt { white-space:nowrap; }\n"); + if (convertFormFields) { + pr(writeHTML, htmlStream, ".textfield {\n"); + pr(writeHTML, htmlStream, " border: 0;\n"); + pr(writeHTML, htmlStream, " padding: 0;\n"); + pr(writeHTML, htmlStream, " background: #ccccff;\n"); + pr(writeHTML, htmlStream, "}\n"); + pr(writeHTML, htmlStream, ".checkbox {\n"); + pr(writeHTML, htmlStream, "}\n"); + } fonts = text->getFonts(); fontScales = (double *)gmallocn(fonts->getLength(), sizeof(double)); for (i = 0; i < fontDefns->getLength(); ++i) { @@ -363,7 +506,7 @@ int HTMLGen::convertPage( if (!fontDefn->used && fontDefn->fontFace) { pr(writeHTML, htmlStream, fontDefn->fontFace->getCString()); } - pf(writeHTML, htmlStream, "#f{0:d} {{ {1:t} }}\n", i, fontDefn->fontSpec); + pf(writeHTML, htmlStream, ".f{0:d} {{ {1:t} }}\n", i, fontDefn->fontSpec); fontScales[i] = fontDefn->scale; fontDefn->used = gTrue; } @@ -374,15 +517,59 @@ int HTMLGen::convertPage( } else { pr(writeHTML, htmlStream, "<body dir=\"rtl\">\n"); } + + // background image element (part 1) if (primaryDir >= 0) { - pf(writeHTML, htmlStream, "<img id=\"background\" style=\"position:absolute; left:0px; top:0px;\" width=\"{0:d}\" height=\"{1:d}\" src=\"{2:s}\">\n", - (int)(pageW * zoom), (int)(pageH * zoom), pngURL); + pf(writeHTML, htmlStream, "<img style=\"position:absolute; left:0px; top:0px;\" width=\"{0:d}\" height=\"{1:d}\" ", + (int)(pageW * zoom), (int)(pageH * zoom * vStretch)); + } else { + pf(writeHTML, htmlStream, "<img style=\"position:absolute; right:0px; top:0px;\" width=\"{0:d}\" height=\"{1:d}\" ", + (int)(pageW * zoom), (int)(pageH * zoom * vStretch)); + } + if (embedBackgroundImage) { + pr(writeHTML, htmlStream, "src=\"data:image/png;base64,\n"); + writeInfo.base64 = new Base64Encoder(writeHTML, htmlStream); + writeInfo.writePNG = NULL; + writeInfo.pngStream = NULL; } else { - pf(writeHTML, htmlStream, "<img id=\"background\" style=\"position:absolute; right:0px; top:0px;\" width=\"{0:d}\" height=\"{1:d}\" src=\"{2:s}\">\n", - (int)(pageW * zoom), (int)(pageH * zoom), pngURL); + pf(writeHTML, htmlStream, "src=\"{0:s}\"", pngURL); + writeInfo.base64 = NULL; + writeInfo.writePNG = writePNG; + writeInfo.pngStream = pngStream; } + // background image data - writing to a separate file, or embedding + // with base64 encoding + if (!(png = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) || + !(pngInfo = png_create_info_struct(png))) { + return errFileIO; + } + if (setjmp(png_jmpbuf(png))) { + return errFileIO; + } + png_set_write_fn(png, &writeInfo, pngWriteFunc, NULL); + png_set_IHDR(png, pngInfo, bitmap->getWidth(), bitmap->getHeight(), + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, pngInfo); + p = bitmap->getDataPtr(); + for (y = 0; y < bitmap->getHeight(); ++y) { + png_write_row(png, (png_bytep)p); + p += bitmap->getRowSize(); + } + png_write_end(png, pngInfo); + png_destroy_write_struct(&png, &pngInfo); + if (embedBackgroundImage) { + writeInfo.base64->flush(); + delete writeInfo.base64; + } + + // background image element (part 2) + pr(writeHTML, htmlStream, "\">\n"); + // generate the HTML text + nextFieldID = 0; cols = text->makeColumns(); for (colIdx = 0; colIdx < cols->getLength(); ++colIdx) { col = (TextColumn *)cols->get(colIdx); @@ -416,11 +603,11 @@ int HTMLGen::convertPage( if (primaryDir >= 0) { pf(writeHTML, htmlStream, "<div class=\"txt\" style=\"position:absolute; left:{0:d}px; top:{1:d}px;\">{2:t}</div>\n", (int)(line->getXMin() * zoom), - (int)(line->getYMin() * zoom), s); + (int)(line->getYMin() * zoom * vStretch), s); } else { pf(writeHTML, htmlStream, "<div class=\"txt\" style=\"position:absolute; right:{0:d}px; top:{1:d}px;\">{2:t}</div>\n", (int)((pageW - line->getXMax()) * zoom), - (int)(line->getYMin() * zoom), s); + (int)(line->getYMin() * zoom * vStretch), s); } delete s; } @@ -429,6 +616,14 @@ int HTMLGen::convertPage( gfree(fontScales); delete text; deleteGList(cols, TextColumn); + if (formFieldFont) { + delete formFieldFont; + formFieldFont = NULL; + } + if (formFieldInfo) { + deleteGList(formFieldInfo, HTMLGenFormFieldInfo); + formFieldInfo = NULL; + } // HTML trailer pr(writeHTML, htmlStream, "</body>\n"); @@ -471,134 +666,200 @@ int HTMLGen::findDirSpan(GList *words, int firstWordIdx, int primaryDir, void HTMLGen::appendSpans(GList *words, int firstWordIdx, int lastWordIdx, int primaryDir, int spanDir, double base, GBool dropCapLine, GString *s) { - TextWord *word0, *word1; - VerticalAlignment vertAlign0, vertAlign1; - const char *dirTag; - Unicode u; - GBool invisible, sp; - double r0, g0, b0, r1, g1, b1; - double base1; - int wordIdx, t, i; + if (allTextInvisible && !drawInvisibleText) { + return; + } if (spanDir != primaryDir) { - t = firstWordIdx; + int t = firstWordIdx; firstWordIdx = lastWordIdx; lastWordIdx = t; } - word0 = NULL; - vertAlign0 = vertAlignBaseline; // make gcc happy - r0 = g0 = b0 = 0; // make gcc happy - for (wordIdx = firstWordIdx; - (spanDir >= 0) ? wordIdx <= lastWordIdx : wordIdx >= lastWordIdx; - wordIdx += spanDir) { - word1 = (TextWord *)words->get(wordIdx); - invisible = allTextInvisible || word1->isInvisible() || word1->isRotated(); - if (!drawInvisibleText && invisible) { - continue; - } - word1->getColor(&r1, &g1, &b1); - base1 = word1->getBaseline(); - if (dropCapLine) { - //~ this will fail if there are subscripts or superscripts in - //~ the first line of a paragraph with a drop cap - vertAlign1 = vertAlignTop; - } else if (base1 - base < -1) { - vertAlign1 = vertAlignSuper; - } else if (base1 - base > 1) { - vertAlign1 = vertAlignSub; - } else { - vertAlign1 = vertAlignBaseline; - } - if (!word0 || - word1->getFontInfo() != word0->getFontInfo() || - word1->getFontSize() != word0->getFontSize() || - word1->isInvisible() != word0->isInvisible() || - word1->isRotated() != word0->isRotated() || - vertAlign1 != vertAlign0 || - r1 != r0 || g1 != g0 || b1 != b0) { - if (word0) { - s->append("</span>"); - } - for (i = 0; i < fonts->getLength(); ++i) { - if (word1->getFontInfo() == (TextFontInfo *)fonts->get(i)) { - break; + int wordIdx = firstWordIdx; + while ((spanDir >= 0) ? wordIdx <= lastWordIdx + : wordIdx >= lastWordIdx) { + TextWord *word0 = (TextWord *)words->get(wordIdx); + + // form field(s): generate <input> element(s) + if (convertFormFields && word0->getFontInfo() == formFieldFont) { + for (int i = (spanDir >= 0) ? 0 : word0->getLength() - 1; + (spanDir >= 0) ? i < word0->getLength() : i >= 0; + i += spanDir) { + int fieldIdx = word0->getChar(0) - 0x80000000; + if (fieldIdx >= 0 && fieldIdx < formFieldInfo->getLength()) { + HTMLGenFormFieldInfo *ffi = + (HTMLGenFormFieldInfo *)formFieldInfo->get(fieldIdx); + AcroFormField *field = ffi->acroFormField; + AcroFormFieldType fieldType = field->getAcroFormFieldType(); + double llx, lly, urx, ury; + field->getBBox(&llx, &lly, &urx, &ury); + int width = (int)(urx - llx); + Ref fontID; + double fontSize; + field->getFont(&fontID, &fontSize); + if (fontSize == 0) { + fontSize = 12; + } + if (fieldType == acroFormFieldText) { + s->appendf("<input type=\"text\" class=\"textfield\" id=\"textfield{0:d}\" style=\"width:{1:d}px; font-size:{2:d}px;\">", nextFieldID, width, (int)(fontSize + 0.5)); + ++nextFieldID; + } else if (fieldType == acroFormFieldCheckbox) { + s->appendf("<input type=\"checkbox\" class=\"checkbox\" id=\"checkbox{0:d}\" style=\"width:{1:d}px; font-size:{2:d}px;\">", nextFieldID, width, (int)(fontSize + 0.5)); + ++nextFieldID; + } } } - // we force spans to be LTR or RTL; this is a kludge, but it's - // far easier than implementing the full Unicode bidi algorithm - if (spanDir == primaryDir) { - dirTag = ""; - } else if (spanDir < 0) { - dirTag = " dir=\"rtl\""; - } else { - dirTag = " dir=\"ltr\""; + + if (word0->getSpaceAfter()) { + s->append(' '); } - s->appendf("<span id=\"f{0:d}\"{1:s} style=\"font-size:{2:d}px;vertical-align:{3:s};{4:s}color:rgba({5:d},{6:d},{7:d},{8:d});\">", - i, - dirTag, - (int)(fontScales[i] * word1->getFontSize() * zoom), - vertAlignNames[vertAlign1], - (dropCapLine && wordIdx == 0) ? "line-height:75%;" : "", - (int)(r1 * 255), (int)(g1 * 255), (int)(b1 * 255), - invisible ? 0 : 1); - } - // add a space before the word, if needed - // -- this only happens with the first word in a reverse section - if (spanDir != primaryDir && wordIdx == firstWordIdx) { - if (spanDir >= 0) { - if (wordIdx > 0) { - sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter(); + wordIdx += spanDir; + + // skip invisible words + } else if (!drawInvisibleText && + (word0->isInvisible() || word0->isRotated())) { + wordIdx += spanDir; + + // generate a <span> containing one or more words + } else { + + double r0 = 0, g0 = 0, b0 = 0; // make gcc happy + VerticalAlignment vertAlign0 = vertAlignBaseline; // make gcc happy + GString *linkURI0 = NULL; + + GBool invisible = word0->isInvisible() || word0->isRotated(); + + do { + TextWord *word1 = (TextWord *)words->get(wordIdx); + + // get word parameters + double r1, g1, b1; + word0->getColor(&r1, &g1, &b1); + double base1 = word1->getBaseline(); + VerticalAlignment vertAlign1; + if (dropCapLine) { + //~ this will fail if there are subscripts or superscripts in + //~ the first line of a paragraph with a drop cap + vertAlign1 = vertAlignTop; + } else if (base1 - base < -1) { + vertAlign1 = vertAlignSuper; + } else if (base1 - base > 1) { + vertAlign1 = vertAlignSub; } else { + vertAlign1 = vertAlignBaseline; + } + GString *linkURI1 = word1->getLinkURI(); + + // start of span + if (word1 == word0) { + r0 = r1; + g0 = g1; + b0 = b1; + vertAlign0 = vertAlign1; + linkURI0 = linkURI1; + + int i; + for (i = 0; i < fonts->getLength(); ++i) { + if (word1->getFontInfo() == (TextFontInfo *)fonts->get(i)) { + break; + } + } + if (linkURI1) { + s->appendf("<a href=\"{0:t}\">", linkURI0); + } + // we force spans to be LTR or RTL; this is a kludge, but it's + // far easier than implementing the full Unicode bidi algorithm + const char *dirTag; + if (spanDir == primaryDir) { + dirTag = ""; + } else if (spanDir < 0) { + dirTag = " dir=\"rtl\""; + } else { + dirTag = " dir=\"ltr\""; + } + s->appendf("<span class=\"f{0:d}\"{1:s} style=\"font-size:{2:d}px;vertical-align:{3:s};{4:s}color:rgba({5:d},{6:d},{7:d},{8:d});\">", + i, + dirTag, + (int)(fontScales[i] * word1->getFontSize() * zoom), + vertAlignNames[vertAlign1], + (dropCapLine && wordIdx == 0) ? "line-height:75%;" : "", + (int)(r0 * 255), (int)(g0 * 255), (int)(b0 * 255), + invisible ? 0 : 1); + + // end of span + } else if (word1->getFontInfo() != word0->getFontInfo() || + word1->getFontSize() != word0->getFontSize() || + word1->isInvisible() != word0->isInvisible() || + word1->isRotated() != word0->isRotated() || + vertAlign1 != vertAlign0 || + r1 != r0 || g1 != g0 || b1 != b0 || + linkURI1 != linkURI0) { + break; + } + + // add a space before the word, if needed + // -- this only happens with the first word in a reverse section + if (spanDir != primaryDir && wordIdx == firstWordIdx) { + GBool sp; + if (spanDir >= 0) { + if (wordIdx > 0) { + sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter(); + } else { + sp = gFalse; + } + } else { + sp = word1->getSpaceAfter(); + } + if (sp) { + s->append(' '); + } + } + + // generate the word text + for (int i = (spanDir >= 0) ? 0 : word1->getLength() - 1; + (spanDir >= 0) ? i < word1->getLength() : i >= 0; + i += spanDir) { + Unicode u = word1->getChar(i); + if (u >= privateUnicodeMapStart && + u <= privateUnicodeMapEnd && + privateUnicodeMap[u - privateUnicodeMapStart]) { + u = privateUnicodeMap[u - privateUnicodeMapStart]; + } + appendUTF8(u, s); + } + + // add a space after the word, if needed + // -- there is never a space after the last word in a reverse + // section (this will be handled as a space after the last + // word in the previous primary-direction section) + GBool sp; + if (spanDir != primaryDir && wordIdx == lastWordIdx) { sp = gFalse; + } else if (spanDir >= 0) { + sp = word1->getSpaceAfter(); + } else { + if (wordIdx > 0) { + sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter(); + } else { + sp = gFalse; + } + } + if (sp) { + s->append(' '); } - } else { - sp = word1->getSpaceAfter(); - } - if (sp) { - s->append(' '); - } - } - for (i = (spanDir >= 0) ? 0 : word1->getLength() - 1; - (spanDir >= 0) ? i < word1->getLength() : i >= 0; - i += spanDir) { - u = word1->getChar(i); - if (u >= privateUnicodeMapStart && - u <= privateUnicodeMapEnd && - privateUnicodeMap[u - privateUnicodeMapStart]) { - u = privateUnicodeMap[u - privateUnicodeMapStart]; - } - appendUTF8(u, s); - } + wordIdx += spanDir; + } while ((spanDir >= 0) ? wordIdx <= lastWordIdx + : wordIdx >= lastWordIdx); - // add a space after the word, if needed - // -- there is never a space after the last word in a reverse - // section (this will be handled as a space after the last word - // in the previous primary-direction section) - if (spanDir != primaryDir && wordIdx == lastWordIdx) { - sp = gFalse; - } else if (spanDir >= 0) { - sp = word1->getSpaceAfter(); - } else { - if (wordIdx > 0) { - sp = ((TextWord *)words->get(wordIdx - 1))->getSpaceAfter(); - } else { - sp = gFalse; + s->append("</span>"); + if (linkURI0) { + s->append("</a>"); } } - if (sp) { - s->append(' '); - } - - word0 = word1; - vertAlign0 = vertAlign1; - r0 = r1; - g0 = g1; - b0 = b1; } - s->append("</span>"); } void HTMLGen::appendUTF8(Unicode u, GString *s) { @@ -694,36 +955,69 @@ HTMLGenFontDefn *HTMLGen::getFontFile(TextFontInfo *font, gfxFont = GfxFont::makeFont(doc->getXRef(), "F", id, fontObj.getDict()); webFont = new WebFont(gfxFont, doc->getXRef()); fontDefn = NULL; + fontFace = 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); + if (embedFonts) { + GString *ttfData = webFont->getTTFData(); + if (ttfData) { + fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"data:font/ttf;base64,", + nextFontFaceIdx); + Base64Encoder enc(writeToString, fontFace); + enc.encode((unsigned char *)ttfData->getCString(), + (size_t)ttfData->getLength()); + enc.flush(); + fontFace->append("\"); }\n"); + delete ttfData; + } + } else { + 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); + } + delete fontPath; + delete fontFile; + } + if (fontFace) { 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); + if (embedFonts) { + GString *otfData = webFont->getOTFData(); + if (otfData) { + fontFace = GString::format("@font-face {{ font-family: ff{0:d}; src: url(\"data:font/otf;base64,", + nextFontFaceIdx); + Base64Encoder enc(writeToString, fontFace); + enc.encode((unsigned char *)otfData->getCString(), + (size_t)otfData->getLength()); + enc.flush(); + fontFace->append("\"); }\n"); + delete otfData; + } + } else { + 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); + } + delete fontPath; + delete fontFile; + } + if (fontFace) { 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; } delete webFont; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h index d09eea3f266..66ee2d27406 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h @@ -2,7 +2,7 @@ // // HTMLGen.h // -// Copyright 2010 Glyph & Cog, LLC +// Copyright 2010-2021 Glyph & Cog, LLC // //======================================================================== @@ -27,7 +27,7 @@ class HTMLGenFontDefn; class HTMLGen { public: - HTMLGen(double backgroundResolutionA); + HTMLGen(double backgroundResolutionA, GBool tableMode); ~HTMLGen(); GBool isOk() { return ok; } @@ -39,6 +39,8 @@ public: double getZoom() { return zoom; } void setZoom(double zoomA) { zoom = zoomA; } + void setVStretch(double vStretchA) { vStretch = vStretchA; } + GBool getDrawInvisibleText() { return drawInvisibleText; } void setDrawInvisibleText(GBool drawInvisibleTextA) { drawInvisibleText = drawInvisibleTextA; } @@ -50,6 +52,15 @@ public: void setExtractFontFiles(GBool extractFontFilesA) { extractFontFiles = extractFontFilesA; } + void setConvertFormFields(GBool convertFormFieldsA) + { convertFormFields = convertFormFieldsA; } + + void setEmbedBackgroundImage(GBool embedBackgroundImageA) + { embedBackgroundImage = embedBackgroundImageA; } + + void setEmbedFonts(GBool embedFontsA) + { embedFonts = embedFontsA; } + void startDoc(PDFDoc *docA); int convertPage(int pg, const char *pngURL, const char *htmlDir, int (*writeHTML)(void *stream, const char *data, int size), @@ -74,9 +85,13 @@ private: double backgroundResolution; double zoom; + double vStretch; GBool drawInvisibleText; GBool allTextInvisible; GBool extractFontFiles; + GBool convertFormFields; + GBool embedBackgroundImage; + GBool embedFonts; PDFDoc *doc; TextOutputDev *textOut; @@ -88,6 +103,10 @@ private: GList *fontDefns; // [HTMLGenFontDefn] int nextFontFaceIdx; + TextFontInfo *formFieldFont; + GList *formFieldInfo; // [HTMLGenFormFieldInfo] + int nextFieldID; + 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 4c4e5183026..02450b4f816 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc @@ -1147,6 +1147,7 @@ JBIG2CodeTable::~JBIG2CodeTable() { JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA): FilterStream(strA) { + decoded = gFalse; pageBitmap = NULL; arithDecoder = new JArithmeticDecoder(); @@ -1205,40 +1206,9 @@ Stream *JBIG2Stream::copy() { } void JBIG2Stream::reset() { - GList *t; - segments = new GList(); globalSegments = new GList(); - - // read the globals stream - if (globalsStream.isStream()) { - curStr = globalsStream.getStream(); - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - curStr->close(); - // swap the newly read segments list into globalSegments - t = segments; - segments = globalSegments; - globalSegments = t; - } - - // read the main stream - curStr = str; - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - - if (pageBitmap) { - dataPtr = pageBitmap->getDataPtr(); - dataEnd = dataPtr + pageBitmap->getDataSize(); - } else { - dataPtr = dataEnd = NULL; - } + decoded = gFalse; } void JBIG2Stream::close() { @@ -1259,6 +1229,9 @@ void JBIG2Stream::close() { } int JBIG2Stream::getChar() { + if (!decoded) { + decodeImage(); + } if (dataPtr && dataPtr < dataEnd) { return (*dataPtr++ ^ 0xff) & 0xff; } @@ -1266,6 +1239,9 @@ int JBIG2Stream::getChar() { } int JBIG2Stream::lookChar() { + if (!decoded) { + decodeImage(); + } if (dataPtr && dataPtr < dataEnd) { return (*dataPtr ^ 0xff) & 0xff; } @@ -1275,6 +1251,9 @@ int JBIG2Stream::lookChar() { int JBIG2Stream::getBlock(char *blk, int size) { int n, i; + if (!decoded) { + decodeImage(); + } if (size <= 0) { return 0; } @@ -1298,6 +1277,42 @@ GBool JBIG2Stream::isBinary(GBool last) { return str->isBinary(gTrue); } +void JBIG2Stream::decodeImage() { + GList *t; + + // read the globals stream + if (globalsStream.isStream()) { + curStr = globalsStream.getStream(); + curStr->reset(); + arithDecoder->setStream(curStr); + huffDecoder->setStream(curStr); + mmrDecoder->setStream(curStr); + readSegments(); + curStr->close(); + // swap the newly read segments list into globalSegments + t = segments; + segments = globalSegments; + globalSegments = t; + } + + // read the main stream + curStr = str; + curStr->reset(); + arithDecoder->setStream(curStr); + huffDecoder->setStream(curStr); + mmrDecoder->setStream(curStr); + readSegments(); + + if (pageBitmap) { + dataPtr = pageBitmap->getDataPtr(); + dataEnd = dataPtr + pageBitmap->getDataSize(); + } else { + dataPtr = dataEnd = NULL; + } + + decoded = gTrue; +} + void JBIG2Stream::readSegments() { Guint segNum, segFlags, segType, page, segLength; Guint refFlags, nRefSegs; @@ -2042,7 +2057,14 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, for (i = 0; i < nRefSegs; ++i) { if ((seg = findSegment(refSegs[i]))) { if (seg->getType() == jbig2SegSymbolDict) { - numSyms += ((JBIG2SymbolDict *)seg)->getSize(); + Guint segSize = ((JBIG2SymbolDict *)seg)->getSize(); + if (segSize > INT_MAX || numSyms > INT_MAX - segSize) { + error(errSyntaxError, getPos(), + "Too many symbols in JBIG2 text region"); + delete codeTables; + return; + } + numSyms += segSize; } else if (seg->getType() == jbig2SegCodeTable) { codeTables->append(seg); } @@ -3933,6 +3955,11 @@ void JBIG2Stream::readPageInfoSeg(Guint length) { pageDefPixel = (flags >> 2) & 1; defCombOp = (flags >> 3) & 3; + // this will only happen if there are multiple page info segments + if (pageBitmap) { + delete pageBitmap; + } + // allocate the page bitmap if (pageH == 0xffffffff) { curPageH = striping & 0x7fff; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h index cca722b4bfc..bb44ba1ab01 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h @@ -48,6 +48,7 @@ public: private: + void decodeImage(); void readSegments(); GBool readSymbolDictSeg(Guint segNum, Guint length, Guint *refSegs, Guint nRefSegs); @@ -117,6 +118,7 @@ private: GBool readULong(Guint *x); GBool readLong(int *x); + GBool decoded; Object globalsStream; Guint pageW, pageH, curPageH; Guint pageDefPixel; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc index d9c295bb12c..a1f7395dd57 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc @@ -230,6 +230,7 @@ JPXStream::JPXStream(Stream *strA): { bufStr = new BufStream(str, 3); + decoded = gFalse; nComps = 0; bpc = NULL; width = height = 0; @@ -270,15 +271,7 @@ Stream *JPXStream::copy() { void JPXStream::reset() { img.ySize = 0; bufStr->reset(); - if (readBoxes() == jpxDecodeFatalError) { - // readBoxes reported an error, so we go immediately to EOF - curY = img.ySize >> reduction; - } else { - curY = img.yOffsetR; - } - curX = img.xOffsetR; - curComp = 0; - readBufLen = 0; + decoded = gFalse; } void JPXStream::close() { @@ -363,9 +356,25 @@ void JPXStream::close() { bufStr->close(); } +void JPXStream::decodeImage() { + if (readBoxes() == jpxDecodeFatalError) { + // readBoxes reported an error, so we go immediately to EOF + curY = img.ySize >> reduction; + } else { + curY = img.yOffsetR; + } + curX = img.xOffsetR; + curComp = 0; + readBufLen = 0; + decoded = gTrue; +} + int JPXStream::getChar() { int c; + if (!decoded) { + decodeImage(); + } if (readBufLen < 8) { fillReadBuf(); } @@ -387,6 +396,9 @@ int JPXStream::getChar() { int JPXStream::lookChar() { int c; + if (!decoded) { + decodeImage(); + } if (readBufLen < 8) { fillReadBuf(); } @@ -420,10 +432,18 @@ void JPXStream::fillReadBuf() { #else tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp]; #endif - tx = jpxFloorDiv(curX - jpxCeilDivPow2(img.tiles[tileIdx].x0, reduction), - tileComp->hSep); - ty = jpxFloorDiv(curY - jpxCeilDivPow2(img.tiles[tileIdx].y0, reduction), - tileComp->vSep); + tx = jpxFloorDiv(curX, tileComp->hSep); + if (tx < tileComp->x0r) { + tx = 0; + } else { + tx -= tileComp->x0r; + } + ty = jpxFloorDiv(curY, tileComp->vSep); + if (ty < tileComp->y0r) { + ty = 0; + } else { + ty -= tileComp->y0r; + } pix = (int)tileComp->data[ty * tileComp->w + tx]; pixBits = tileComp->prec; eol = gFalse; @@ -1061,6 +1081,12 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); return jpxDecodeFatalError; } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return jpxDecodeFatalError; + } img.tiles[0].tileComps[0].resLevels[r].precinctWidth = precinctSize & 0x0f; img.tiles[0].tileComps[0].resLevels[r].precinctHeight = @@ -1135,6 +1161,12 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); return jpxDecodeFatalError; } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return jpxDecodeFatalError; + } img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = precinctSize & 0x0f; img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = @@ -1579,6 +1611,12 @@ GBool JPXStream::readTilePart() { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); return gFalse; } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return gFalse; + } img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = precinctSize & 0x0f; img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = @@ -1643,6 +1681,12 @@ GBool JPXStream::readTilePart() { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); return gFalse; } + if (r > 0 && ((precinctSize & 0x0f) == 0 || + (precinctSize & 0xf0) == 0)) { + error(errSyntaxError, getPos(), + "Invalid precinct size in JPX COD marker segment"); + return gFalse; + } img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = precinctSize & 0x0f; img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = @@ -1886,9 +1930,9 @@ GBool JPXStream::readTilePart() { for (comp = 0; comp < img.nComps; ++comp) { tileComp = &img.tiles[tileIdx].tileComps[comp]; qStyle = tileComp->quantStyle & 0x1f; - if ((qStyle == 0 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels) || + if ((qStyle == 0 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels + 1) || (qStyle == 1 && tileComp->nQuantSteps < 1) || - (qStyle == 2 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels)) { + (qStyle == 2 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels + 1)) { error(errSyntaxError, getPos(), "Too few quant steps in JPX tile part"); return gFalse; } @@ -1917,6 +1961,7 @@ GBool JPXStream::readTilePart() { tile->layer = 0; tile->done = gFalse; tile->maxNDecompLevels = 0; + tile->maxNPrecincts = 0; for (comp = 0; comp < img.nComps; ++comp) { tileComp = &tile->tileComps[comp]; if (tileComp->nDecompLevels > tile->maxNDecompLevels) { @@ -1926,11 +1971,12 @@ GBool JPXStream::readTilePart() { tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->vSep); tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep); tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep); - 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) { + tileComp->x0r = jpxCeilDivPow2(tileComp->x0, reduction); + tileComp->w = jpxCeilDivPow2(tileComp->x1, reduction) - tileComp->x0r; + tileComp->y0r = jpxCeilDivPow2(tileComp->y0, reduction); + tileComp->h = jpxCeilDivPow2(tileComp->y1, reduction) - tileComp->y0r; + if (tileComp->w == 0 || tileComp->h == 0 || + tileComp->w > INT_MAX / tileComp->h) { error(errSyntaxError, getPos(), "Invalid tile size or sample separation in JPX stream"); return gFalse; @@ -2008,6 +2054,9 @@ GBool JPXStream::readTilePart() { resLevel->nPrecincts = (preCol1 - preCol0) * (preRow1 - preRow0); resLevel->precincts = (JPXPrecinct *)gmallocn(resLevel->nPrecincts, sizeof(JPXPrecinct)); + if (resLevel->nPrecincts > tile->maxNPrecincts) { + tile->maxNPrecincts = resLevel->nPrecincts; + } for (pre = 0; pre < resLevel->nPrecincts; ++pre) { resLevel->precincts[pre].subbands = NULL; } @@ -2169,14 +2218,15 @@ 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 the tile is finished, skip any remaining data + if (tile->done) { + bufStr->discardChars(tilePartLen); + return gTrue; + } + if (tilePartToEOC) { //~ peek for an EOC marker cover(93); @@ -2425,90 +2475,110 @@ GBool JPXStream::readTilePartData(Guint tileIdx, switch (tile->progOrder) { case 0: // layer, resolution level, component, precinct cover(58); - resLevel = &tile->tileComps[tile->comp].resLevels[tile->res]; - if (++tile->precinct == resLevel->nPrecincts) { - tile->precinct = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - tile->done = gTrue; + do { + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + tile->done = gTrue; + } } } } - } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); break; case 1: // resolution level, layer, component, precinct cover(59); - resLevel = &tile->tileComps[tile->comp].resLevels[tile->res]; - if (++tile->precinct == resLevel->nPrecincts) { - tile->precinct = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - tile->done = gTrue; + do { + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + tile->done = gTrue; + } } } } - } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); break; case 2: // resolution level, precinct, component, layer cover(60); //~ this is incorrect if there are subsampled components (?) - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - resLevel = &tile->tileComps[tile->comp].resLevels[tile->res]; - if (++tile->precinct == resLevel->nPrecincts) { - tile->precinct = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - tile->done = gTrue; + do { + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + tile->done = gTrue; + } } } } - } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); break; case 3: // precinct, component, resolution level, layer cover(61); //~ this is incorrect if there are subsampled components (?) - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - resLevel = &tile->tileComps[tile->comp].resLevels[tile->res]; - if (++tile->precinct == resLevel->nPrecincts) { - tile->precinct = 0; - tile->done = gTrue; + do { + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + tile->done = gTrue; + } } } } - } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); break; case 4: // component, precinct, resolution level, layer cover(62); - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - resLevel = &tile->tileComps[tile->comp].resLevels[tile->res]; - if (++tile->precinct == resLevel->nPrecincts) { - tile->precinct = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - tile->done = gTrue; + do { + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->precinct == tile->maxNPrecincts) { + tile->precinct = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + tile->done = gTrue; + } } } } - } + } while (!tile->done && + (tile->res > tile->tileComps[tile->comp].nDecompLevels || + tile->precinct >= tile->tileComps[tile->comp] + .resLevels[tile->res].nPrecincts)); break; } } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h index 510826cd162..4b8587b0fb2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h @@ -202,6 +202,7 @@ struct JPXTileComp { //----- computed Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords + Guint x0r, y0r; // x0 >> reduction, y0 >> reduction Guint w, h; // data size = {x1 - x0, y1 - y0} >> reduction //----- image data @@ -228,6 +229,8 @@ struct JPXTile { Guint x0, y0, x1, y1; // bounds of the tile, in ref coords Guint maxNDecompLevels; // max number of decomposition levels used // in any component in this tile + Guint maxNPrecincts; // max number of precints in any + // component/res level in this tile //----- progression order loop counters Guint comp; // component @@ -294,6 +297,7 @@ public: private: + void decodeImage(); void fillReadBuf(); void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode); JPXDecodeResult readBoxes(); @@ -329,6 +333,7 @@ private: BufStream *bufStr; // buffered stream (for lookahead) + GBool decoded; // set when the image has been decoded Guint nComps; // number of components Guint *bpc; // bits per component, for each component Guint width, height; // image size diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h index 6fe7eeedb4e..54483cfcc43 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h @@ -229,10 +229,10 @@ public: virtual void psXObject(Stream *psStream, Stream *level1Stream) {} //----- transparency groups and soft masks - virtual void beginTransparencyGroup(GfxState *state, double *bbox, - GfxColorSpace *blendingColorSpace, - GBool isolated, GBool knockout, - GBool forSoftMask) {} + virtual GBool beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { return gTrue; } virtual void endTransparencyGroup(GfxState *state) {} virtual void paintTransparencyGroup(GfxState *state, double *bbox) {} virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc index 877bcb88255..b833d5dabf0 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc @@ -421,7 +421,15 @@ void PDFCore::finishUpdate(GBool addToHist, GBool checkForChangedFile) { } // redraw - invalidateWholeWindow(); + // - if the bitmap is available (e.g., we just scrolled), we want to + // redraw immediately; if not, postpone the redraw until a + // tileDone or tick (incremental update) to avoid "flashing" the + // screen (drawing a blank background, followed by the actual + // content slightly later) + getWindowBitmap(gTrue); + if (bitmapFinished) { + invalidateWholeWindow(); + } updateScrollbars(); // add to history @@ -436,21 +444,28 @@ void PDFCore::addToHistory() { cur = &history[historyCur]; h.page = tileMap->getMidPage(); + h.fileName = NULL; #ifdef _WIN32 if (doc->getFileNameU()) { - h.fileName = (wchar_t *)gmallocn(MAX_PATH + 1, sizeof(wchar_t)); - if (GetFullPathNameW(doc->getFileNameU(), MAX_PATH + 1, - h.fileName, NULL) == 0) { - h.fileName = NULL; + wchar_t dummy; + // NB: if the buffer is too small, GetFullPathNameW returns a + // *maximum* required buffer size, which may be larger than the + // size actually used by the second call (it looks like it just + // adds the size of the current directory and the sizef of the + // input path) + DWORD nChars = GetFullPathNameW(doc->getFileNameU(), 1, &dummy, NULL); + if (nChars > 0) { + h.fileName = (wchar_t *)gmallocn(nChars, sizeof(wchar_t)); + if (GetFullPathNameW(doc->getFileNameU(), nChars, + h.fileName, NULL) == 0) { + gfree(h.fileName); + h.fileName = NULL; + } } - } else { - h.fileName = NULL; } #else if (doc->getFileName()) { h.fileName = doc->getFileName()->copy(); - } else { - h.fileName = NULL; } #endif if (historyBLen > 0 && h.page == cur->page) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc index 6efd4aac6c4..a6663ea4222 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc @@ -125,11 +125,11 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, init(coreA); // handle a Windows shortcut - wchar_t wPath[MAX_PATH + 1]; - int n = fileNameLen < MAX_PATH ? fileNameLen : MAX_PATH; + wchar_t wPath[winMaxLongPath + 1]; + int n = fileNameLen < winMaxLongPath ? fileNameLen : winMaxLongPath; memcpy(wPath, fileNameA, n * sizeof(wchar_t)); wPath[n] = L'\0'; - readWindowsShortcut(wPath, MAX_PATH + 1); + readWindowsShortcut(wPath, winMaxLongPath + 1); int wPathLen = (int)wcslen(wPath); // save both Unicode and 8-bit copies of the file name @@ -166,33 +166,32 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword, GString *userPassword, PDFCore *coreA) { -/* +#if 0 #ifdef _WIN32 OSVERSIONINFO version; #endif -*/ +#endif /* 0 */ Object obj; -/* +#if 0 #ifdef _WIN32 Unicode u; int i, j; #endif -*/ - +#endif /* 0 */ init(coreA); fileName = new GString(fileNameA); #if defined(_WIN32) #if 0 - wchar_t wPath[MAX_PATH + 1]; + wchar_t wPath[winMaxLongPath + 1]; i = 0; j = 0; - while (j < MAX_PATH && getUTF8(fileName, &i, &u)) { + while (j < winMaxLongPath && getUTF8(fileName, &i, &u)) { wPath[j++] = (wchar_t)u; } wPath[j] = L'\0'; - readWindowsShortcut(wPath, MAX_PATH + 1); + readWindowsShortcut(wPath, winMaxLongPath + 1); int wPathLen = (int)wcslen(wPath); fileNameU = (wchar_t *)gmallocn(wPathLen + 1, sizeof(wchar_t)); @@ -462,6 +461,11 @@ void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage, int page; for (page = firstPage; page <= lastPage; ++page) { + if (globalParams->getPrintStatusInfo()) { + fflush(stderr); + printf("[processing page %d]\n", page); + fflush(stdout); + } displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, printing, abortCheckCbk, abortCheckCbkData); catalog->doneWithPage(page); @@ -607,31 +611,31 @@ GBool PDFDoc::saveEmbeddedFileU(int idx, const char *path) { GBool PDFDoc::saveEmbeddedFile(int idx, const wchar_t *path, int pathLen) { FILE *f; OSVERSIONINFO version; - wchar_t path2w[_MAX_PATH + 1]; - char path2c[_MAX_PATH + 1]; + wchar_t path2w[winMaxLongPath + 1]; + char path2c[MAX_PATH + 1]; int i; GBool ret; // NB: _wfopen is only available in NT -/* +#if 0 version.dwOSVersionInfoSize = sizeof(version); GetVersionEx(&version); if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { - for (i = 0; i < pathLen && i < _MAX_PATH; ++i) { + for (i = 0; i < pathLen && i < winMaxLongPath; ++i) { path2w[i] = path[i]; } path2w[i] = 0; f = _wfopen(path2w, L"wb"); } else { -*/ - for (i = 0; i < pathLen && i < _MAX_PATH; ++i) { +#endif /* 0 */ + for (i = 0; i < pathLen && i < MAX_PATH; ++i) { path2c[i] = (char)path[i]; } path2c[i] = 0; f = fopen(path2c, "wb"); -/* +#if 0 } -*/ +#endif /* 0 */ if (!f) { return gFalse; } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h index 5069cb78689..2b8eba2cba7 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h @@ -162,6 +162,10 @@ public: GBool okToAddNotes(GBool ignoreOwnerPW = gFalse) { return xref->okToAddNotes(ignoreOwnerPW); } + // Is the PDF file damaged? This checks to see if the xref table + // was constructed by the repair code. + GBool isDamaged() { return xref->isRepaired(); } + // Is this document linearized? GBool isLinearized(); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc index 0c39472ba85..b9fff4ffaed 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc @@ -1481,6 +1481,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, rotate0 = -1; clipLLX0 = clipLLY0 = 0; clipURX0 = clipURY0 = -1; + expandSmallPages = globalParams->getPSExpandSmaller(); // initialize font lists, etc. for (i = 0; i < 14; ++i) { @@ -1581,6 +1582,11 @@ PSOutputDev::~PSOutputDev() { customColors = cc->next; delete cc; } + if (t3String) { + // this will only happen if the 'd1' operator is used outside of a + // Type 3 CharProc + delete t3String; + } } GBool PSOutputDev::checkIO() { @@ -3827,6 +3833,7 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask, } // filters + str->disableDecompressionBombChecking(); if (level < psLevel2) { useLZW = useRLE = gFalse; useCompressed = gFalse; @@ -4265,6 +4272,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, } break; case psLevel1Sep: +#if SPLASH_CMYK writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n", w, h, w, -h, h); p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize(); @@ -4299,6 +4307,8 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, processColors |= psProcessBlack; } break; + // if !SPLASH_CMYK: fall through +#endif case psLevel2: case psLevel2Gray: case psLevel2Sep: @@ -4510,7 +4520,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) { } else if ((globalParams->getPSShrinkLarger() && (width * userUnit > imgWidth2 || height * userUnit > imgHeight2)) || - (globalParams->getPSExpandSmaller() && + (expandSmallPages && (width * userUnit < imgWidth2 && height * userUnit < imgHeight2))) { xScale = (double)imgWidth2 / (double)width; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h index 466f81f1992..b7223c6cdd8 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h @@ -264,6 +264,8 @@ public: { rotate0 = rotateA; } void setClip(double llx, double lly, double urx, double ury) { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; } + void setExpandSmallPages(GBool expand) + { expandSmallPages = expand; } void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), void *data) { underlayCbk = cbk; underlayCbkData = data; } @@ -474,6 +476,7 @@ private: int rotate0; // rotation angle (0, 90, 180, 270) double clipLLX0, clipLLY0, clipURX0, clipURY0; + GBool expandSmallPages; // expand smaller pages to fill paper double tx, ty; // global translation for current page double xScale, yScale; // global scaling for current page int rotate; // rotation angle for current page diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc index ace0b33d85c..368bc68dd8a 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc @@ -64,7 +64,7 @@ void PDFRectangle::clipTo(PDFRectangle *rect) { // PageAttrs //------------------------------------------------------------------------ -PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { +PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict, XRef *xref) { Object obj1; // get old/default values @@ -73,7 +73,6 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { cropBox = attrs->cropBox; haveCropBox = attrs->haveCropBox; rotate = attrs->rotate; - attrs->resources.copy(&resources); } else { // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary // but some (non-compliant) PDF files don't specify a MediaBox @@ -84,7 +83,6 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0; haveCropBox = gFalse; rotate = 0; - resources.initNull(); } // media box @@ -137,12 +135,59 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { obj1.free(); // resource dictionary - dict->lookup("Resources", &obj1); - if (obj1.isDict()) { - resources.free(); - obj1.copy(&resources); + Object childResDictObj; + dict->lookup("Resources", &childResDictObj); + if (attrs && attrs->resources.isDict() && childResDictObj.isDict()) { + // merge this node's resources into the parent's resources + // (some PDF files violate the PDF spec and expect this merging) + resources.initDict(xref); + Dict *resDict = resources.getDict(); + Dict *parentResDict = attrs->resources.getDict(); + for (int i = 0; i < parentResDict->getLength(); ++i) { + char *resType = parentResDict->getKey(i); + Object subdictObj1; + if (parentResDict->getVal(i, &subdictObj1)->isDict()) { + Dict *subdict1 = subdictObj1.getDict(); + Object subdictObj2; + subdictObj2.initDict(xref); + Dict *subdict2 = subdictObj2.getDict(); + for (int j = 0; j < subdict1->getLength(); ++j) { + subdict1->getValNF(j, &obj1); + subdict2->add(copyString(subdict1->getKey(j)), &obj1); + } + resDict->add(copyString(resType), &subdictObj2); + } + subdictObj1.free(); + } + Dict *childResDict = childResDictObj.getDict(); + for (int i = 0; i < childResDict->getLength(); ++i) { + char *resType = childResDict->getKey(i); + Object subdictObj1; + if (childResDict->getVal(i, &subdictObj1)->isDict()) { + Object subdictObj2; + if (resDict->lookup(resType, &subdictObj2)->isDict()) { + Dict *subdict1 = subdictObj1.getDict(); + Dict *subdict2 = subdictObj2.getDict(); + for (int j = 0; j < subdict1->getLength(); ++j) { + subdict1->getValNF(j, &obj1); + subdict2->add(copyString(subdict1->getKey(j)), &obj1); + } + subdictObj2.free(); + } else { + subdictObj2.free(); + resDict->add(copyString(resType), subdictObj1.copy(&subdictObj2)); + } + } + subdictObj1.free(); + } + } else if (attrs && attrs->resources.isDict()) { + attrs->resources.copy(&resources); + } else if (childResDictObj.isDict()) { + childResDictObj.copy(&resources); + } else { + resources.initNull(); } - obj1.free(); + childResDictObj.free(); } PageAttrs::PageAttrs() { @@ -160,6 +205,7 @@ PageAttrs::PageAttrs() { metadata.initNull(); pieceInfo.initNull(); separationInfo.initNull(); + userUnit = 1; resources.initNull(); } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h index 8ec5a10995a..fe579e7b3af 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h @@ -46,7 +46,7 @@ public: // Construct a new PageAttrs object by merging a dictionary // (of type Pages or Page) into another PageAttrs object. If // <attrs> is NULL, uses defaults. - PageAttrs(PageAttrs *attrs, Dict *dict); + PageAttrs(PageAttrs *attrs, Dict *dict, XRef *xref); // Construct a new PageAttrs object for an empty page (only used // when there is an error in the page tree). diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc index 87e3fc5e24b..4fad6afae13 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc @@ -152,36 +152,35 @@ Object *Parser::getObj(Object *obj, GBool simpleOnly, Stream *Parser::makeStream(Object *dict, Guchar *fileKey, CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen, int recursion) { - Object obj; - BaseStream *baseStr; - Stream *str, *str2; - GFileOffset pos, endPos, length; - char endstreamBuf[8]; - GBool foundEndstream; - int c, i; - // get stream start position lexer->skipToNextLine(); - if (!(str = lexer->getStream())) { + Stream *curStr = lexer->getStream(); + if (!curStr) { return NULL; } - pos = str->getPos(); + GFileOffset pos = curStr->getPos(); + + GBool haveLength = gFalse; + GFileOffset length = 0; + GFileOffset endPos; // check for length in damaged file if (xref && xref->getStreamEnd(pos, &endPos)) { length = endPos - pos; + haveLength = gTrue; // get length from the stream object } else { + Object obj; dict->dictLookup("Length", &obj, recursion); if (obj.isInt()) { length = (GFileOffset)(Guint)obj.getInt(); - obj.free(); + haveLength = gTrue; } else { - error(errSyntaxError, getPos(), "Bad 'Length' attribute in stream"); - obj.free(); - return NULL; + error(errSyntaxError, getPos(), + "Missing or invalid 'Length' attribute in stream"); } + obj.free(); } // in badly damaged PDF files, we can run off the end of the input @@ -189,47 +188,78 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey, if (!lexer->getStream()) { return NULL; } + // copy the base stream (Lexer will free stream objects when it gets // to end of stream -- which can happen in the shift() calls below) - baseStr = (BaseStream *)lexer->getStream()->getBaseStream()->copy(); + BaseStream *baseStr = + (BaseStream *)lexer->getStream()->getBaseStream()->copy(); + + // 'Length' attribute is missing -- search for 'endstream' + if (!haveLength) { + GBool foundEndstream = gFalse; + char endstreamBuf[8]; + if ((curStr = lexer->getStream())) { + int c; + while ((c = curStr->getChar()) != EOF) { + if (c == 'e' && + curStr->getBlock(endstreamBuf, 8) == 8 && + !memcmp(endstreamBuf, "ndstream", 8)) { + length = curStr->getPos() - 9 - pos; + foundEndstream = gTrue; + break; + } + } + } + if (!foundEndstream) { + error(errSyntaxError, getPos(), "Couldn't find 'endstream' for stream"); + delete baseStr; + return NULL; + } + } // make new base stream - str = baseStr->makeSubStream(pos, gTrue, length, dict); + Stream *str = baseStr->makeSubStream(pos, gTrue, length, dict); - // skip over stream data - lexer->setPos(pos + length); + // look for the 'endstream' marker + if (haveLength) { + // skip over stream data + lexer->setPos(pos + length); - // check for 'endstream' - // NB: we never reuse the Parser object to parse objects after a - // stream, and we could (if the PDF file is damaged) be in the - // middle of binary data at this point, so we check the stream data - // directly for 'endstream', rather than calling shift() to parse - // objects - foundEndstream = gFalse; - if ((str2 = lexer->getStream())) { - // skip up to 100 whitespace chars - for (i = 0; i < 100; ++i) { - c = str2->getChar(); - if (!Lexer::isSpace(c)) { - break; + // check for 'endstream' + // NB: we never reuse the Parser object to parse objects after a + // stream, and we could (if the PDF file is damaged) be in the + // middle of binary data at this point, so we check the stream + // data directly for 'endstream', rather than calling shift() to + // parse objects + GBool foundEndstream = gFalse; + char endstreamBuf[8]; + if ((curStr = lexer->getStream())) { + // skip up to 100 whitespace chars + int c; + for (int i = 0; i < 100; ++i) { + c = curStr->getChar(); + if (!Lexer::isSpace(c)) { + break; + } } - } - if (c == 'e') { - if (str2->getBlock(endstreamBuf, 8) == 8 || - !memcmp(endstreamBuf, "ndstream", 8)) { - foundEndstream = gTrue; + if (c == 'e') { + if (curStr->getBlock(endstreamBuf, 8) == 8 && + !memcmp(endstreamBuf, "ndstream", 8)) { + foundEndstream = gTrue; + } } } - } - if (!foundEndstream) { - error(errSyntaxError, getPos(), "Missing 'endstream'"); - // kludge for broken PDF files: just add 5k to the length, and - // hope it's enough - // (dict is now owned by str, so we need to copy it before deleting str) - dict->copy(&obj); - delete str; - length += 5000; - str = baseStr->makeSubStream(pos, gTrue, length, &obj); + if (!foundEndstream) { + error(errSyntaxError, getPos(), "Missing 'endstream'"); + // kludge for broken PDF files: just add 5k to the length, and + // hope it's enough + // (dict is now owned by str, so we need to copy it before deleting str) + Object obj; + dict->copy(&obj); + delete str; + length += 5000; + str = baseStr->makeSubStream(pos, gTrue, length, &obj); + } } // free the copied base stream @@ -237,8 +267,25 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey, // handle decryption if (fileKey) { - str = new DecryptStream(str, fileKey, encAlgorithm, keyLength, - objNum, objGen); + // the 'Crypt' filter is used to mark unencrypted metadata streams + //~ this should also check for an empty DecodeParams entry + GBool encrypted = gTrue; + Object obj; + dict->dictLookup("Filter", &obj, recursion); + if (obj.isName("Crypt")) { + encrypted = gFalse; + } else if (obj.isArray() && obj.arrayGetLength() >= 1) { + Object obj2; + if (obj.arrayGet(0, &obj2)->isName("Crypt")) { + encrypted = gFalse; + } + obj2.free(); + } + obj.free(); + if (encrypted) { + str = new DecryptStream(str, fileKey, encAlgorithm, keyLength, + objNum, objGen); + } } // get filters diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc index e5e00b85f51..29f26c00cee 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc @@ -248,13 +248,14 @@ void PreScanOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, gdi = gFalse; } -void PreScanOutputDev::beginTransparencyGroup( - GfxState *state, double *bbox, - GfxColorSpace *blendingColorSpace, - GBool isolated, GBool knockout, - GBool forSoftMask) { +GBool PreScanOutputDev::beginTransparencyGroup( + GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { transparency = gTrue; gdi = gFalse; + return gTrue; } void PreScanOutputDev::check(GfxState *state, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h index 253733772bf..ee21e98b148 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h @@ -103,10 +103,10 @@ public: double *matte, GBool interpolate); //----- transparency groups and soft masks - virtual void beginTransparencyGroup(GfxState *state, double *bbox, - GfxColorSpace *blendingColorSpace, - GBool isolated, GBool knockout, - GBool forSoftMask); + virtual GBool beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); //----- special access diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc index 4a7d0954c40..a61a84e8fa2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc @@ -203,18 +203,15 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, fileKeyLength = cfLengthObj.getInt(); } cfLengthObj.free(); - if (fileKeyLength == 16) { - // this isn't allowed by the spec, but Adobe supports it - encVersion = 2; - encRevision = 3; - encAlgorithm = cryptAES; - } else { - encVersion = 5; - if (encRevision != 5 && encRevision != 6) { - encRevision = 6; - } - encAlgorithm = cryptAES256; + encVersion = 5; + if (encRevision != 5 && encRevision != 6) { + encRevision = 6; } + encAlgorithm = cryptAES256; + // The PDF 2.0 spec says Length and CF.Length are both deprecated. + // Acrobat X honors Length and ignores CF.Length. + // I think it's safest to ignore both. + fileKeyLength = 32; } cfmObj.free(); } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc index 89c7c02a7b6..d758e25b306 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc @@ -1882,10 +1882,10 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, idet = 1 / idet; clipXC = 0.5 * (clipXMin + clipXMax); clipYC = 0.5 * (clipYMin + clipYMax); - ix = (int)((yStepX * (tileYMin - clipYC) - (tileXMin - clipXC) * yStepY) - * idet + 0.5); - iy = (int)((xStepX * (clipYC - tileYMin) - (clipXC - tileXMin) * xStepY) - * idet + 0.5); + ix = (int)floor((yStepX * (tileYMin - clipYC) + - (tileXMin - clipXC) * yStepY) * idet + 0.5); + iy = (int)floor((xStepX * (clipYC - tileYMin) + - (clipXC - tileXMin) * xStepY) * idet + 0.5); adjXMin = (int)floor(tileXMin + ix * xStepX + iy * yStepX + 0.5); adjYMin = (int)floor(tileYMin + ix * xStepY + iy * yStepY + 0.5); sx = tileW / (tileXMax - tileXMin); @@ -1896,38 +1896,6 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, yStepY = (int)floor(sy * yStepY + 0.5); } - // compute tile matrix = PTM * BTM * Mtranslate * Mscale * iCTM - // = mat * CTM * Mtranslate * Mscale * iCTM - ctm = state->getCTM(); - idet = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); - ictm[0] = ctm[3] * idet; - ictm[1] = -ctm[1] * idet; - ictm[2] = -ctm[2] * idet; - ictm[3] = ctm[0] * idet; - ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * idet; - ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * idet; - // mat * CTM - mat1[0] = mat[0] * ctm[0] + mat[1] * ctm[2]; - mat1[1] = mat[0] * ctm[1] + mat[1] * ctm[3]; - mat1[2] = mat[2] * ctm[0] + mat[3] * ctm[2]; - mat1[3] = mat[2] * ctm[1] + mat[3] * ctm[3]; - mat1[4] = mat[4] * ctm[0] + mat[5] * ctm[2] + ctm[4]; - mat1[5] = mat[4] * ctm[1] + mat[5] * ctm[3] + ctm[5]; - // mat * CTM * (Mtranslate * Mscale) - mat2[0] = mat1[0] * sx; - mat2[1] = mat1[1] * sy; - mat2[2] = mat1[2] * sx; - mat2[3] = mat1[3] * sy; - mat2[4] = mat1[4] * sx - sx * tileXMin; - mat2[5] = mat1[5] * sy - sy * tileYMin; - // mat * CTM * (Mtranslate * Mscale) * iCTM - tileMat[0] = mat2[0] * ictm[0] + mat2[1] * ictm[2]; - tileMat[1] = mat2[0] * ictm[1] + mat2[1] * ictm[3]; - tileMat[2] = mat2[2] * ictm[0] + mat2[3] * ictm[2]; - tileMat[3] = mat2[2] * ictm[1] + mat2[3] * ictm[3]; - tileMat[4] = mat2[4] * ictm[0] + mat2[5] * ictm[2] + ictm[4]; - tileMat[5] = mat2[4] * ictm[1] + mat2[5] * ictm[3] + ictm[5]; - // compute tiling range: // - look at the four corners of the clipping bbox // - solve for the (ix,iy) tile position at each corner @@ -1989,10 +1957,65 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, } else if (ty > tyMax) { tyMax = ty; } - ixMin = (int)floor(txMin); - ixMax = (int)ceil(txMax); - iyMin = (int)floor(tyMin); - iyMax = (int)ceil(tyMax); + ixMin = (int)ceil(txMin); + ixMax = (int)floor(txMax) + 1; + iyMin = (int)ceil(tyMin); + iyMax = (int)floor(tyMax) + 1; + + // special case: pattern tile is larger than clipping bbox + if (ixMax - ixMin == 1 && iyMax - iyMin == 1) { + // reduce the tile size to just the clipping bbox -- this improves + // performance in cases where just a small portion of one tile is + // needed + tileW = (int)(clipXMax - clipXMin + 0.5); + tileH = (int)(clipYMax - clipYMin + 0.5); + if (tileW < 1) { + tileW = 1; + } + if (tileH < 1) { + tileH = 1; + } + tileXMin += clipXMin - (adjXMin + ixMin * xStepX + iyMin * yStepX); + tileYMin += clipYMin - (adjYMin + ixMin * xStepY + iyMin * yStepY); + ixMin = 0; + iyMin = 0; + ixMax = 1; + iyMax = 1; + adjXMin = clipXMin; + adjYMin = clipYMin; + } + + // compute tile matrix = PTM * BTM * Mtranslate * Mscale * iCTM + // = mat * CTM * Mtranslate * Mscale * iCTM + ctm = state->getCTM(); + idet = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * idet; + ictm[1] = -ctm[1] * idet; + ictm[2] = -ctm[2] * idet; + ictm[3] = ctm[0] * idet; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * idet; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * idet; + // mat * CTM + mat1[0] = mat[0] * ctm[0] + mat[1] * ctm[2]; + mat1[1] = mat[0] * ctm[1] + mat[1] * ctm[3]; + mat1[2] = mat[2] * ctm[0] + mat[3] * ctm[2]; + mat1[3] = mat[2] * ctm[1] + mat[3] * ctm[3]; + mat1[4] = mat[4] * ctm[0] + mat[5] * ctm[2] + ctm[4]; + mat1[5] = mat[4] * ctm[1] + mat[5] * ctm[3] + ctm[5]; + // mat * CTM * (Mtranslate * Mscale) + mat2[0] = mat1[0] * sx; + mat2[1] = mat1[1] * sy; + mat2[2] = mat1[2] * sx; + mat2[3] = mat1[3] * sy; + mat2[4] = mat1[4] * sx - sx * tileXMin; + mat2[5] = mat1[5] * sy - sy * tileYMin; + // mat * CTM * (Mtranslate * Mscale) * iCTM + tileMat[0] = mat2[0] * ictm[0] + mat2[1] * ictm[2]; + tileMat[1] = mat2[0] * ictm[1] + mat2[1] * ictm[3]; + tileMat[2] = mat2[2] * ictm[0] + mat2[3] * ictm[2]; + tileMat[3] = mat2[2] * ictm[1] + mat2[3] * ictm[3]; + tileMat[4] = mat2[4] * ictm[0] + mat2[5] * ictm[2] + ictm[4]; + tileMat[5] = mat2[4] * ictm[1] + mat2[5] * ictm[3] + ictm[5]; // create a temporary bitmap origBitmap = bitmap; @@ -2068,8 +2091,8 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, } else { for (iy = iyMin; iy < iyMax; ++iy) { for (ix = ixMin; ix < ixMax; ++ix) { - x = (int)(adjXMin + ix * xStepX + iy * yStepX + 0.5); - y = (int)(adjYMin + ix * xStepY + iy * yStepY + 0.5); + x = (int)floor(adjXMin + ix * xStepX + iy * yStepX + 0.5); + y = (int)floor(adjYMin + ix * xStepY + iy * yStepY + 0.5); if (overprintMaskBitmap) { splash->compositeWithOverprint(tileBitmap, overprintMaskBitmap, 0, 0, x, y, tileW, tileH, @@ -2722,7 +2745,8 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, imgTag = makeImageTag(ref, gfxRenderingIntentRelativeColorimetric, NULL); splash->fillImageMask(imgTag, &imageMaskSrc, &imgMaskData, width, height, mat, - t3GlyphStack != NULL, interpolate); + t3GlyphStack != NULL, interpolate, + globalParams->getImageMaskAntialias()); if (inlineImg) { while (imgMaskData.y < height) { @@ -2772,12 +2796,16 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state, mapStrokeAdjustMode[globalParams->getStrokeAdjust()]); maskSplash->setEnablePathSimplification( globalParams->getEnablePathSimplification()); + if (splash->getSoftMask()) { + maskSplash->setSoftMask(splash->getSoftMask(), gFalse); + } clearMaskRegion(state, maskSplash, 0, 0, 1, 1); maskColor[0] = 0xff; maskSplash->setFillPattern(new SplashSolidColor(maskColor)); imgTag = makeImageTag(ref, gfxRenderingIntentRelativeColorimetric, NULL); maskSplash->fillImageMask(imgTag, &imageMaskSrc, &imgMaskData, - width, height, mat, gFalse, interpolate); + width, height, mat, gFalse, interpolate, + globalParams->getImageMaskAntialias()); delete imgTag; delete imgMaskData.imgStr; str->close(); @@ -3273,7 +3301,8 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, maskSplash->setFillPattern(new SplashSolidColor(maskColor)); // use "glyph mode" here to get the correct scaled size maskSplash->fillImageMask(NULL, &imageMaskSrc, &imgMaskData, - maskWidth, maskHeight, mat, gTrue, interpolate); + maskWidth, maskHeight, mat, gTrue, interpolate, + globalParams->getImageMaskAntialias()); delete imgMaskData.imgStr; maskStr->close(); delete maskSplash; @@ -3818,10 +3847,10 @@ void SplashOutputDev::clearMaskRegion(GfxState *state, } } -void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, - GfxColorSpace *blendingColorSpace, - GBool isolated, GBool knockout, - GBool forSoftMask) { +GBool SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { SplashTransparencyGroup *transpGroup; SplashBitmap *backdropBitmap; SplashColor color; @@ -3916,6 +3945,28 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, h = 1; } + // optimization: a non-isolated group drawn with alpha=1 and + // Blend=Normal and backdrop alpha=0 is equivalent to drawing + // directly onto the backdrop (i.e., a regular non-t-group Form) + // notes: + // - if we are already in a non-isolated group, it means the + // backdrop alpha is non-zero (otherwise the parent non-isolated + // group would have been optimized away) + // - if there is a soft mask in place, then source alpha is not 1 + // (i.e., source alpha = fillOpacity * softMask) + // - both the parent and child groups must be non-knockout + if (!isolated && + !splash->getInNonIsolatedGroup() && + !knockout && + !splash->getInKnockoutGroup() && + !forSoftMask && + !splash->getSoftMask() && + state->getFillOpacity() == 1 && + state->getBlendMode() == gfxBlendNormal && + splash->checkTransparentRect(tx, ty, w, h)) { + return gFalse; + } + // push a new stack entry transpGroup = new SplashTransparencyGroup(); transpGroup->tx = tx; @@ -4042,6 +4093,8 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, state->shiftCTM(-tx, -ty); updateCTM(state, 0, 0, 0, 0, 0, 0); ++nestCount; + + return gTrue; } void SplashOutputDev::endTransparencyGroup(GfxState *state) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h index cbe47b61cb7..5ec70e95509 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h @@ -167,10 +167,10 @@ public: double llx, double lly, double urx, double ury); //----- transparency groups and soft masks - virtual void beginTransparencyGroup(GfxState *state, double *bbox, - GfxColorSpace *blendingColorSpace, - GBool isolated, GBool knockout, - GBool forSoftMask); + virtual GBool beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); virtual void endTransparencyGroup(GfxState *state); virtual void paintTransparencyGroup(GfxState *state, double *bbox); virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc index 601add89be4..383ac5478ff 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc @@ -52,6 +52,14 @@ static GBool setDJSYSFLAGS = gFalse; #endif //------------------------------------------------------------------------ + +// An LZW/Flate decompression bomb is detected if the output size +// exceeds decompressionBombSizeThreshold and the decompression ratio +// exceeds decompressionBombRatioThreshold. +#define decompressionBombSizeThreshold 50000000 +#define decompressionBombRatioThreshold 200 + +//------------------------------------------------------------------------ // Stream (base class) //------------------------------------------------------------------------ @@ -148,7 +156,7 @@ Stream *Stream::addFilters(Object *dict, int recursion) { } else if (obj.isArray()) { for (i = 0; i < obj.arrayGetLength(); ++i) { obj.arrayGet(i, &obj2, recursion); - if (params.isArray()) + if (params.isArray() && i < params.arrayGetLength()) params.arrayGet(i, ¶ms2, recursion); else params2.initNull(); @@ -305,6 +313,8 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, globals.free(); } else if (!strcmp(name, "JPXDecode")) { str = new JPXStream(str); + } else if (!strcmp(name, "Crypt")) { + // this is handled in Parser::makeStream() } else { error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name); str = new EOFStream(str); @@ -384,6 +394,7 @@ ImageStream::~ImageStream() { } void ImageStream::reset() { + str->disableDecompressionBombChecking(); str->reset(); } @@ -935,7 +946,11 @@ void MemStream::setPos(GFileOffset pos, int dir) { if (dir >= 0) { i = (Guint)pos; } else { - i = (Guint)(start + length - pos); + if (pos > start + length) { + i = 0; + } else { + i = (Guint)(start + length - pos); + } } if (i < start) { i = start; @@ -1221,6 +1236,7 @@ LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors, eof = gFalse; inputBits = 0; clearTable(); + checkForDecompressionBombs = gTrue; } LZWStream::~LZWStream() { @@ -1240,6 +1256,11 @@ Stream *LZWStream::copy() { } } +void LZWStream::disableDecompressionBombChecking() { + checkForDecompressionBombs = gFalse; + FilterStream::disableDecompressionBombChecking(); +} + int LZWStream::getChar() { if (pred) { return pred->getChar(); @@ -1386,8 +1407,10 @@ GBool LZWStream::processNextCode() { totalOut += seqLength; // check for a 'decompression bomb' - if (totalOut > 50000000 && totalIn < totalOut / 250) { - error(errSyntaxError, getPos(), "Decompression bomb in flate stream"); + if (checkForDecompressionBombs && + totalOut > decompressionBombSizeThreshold && + totalIn < totalOut / decompressionBombRatioThreshold) { + error(errSyntaxError, getPos(), "Decompression bomb in LZW stream"); eof = gTrue; return gFalse; } @@ -2638,6 +2661,7 @@ DCTStream::DCTStream(Stream *strA, GBool colorXformA): FilterStream(strA) { int i; + prepared = gFalse; colorXform = colorXformA; progressive = interleaved = gFalse; width = height = 0; @@ -2683,6 +2707,7 @@ void DCTStream::reset() { // force an EOF condition progressive = gTrue; y = height; + prepared = gTrue; return; } @@ -2719,56 +2744,7 @@ void DCTStream::reset() { } } - if (progressive || !interleaved) { - - // allocate a buffer for the whole image - bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; - if (bufWidth <= 0 || bufHeight <= 0 || - bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { - error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); - y = height; - return; - } - for (i = 0; i < numComps; ++i) { - frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); - memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); - } - - // read the image data - do { - restartMarker = 0xd0; - restart(); - readScan(); - } while (readHeader(gFalse)); - - // decode - decodeImage(); - - // initialize counters - comp = 0; - x = 0; - y = 0; - - } else { - - if (scanInfo.numComps != numComps) { - error(errSyntaxError, getPos(), "Invalid scan in sequential DCT stream"); - y = height; - return; - } - - // allocate a buffer for one row of MCUs - bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); - rowBufPtr = rowBufEnd = rowBuf; - - // initialize counters - y = -mcuHeight; - - restartMarker = 0xd0; - restart(); - } + prepared = gFalse; } GBool DCTStream::checkSequentialInterleaved() { @@ -2808,6 +2784,9 @@ void DCTStream::close() { int DCTStream::getChar() { int c; + if (!prepared) { + prepare(); + } if (progressive || !interleaved) { if (y >= height) { return EOF; @@ -2837,6 +2816,9 @@ int DCTStream::getChar() { } int DCTStream::lookChar() { + if (!prepared) { + prepare(); + } if (progressive || !interleaved) { if (y >= height) { return EOF; @@ -2859,6 +2841,9 @@ int DCTStream::lookChar() { int DCTStream::getBlock(char *blk, int size) { int nRead, nAvail, n; + if (!prepared) { + prepare(); + } if (progressive || !interleaved) { if (y >= height) { return 0; @@ -2900,6 +2885,76 @@ int DCTStream::getBlock(char *blk, int size) { return nRead; } +void DCTStream::prepare() { + int i; + + if (progressive || !interleaved) { + + // allocate a buffer for the whole image + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; + if (bufWidth <= 0 || bufHeight <= 0 || + bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { + error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); + y = height; + prepared = gTrue; + return; + } +#if USE_EXCEPTIONS + try { +#endif + for (i = 0; i < numComps; ++i) { + frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); + memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); + } +#if USE_EXCEPTIONS + } catch (GMemException) { + error(errSyntaxError, getPos(), "Out of memory in DCT stream"); + y = height; + prepared = gTrue; + return; + } +#endif + + // read the image data + do { + restartMarker = 0xd0; + restart(); + readScan(); + } while (readHeader(gFalse)); + + // decode + decodeImage(); + + // initialize counters + comp = 0; + x = 0; + y = 0; + + } else { + + if (scanInfo.numComps != numComps) { + error(errSyntaxError, getPos(), "Invalid scan in sequential DCT stream"); + y = height; + prepared = gTrue; + return; + } + + // allocate a buffer for one row of MCUs + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); + rowBufPtr = rowBufEnd = rowBuf; + + // initialize counters + y = -mcuHeight; + + restartMarker = 0xd0; + restart(); + } + + prepared = gTrue; +} + void DCTStream::restart() { int i; @@ -3841,6 +3896,9 @@ GBool DCTStream::readHeader(GBool frame) { if (!readScanInfo()) { return gFalse; } + if (frame) { + interleaved = scanInfo.numComps == numComps; + } doScan = gTrue; break; case 0xdb: // DQT @@ -4006,7 +4064,6 @@ GBool DCTStream::readScanInfo() { error(errSyntaxError, getPos(), "Bad DCT scan info block"); return gFalse; } - interleaved = scanInfo.numComps == numComps; for (j = 0; j < numComps; ++j) { scanInfo.comp[j] = gFalse; } @@ -4911,6 +4968,7 @@ FlateStream::FlateStream(Stream *strA, int predictor, int columns, litCodeTab.codes = NULL; distCodeTab.codes = NULL; memset(buf, 0, flateWindow); + checkForDecompressionBombs = gTrue; } FlateStream::~FlateStream() { @@ -4936,6 +4994,11 @@ Stream *FlateStream::copy() { } } +void FlateStream::disableDecompressionBombChecking() { + checkForDecompressionBombs = gFalse; + FilterStream::disableDecompressionBombChecking(); +} + void FlateStream::reset() { int cmf, flg; @@ -5198,7 +5261,9 @@ void FlateStream::readSome() { totalOut += remain; // check for a 'decompression bomb' - if (totalOut > 50000000 && totalIn < totalOut / 250) { + if (checkForDecompressionBombs && + totalOut > decompressionBombSizeThreshold && + totalIn < totalOut / decompressionBombRatioThreshold) { error(errSyntaxError, getPos(), "Decompression bomb in flate stream"); endOfBlock = eof = gTrue; remain = 0; @@ -5249,8 +5314,7 @@ GBool FlateStream::startBlock() { goto err; check |= (c & 0xff) << 8; if (check != (~blockLen & 0xffff)) - error(errSyntaxError, getPos(), - "Bad uncompressed block length in flate stream"); + goto err; codeBuf = 0; codeSize = 0; totalIn += 4; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h index 59cafadc14f..9d084c94895 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h @@ -80,6 +80,13 @@ public: virtual GBool isEmbedStream() { return gFalse; } + // Disable checking for 'decompression bombs', i.e., cases where the + // encryption ratio looks suspiciously high. This should be called + // for things like images which (a) can have very high compression + // ratios in certain cases, and (b) have fixed data sizes controlled + // by the reader. + virtual void disableDecompressionBombChecking() {} + // Reset stream to beginning. virtual void reset() = 0; @@ -192,6 +199,8 @@ public: FilterStream(Stream *strA); virtual ~FilterStream(); + virtual void disableDecompressionBombChecking() + { str->disableDecompressionBombChecking(); } virtual void close(); virtual GFileOffset getPos() { return str->getPos(); } virtual void setPos(GFileOffset pos, int dir = 0); @@ -472,6 +481,7 @@ public: virtual ~LZWStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strLZW; } + virtual void disableDecompressionBombChecking(); virtual void reset(); virtual int getChar(); virtual int lookChar(); @@ -501,6 +511,7 @@ private: int seqLength; // length of current sequence int seqIndex; // index into current sequence GBool first; // first code after a table clear + GBool checkForDecompressionBombs; unsigned long long totalIn; // total number of encoded bytes read so far unsigned long long totalOut; // total number of bytes decoded so far @@ -693,6 +704,7 @@ private: #else // HAVE_JPEGLIB + GBool prepared; // set after prepare() is called GBool progressive; // set if in progressive mode GBool interleaved; // set if in interleaved mode int width, height; // image size @@ -724,6 +736,7 @@ private: int inputBuf; // input buffer for variable length codes int inputBits; // number of valid bits in input buffer + void prepare(); void restart(); GBool readMCURow(); void readScan(); @@ -791,6 +804,7 @@ public: virtual ~FlateStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strFlate; } + virtual void disableDecompressionBombChecking(); virtual void reset(); virtual int getChar(); virtual int lookChar(); @@ -816,6 +830,7 @@ private: int blockLen; // remaining length of uncompressed block GBool endOfBlock; // set when end of block is reached GBool eof; // set when end of stream is reached + GBool checkForDecompressionBombs; unsigned long long totalIn; // total number of encoded bytes read so far unsigned long long totalOut; // total number of bytes decoded so far diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc index 9ec906c7379..e2da940bb41 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc @@ -58,27 +58,42 @@ // considered to be equivalent. #define splitGapSlack 0.2 -// The vertical gap threshold (minimum gap required to split -// vertically) depends on the (approximate) number of lines in the -// block: -// threshold = (max + slope * nLines) * avgFontSize -// with a min value of vertGapThresholdMin * avgFontSize. -#define vertGapThresholdMin 0.8 -#define vertGapThresholdMax 3 -#define vertGapThresholdSlope -0.5 - -// Vertical gap threshold for table mode. -#define vertGapThresholdTableMin 0.2 -#define vertGapThresholdTableMax 0.5 -#define vertGapThresholdTableSlope -0.02 +// Gap area (width * height) must be larger than this to allow a +// vertical split (or horizontal split if rot=1,3). +#define minGapArea 3 +#define minTableGapArea 1.5 // A large character has a font size larger than // largeCharThreshold * avgFontSize. #define largeCharThreshold 1.5 -// A block will be split vertically only if the resulting chunk -// widths are greater than vertSplitChunkThreshold * avgFontSize. -#define vertSplitChunkThreshold 2 +// A block will be split vertically only if the resulting chunk widths +// are greater than minChunkWidth * avgFontSize. However, Blocks of +// height less than maxSingleLineHeight * avgFontSize are not subject +// to this minimum chunk width criterion. +#define minChunkWidth 2 +#define maxSingleLineHeight 1.5 + +// Minimum vertical gap is minGapSize * minFontSize. +// (horizontal gap for rot=1,3) +#define minGapSize 0.2 + +// Maximum vertical gap for a "small" split is maxWordGapSize * +// avgFontSize. +#define maxWordGapSize 2.5 +#define tableModeMaxWordGapSize 1.1 + +// Adjacent lines can overlap by at most lineOverlapThreshold * +// lineHeight. +#define lineOverlapThreshold 0.33 + +// Subscripts (superscripts) must overlap the next (previous) line by +// minSubSuperscriptVertOverlap * fontSize. +#define minSubSuperscriptVertOverlap 0.25 + +// Subscripts (superscripts) may horizontally overlap adjacent +// characters by up to maxSubSuperscriptHorizOverlap * fontSize. +#define maxSubSuperscriptHorizOverlap 0.05 // Max difference in primary,secondary coordinates (as a fraction of // the font size) allowed for duplicated text (fake boldface, drop @@ -257,6 +272,16 @@ TextChar::TextChar(Unicode cA, int charPosA, int charLenA, if (yMax > 1e8) { yMax = 1e8; } + // zero-width characters will cause problems in the splitting code + if (rotA & 1) { + if (yMax - yMin < 1e-6) { + yMax = yMin + 1e-6; + } + } else { + if (xMax - xMin < 1e-6) { + xMax = xMin + 1e-6; + } + } rot = (Guchar)rotA; rotated = (char)rotatedA; clipped = (char)clippedA; @@ -527,6 +552,35 @@ void TextGaps::addGap(double x, double w) { } //------------------------------------------------------------------------ +// SplitLine +//------------------------------------------------------------------------ + +class SplitLine { +public: + + SplitLine(int firstCharIdxA, int lastCharIdxA, + double yMinA, double yMaxA); + ~SplitLine(); + + int firstCharIdx, lastCharIdx; + double yMin, yMax; // xMin, xMax if rot = {1,3} + GList *chars; // [TextChar] +}; + +SplitLine::SplitLine(int firstCharIdxA, int lastCharIdxA, + double yMinA, double yMaxA) { + firstCharIdx = firstCharIdxA; + lastCharIdx = lastCharIdxA; + yMin = yMinA; + yMax = yMaxA; + chars = NULL; +} + +SplitLine::~SplitLine() { + delete chars; +} + +//------------------------------------------------------------------------ // TextSuperLine //------------------------------------------------------------------------ @@ -671,6 +725,16 @@ TextFontInfo::TextFontInfo(GfxState *state) { } } +TextFontInfo::TextFontInfo() { + fontID.num = -1; + fontID.gen = -1; + fontName = NULL; + flags = 0; + mWidth = 0; + ascent = 0; + descent = 0; +} + TextFontInfo::~TextFontInfo() { if (fontName) { delete fontName; @@ -1388,11 +1452,13 @@ void TextPage::addChar(GfxState *state, double x, double y, } } - // skip space, tab, and non-breaking space characters + // skip various whitespace characters // (ActualText spans can result in multiple space chars) for (i = 0; i < uLen; ++i) { if (u[i] != (Unicode)0x20 && u[i] != (Unicode)0x09 && + u[i] != (Unicode)0x0a && + u[i] != (Unicode)0x0d && u[i] != (Unicode)0xa0) { break; } @@ -1507,6 +1573,36 @@ void TextPage::addChar(GfxState *state, double x, double y, charPos += nBytes; } +void TextPage::addSpecialChar(double xMin, double yMin, + double xMax, double yMax, + int rot, TextFontInfo *font, double fontSize, + Unicode u) { + chars->append(new TextChar(u, 0, 0, xMin, yMin, xMax, yMax, rot, + gFalse, gFalse, gFalse, font, fontSize, 0, 0, 0)); +} + +//~ this is inefficient -- consider using some sort of tree +//~ structure to store the chars (?) +void TextPage::removeChars(double xMin, double yMin, + double xMax, double yMax, + double xOverlapThresh, double yOverlapThresh) { + int i = 0; + while (i < chars->getLength()) { + TextChar *ch = (TextChar *)chars->get(i); + double xOverlap = (ch->xMax < xMax ? ch->xMax : xMax) + - (ch->xMin > xMin ? ch->xMin : xMin); + double yOverlap = (ch->yMax < yMax ? ch->yMax : yMax) + - (ch->yMin > yMin ? ch->yMin : yMin); + if (xOverlap > xOverlapThresh * (ch->xMax - ch->xMin) && + yOverlap > yOverlapThresh * (ch->yMax - ch->yMin)) { + chars->del(i); + delete ch; + } else { + ++i; + } + } +} + void TextPage::incCharCount(int nChars) { charPos += nChars; } @@ -2181,6 +2277,8 @@ void TextPage::writeRaw(void *outputStream, void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, GBool primaryLR, GString *s) { char lre[8], rle[8], popdf[8], buf[8]; + GBool open; + Unicode opposite; int lreLen, rleLen, popdfLen, n; int i, j, k; @@ -2195,7 +2293,11 @@ void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, i = 0; while (i < len) { // output a left-to-right section - for (j = i; j < len && !unicodeTypeR(text[j]); ++j) ; + for (j = i; + j < len && !unicodeEffectiveTypeR(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); + ++j) ; for (k = i; k < j; ++k) { n = uMap->mapUnicode(text[k], buf, sizeof(buf)); s->append(buf, n); @@ -2203,12 +2305,18 @@ void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, i = j; // output a right-to-left section for (j = i; - j < len && !(unicodeTypeL(text[j]) || unicodeTypeNum(text[j])); + j < len && !unicodeEffectiveTypeLOrNum(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); ++j) ; if (j > i) { s->append(rle, rleLen); for (k = j - 1; k >= i; --k) { - n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + if (unicodeBracketInfo(text[k], &open, &opposite)) { + n = uMap->mapUnicode(opposite, buf, sizeof(buf)); + } else { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + } s->append(buf, n); } s->append(popdf, popdfLen); @@ -2216,26 +2324,32 @@ void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, } } - } else { + } else { // !primaryLR - // Note: This code treats numeric characters (European and - // Arabic/Indic) as left-to-right, which isn't strictly correct - // (incurs extra LRE/POPDF pairs), but does produce correct - // visual formatting. s->append(rle, rleLen); i = len - 1; while (i >= 0) { // output a right-to-left section for (j = i; - j >= 0 && !(unicodeTypeL(text[j]) || unicodeTypeNum(text[j])); + j >= 0 && !unicodeEffectiveTypeLOrNum(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); --j) ; for (k = i; k > j; --k) { - n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + if (unicodeBracketInfo(text[k], &open, &opposite)) { + n = uMap->mapUnicode(opposite, buf, sizeof(buf)); + } else { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + } s->append(buf, n); } i = j; // output a left-to-right section - for (j = i; j >= 0 && !unicodeTypeR(text[j]); --j) ; + for (j = i; + j >= 0 && !unicodeEffectiveTypeR(text[j], + j > 0 ? text[j-1] : 0, + j < len-1 ? text[j+1] : 0); + --j) ; if (j < i) { s->append(lre, lreLen); for (k = j + 1; k <= i; ++k) { @@ -2257,6 +2371,45 @@ void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, } } +// Returns true if [u] is LTR, in the context of [left]-[u]-[right]. +// NB: returns false if [u] is neutral. +GBool TextPage::unicodeEffectiveTypeLOrNum(Unicode u, Unicode left, + Unicode right) { + GBool open; + Unicode opposite; + if (unicodeBracketInfo(u, &open, &opposite)) { + // bracket takes the direction of the first char inside the bracket + if (open) { + return unicodeTypeL(right) || unicodeTypeNum(right); + } else { + return unicodeTypeL(left) || unicodeTypeNum(left); + } + } else if (unicodeTypeNumSep(u)) { + // numeric separator is numeric if either side is a digit; neutral + // otherwise + return unicodeTypeDigit(left) || unicodeTypeDigit(right); + } else { + return unicodeTypeL(u) || unicodeTypeDigit(u); + } +} + +// Returns true if [u] is RTL, in the context of [left]-[u]-[right]. +// NB: returns false if [u] is neutral. +GBool TextPage::unicodeEffectiveTypeR(Unicode u, Unicode left, Unicode right) { + GBool open; + Unicode opposite; + if (unicodeBracketInfo(u, &open, &opposite)) { + // bracket takes the direction of the first char inside the bracket + if (open) { + return unicodeTypeR(right); + } else { + return unicodeTypeR(left); + } + } else { + return unicodeTypeR(u); + } +} + //------------------------------------------------------------------------ // TextPage: layout analysis //------------------------------------------------------------------------ @@ -3406,7 +3559,7 @@ TextBlock *TextPage::splitChars(GList *charsA) { } } if (chars2->getLength() > 0) { - tree[rot] = split(chars2, rot); + tree[rot] = split(chars2, rot, gFalse); } } delete chars2; @@ -3457,26 +3610,29 @@ TextBlock *TextPage::splitChars(GList *charsA) { } // Generate a tree of TextBlocks, marked as columns, lines, and words. -TextBlock *TextPage::split(GList *charsA, int rot) { +TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { TextBlock *blk; GList *chars2, *chars3; + GList *splitLines; TextGaps *horizGaps, *vertGaps; TextChar *ch; - double xMin, yMin, xMax, yMax, avgFontSize; + double xMin, yMin, xMax, yMax, avgFontSize, minFontSize; double horizGapSize, vertGapSize, minHorizChunkWidth, minVertChunkWidth; - double gap, nLines, vertGapThreshold, minChunk; + double gap, gapThreshold, smallSplitThreshold, blockHeight, minChunk; double largeCharSize; double x0, x1, y0, y1; int nHorizGaps, nVertGaps, nLargeChars; int i; - GBool doHorizSplit, doVertSplit, smallSplit; + GBool singleLine; + GBool doHorizSplit, doVertSplit, doLineSplit, doLargeCharSplit, smallSplit; //----- find all horizontal and vertical gaps horizGaps = new TextGaps(); vertGaps = new TextGaps(); - findGaps(charsA, rot, &xMin, &yMin, &xMax, &yMax, &avgFontSize, - horizGaps, vertGaps); + splitLines = new GList(); + findGaps(charsA, rot, &xMin, &yMin, &xMax, &yMax, &avgFontSize, &minFontSize, + splitLines, horizGaps, vertGaps); //----- find the largest horizontal and vertical gaps @@ -3540,38 +3696,48 @@ TextBlock *TextPage::split(GList *charsA, int rot) { //----- compute splitting parameters - // approximation of number of lines in block - if (fabs(avgFontSize) < 0.001) { - nLines = 1; - } else if (rot & 1) { - nLines = (xMax - xMin) / avgFontSize; - } else { - nLines = (yMax - yMin) / avgFontSize; - } + // compute block height; check for single line + blockHeight = (rot & 1) ? xMax - xMin : yMax - yMin; + singleLine = blockHeight < maxSingleLineHeight * avgFontSize && + splitLines->getLength() == 1; // compute the minimum allowed vertical gap size // (this is a horizontal gap threshold for rot=1,3 if (control.mode == textOutTableLayout) { - vertGapThreshold = vertGapThresholdTableMax - + vertGapThresholdTableSlope * nLines; - if (vertGapThreshold < vertGapThresholdTableMin) { - vertGapThreshold = vertGapThresholdTableMin; + if (rot & 1) { + gapThreshold = (minTableGapArea * avgFontSize * avgFontSize) + / (xMax - xMin); + } else { + gapThreshold = (minTableGapArea * avgFontSize * avgFontSize) + / (yMax - yMin); + } + if (minGapSize * avgFontSize > gapThreshold) { + gapThreshold = minGapSize * avgFontSize; } - } else if (control.mode == textOutSimpleLayout) { - vertGapThreshold = simpleLayoutGapThreshold; + smallSplitThreshold = tableModeMaxWordGapSize * avgFontSize; } else { - vertGapThreshold = vertGapThresholdMax + vertGapThresholdSlope * nLines; - if (vertGapThreshold < vertGapThresholdMin) { - vertGapThreshold = vertGapThresholdMin; + if (rot & 1) { + gapThreshold = (minGapArea * avgFontSize * avgFontSize) / (xMax - xMin); + if (vertGapSize > gapThreshold) { + gapThreshold = vertGapSize; + } + } else { + gapThreshold = (minGapArea * avgFontSize * avgFontSize) / (yMax - yMin); + if (horizGapSize > gapThreshold) { + gapThreshold = horizGapSize; + } + } + if (minGapSize * avgFontSize > gapThreshold) { + gapThreshold = minGapSize * avgFontSize; } + smallSplitThreshold = maxWordGapSize * avgFontSize; } - vertGapThreshold = vertGapThreshold * avgFontSize; - // compute the minimum allowed chunk width - if (control.mode == textOutTableLayout) { + if (control.mode == textOutTableLayout || + singleLine) { minChunk = 0; } else { - minChunk = vertSplitChunkThreshold * avgFontSize; + minChunk = minChunkWidth * avgFontSize; } // look for large chars @@ -3593,49 +3759,68 @@ TextBlock *TextPage::split(GList *charsA, int rot) { } // figure out which type of split to do - doHorizSplit = doVertSplit = gFalse; + doHorizSplit = doVertSplit = doLineSplit = doLargeCharSplit = gFalse; smallSplit = gFalse; if (rot & 1) { - if (control.mode == textOutSimpleLayout) { + if (vertOnly) { + if (nHorizGaps > 0 && horizGapSize > minGapSize * minFontSize) { + doHorizSplit = gTrue; + smallSplit = horizGapSize < smallSplitThreshold; + } + } else if (control.mode == textOutSimpleLayout) { if (nVertGaps > 0) { doVertSplit = gTrue; - } else if (nHorizGaps > 0) { + } else if (nHorizGaps > 0 && horizGapSize > minGapSize * minFontSize) { doHorizSplit = gTrue; - smallSplit = horizGapSize <= vertGapThreshold; + smallSplit = horizGapSize < smallSplitThreshold; + } else if (!vertOnly && splitLines->getLength() > 1) { + doLineSplit = gTrue; } } else if (nHorizGaps > 0 && - (horizGapSize > vertGapSize || - control.mode == textOutTableLayout) && - horizGapSize > vertGapThreshold && - (minHorizChunkWidth > minChunk || - nVertGaps == 0)) { + ((horizGapSize > minGapSize * minFontSize && + nVertGaps == 0 && + splitLines->getLength() <= 1) || + (horizGapSize > gapThreshold && + minHorizChunkWidth > minChunk))) { doHorizSplit = gTrue; + smallSplit = horizGapSize < smallSplitThreshold; } else if (nVertGaps > 0) { doVertSplit = gTrue; - } else if (nLargeChars == 0 && nHorizGaps > 0) { - doHorizSplit = gTrue; - smallSplit = gTrue; + } else if (nLargeChars > 0) { + doLargeCharSplit = gTrue; + } else if (splitLines->getLength() > 1) { + doLineSplit = gTrue; } } else { - if (control.mode == textOutSimpleLayout) { + if (vertOnly) { + if (nVertGaps > 0 && + vertGapSize > minGapSize * minFontSize) { + doVertSplit = gTrue; + smallSplit = vertGapSize < smallSplitThreshold; + } + } else if (control.mode == textOutSimpleLayout) { if (nHorizGaps > 0) { doHorizSplit = gTrue; - } else if (nVertGaps > 0) { + } else if (nVertGaps > 0 && vertGapSize > minGapSize * minFontSize) { doVertSplit = gTrue; - smallSplit = vertGapSize <= vertGapThreshold; + smallSplit = vertGapSize < smallSplitThreshold; + } else if (splitLines->getLength() > 1) { + doLineSplit = gTrue; } } else if (nVertGaps > 0 && - (vertGapSize > horizGapSize || - control.mode == textOutTableLayout) && - vertGapSize > vertGapThreshold && - (minVertChunkWidth > minChunk || - nHorizGaps == 0)) { + ((vertGapSize > minGapSize * minFontSize && + nHorizGaps == 0 && + splitLines->getLength() <= 1) || + (vertGapSize > gapThreshold && + minVertChunkWidth > minChunk))) { doVertSplit = gTrue; + smallSplit = vertGapSize < smallSplitThreshold; } else if (nHorizGaps > 0) { doHorizSplit = gTrue; - } else if (nLargeChars == 0 && nVertGaps > 0) { - doVertSplit = gTrue; - smallSplit = gTrue; + } else if (nLargeChars > 0) { + doLargeCharSplit = gTrue; + } else if (splitLines->getLength() > 1) { + doLineSplit = gTrue; } } @@ -3662,13 +3847,13 @@ TextBlock *TextPage::split(GList *charsA, int rot) { 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)); + blk->addChild(split(chars2, rot, vertOnly)); delete chars2; x0 = x1; } } chars2 = getChars(charsA, x0, yMin - 1, xMax + 1, yMax + 1); - blk->addChild(split(chars2, rot)); + blk->addChild(split(chars2, rot, vertOnly)); delete chars2; // split horizontally @@ -3689,17 +3874,17 @@ TextBlock *TextPage::split(GList *charsA, int rot) { 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)); + blk->addChild(split(chars2, rot, gFalse)); delete chars2; y0 = y1; } } chars2 = getChars(charsA, xMin - 1, y0, xMax + 1, yMax + 1); - blk->addChild(split(chars2, rot)); + blk->addChild(split(chars2, rot, gFalse)); delete chars2; // split into larger and smaller chars - } else if (nLargeChars > 0) { + } else if (doLargeCharSplit) { #if 0 //~debug printf("large char split xMin=%g yMin=%g xMax=%g yMax=%g\n", xMin, pageHeight - yMax, xMax, pageHeight - yMin); @@ -3714,23 +3899,60 @@ TextBlock *TextPage::split(GList *charsA, int rot) { chars3->append(ch); } } - blk = split(chars3, rot); + blk = split(chars3, rot, gFalse); + chars2->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); insertLargeChars(chars2, blk); delete chars2; delete chars3; + // split into lines -- this handles the case where lines overlap slightly + } else if (doLineSplit) { + mergeSplitLines(charsA, rot, splitLines); +#if 0 //~debug + printf("line split xMin=%g yMin=%g xMax=%g yMax=%g\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin); + for (i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + printf(" yMin=%g yMax=%g\n", + pageHeight - splitLine->yMax, pageHeight - splitLine->yMin); + } +#endif + if (splitLines->getLength() == 1) { + // if merging sub/superscripts resulted in a single line, then + // it's a leaf + blk = new TextBlock(blkLeaf, rot); + SplitLine *splitLine = (SplitLine *)splitLines->get(0); + for (i = 0; i < splitLine->chars->getLength(); ++i) { + blk->addChild((TextChar *)splitLine->chars->get(i), gTrue); + } + } else { + blk = new TextBlock((rot & 1) ? blkVertSplit : blkHorizSplit, rot); + blk->smallSplit = gFalse; + for (i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + blk->addChild(split(splitLine->chars, rot, singleLine)); + } + } + // create a leaf node } else { #if 0 //~debug printf("leaf xMin=%g yMin=%g xMax=%g yMax=%g\n", xMin, pageHeight - yMax, xMax, pageHeight - yMin); + printf(" "); + for (i = 0; i < charsA->getLength(); ++i) { + printf("%c", ((TextChar *)charsA->get(i))->c); + } + printf("\n"); #endif blk = new TextBlock(blkLeaf, rot); + charsA->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); for (i = 0; i < charsA->getLength(); ++i) { blk->addChild((TextChar *)charsA->get(i), gTrue); } } + deleteGList(splitLines, SplitLine); delete horizGaps; delete vertGaps; @@ -3750,11 +3972,12 @@ GList *TextPage::getChars(GList *charsA, double xMin, double yMin, ret = new GList(); for (i = 0; i < charsA->getLength(); ++i) { ch = (TextChar *)charsA->get(i); - // because of {ascent,descent}AdjustFactor, the y coords (or x - // coords for rot 1,3) for the gaps will be a little bit tight -- - // so we use the center of the character here + // compute the center of the adjusted bbox, and check to see if + // that's inside the specified rectangle x = 0.5 * (ch->xMin + ch->xMax); - y = 0.5 * (ch->yMin + ch->yMax); + y = 0.5 * (ch->yMin + ch->yMax + + (ascentAdjustFactor - descentAdjustFactor) * + (ch->yMax - ch->yMin)); if (x > xMin && x < xMax && y > yMin && y < yMax) { ret->append(ch); } @@ -3765,22 +3988,15 @@ GList *TextPage::getChars(GList *charsA, double xMin, double yMin, void TextPage::findGaps(GList *charsA, int rot, double *xMinOut, double *yMinOut, double *xMaxOut, double *yMaxOut, - double *avgFontSizeOut, + double *avgFontSizeOut, double *minFontSizeOut, + GList *splitLines, TextGaps *horizGaps, TextGaps *vertGaps) { - TextChar *ch; - char *horizProfile, *vertProfile; - double xMin, yMin, xMax, yMax, w; - double minFontSize, avgFontSize, splitPrecision, invSplitPrecision; - double ascentAdjust, descentAdjust; - int xMinI, yMinI, xMaxI, yMaxI, xMinI2, yMinI2, xMaxI2, yMaxI2; - int start, x, y, i; - - //----- compute bbox, min font size, average font size, and split precision + //----- compute bbox, min font size, and average font size - xMin = yMin = xMax = yMax = 0; // make gcc happy - minFontSize = avgFontSize = 0; - for (i = 0; i < charsA->getLength(); ++i) { - ch = (TextChar *)charsA->get(i); + double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double avgFontSize = 0, minFontSize = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); if (i == 0 || ch->xMin < xMin) { xMin = ch->xMin; } @@ -3799,115 +4015,338 @@ void TextPage::findGaps(GList *charsA, int rot, } } avgFontSize /= charsA->getLength(); - splitPrecision = splitPrecisionMul * minFontSize; - if (splitPrecision < minSplitPrecision) { - splitPrecision = minSplitPrecision; - } - invSplitPrecision = 1 / splitPrecision; *xMinOut = xMin; *yMinOut = yMin; *xMaxOut = xMax; *yMaxOut = yMax; *avgFontSizeOut = avgFontSize; + *minFontSizeOut = minFontSize; - //----- compute the horizontal and vertical profiles + //----- find vertical gaps - if (xMin * invSplitPrecision < 0.5 * INT_MIN || - xMax * invSplitPrecision > 0.5 * INT_MAX || - yMin * invSplitPrecision < 0.5 * INT_MIN || - yMax * invSplitPrecision > 0.5 * INT_MAX) { - return; - } - // add some slack to the array bounds to avoid floating point - // precision problems - 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 * invSplitPrecision); - xMaxI2 = (int)floor(ch->xMax * invSplitPrecision); - ascentAdjust = ascentAdjustFactor * (ch->yMax - ch->yMin); - yMinI2 = (int)floor((ch->yMin + ascentAdjust) * invSplitPrecision); - descentAdjust = descentAdjustFactor * (ch->yMax - ch->yMin); - yMaxI2 = (int)floor((ch->yMax - descentAdjust) * invSplitPrecision); - break; - case 1: - descentAdjust = descentAdjustFactor * (ch->xMax - ch->xMin); - xMinI2 = (int)floor((ch->xMin + descentAdjust) * invSplitPrecision); - ascentAdjust = ascentAdjustFactor * (ch->xMax - ch->xMin); - 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 * invSplitPrecision); - xMaxI2 = (int)floor(ch->xMax * invSplitPrecision); - descentAdjust = descentAdjustFactor * (ch->yMax - ch->yMin); - yMinI2 = (int)floor((ch->yMin + descentAdjust) * invSplitPrecision); - ascentAdjust = ascentAdjustFactor * (ch->yMax - ch->yMin); - yMaxI2 = (int)floor((ch->yMax - ascentAdjust) * invSplitPrecision); - break; - case 3: - ascentAdjust = ascentAdjustFactor * (ch->xMax - ch->xMin); - xMinI2 = (int)floor((ch->xMin + ascentAdjust) * invSplitPrecision); - descentAdjust = descentAdjustFactor * (ch->xMax - ch->xMin); - 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] = 1; + if (rot & 1) { + charsA->sort(&TextChar::cmpY); + double yyMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0) { + yyMax = ch->yMax; + } else if (ch->yMin <= yyMax) { + if (ch->yMax > yyMax) { + yyMax = ch->yMax; + } + } else { + horizGaps->addGap(0.5 * (ch->yMin + yyMax), ch->yMin - yyMax); + yyMax = ch->yMax; + } } - for (x = xMinI2; x <= xMaxI2; ++x) { - vertProfile[x - xMinI] = 1; + } else { + charsA->sort(&TextChar::cmpX); + double xxMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0) { + xxMax = ch->xMax; + } else if (ch->xMin <= xxMax) { + if (ch->xMax > xxMax) { + xxMax = ch->xMax; + } + } else { + vertGaps->addGap(0.5 * (ch->xMin + xxMax), ch->xMin - xxMax); + xxMax = ch->xMax; + } } } - //----- build the list of horizontal gaps + //----- partition into lines and find horizontal gaps - for (start = yMinI; start < yMaxI && !horizProfile[start - yMinI]; ++start) ; - for (y = start; y < yMaxI; ++y) { - if (horizProfile[y - yMinI]) { - if (!horizProfile[y + 1 - yMinI]) { - start = y; + if (rot & 1) { + charsA->sort(&TextChar::cmpX); + SplitLine *splitLine = NULL; + double xxMin = 0, xxMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0 || + ch->xMin > xxMax - lineOverlapThreshold * (xxMax - xxMin)) { + if (i > 0 && ch->xMin > xxMax) { + vertGaps->addGap(0.5 * (ch->xMin + xxMax), ch->xMin - xxMax); + } + xxMin = ch->xMin; + xxMax = ch->xMax; + splitLine = new SplitLine(i, i, xxMin, xxMax); + splitLines->append(splitLine); + } else { + splitLine->lastCharIdx = i; + if (ch->xMax > xxMax) { + xxMax = ch->xMax; + splitLine->yMax = xxMax; + } } - } else { - if (horizProfile[y + 1 - yMinI]) { - w = (y - start) * splitPrecision; - horizGaps->addGap((start + 1) * splitPrecision + 0.5 * w, w); + } + } else { + charsA->sort(&TextChar::cmpY); + SplitLine *splitLine = NULL; + double yyMin = 0, yyMax = 0; + for (int i = 0; i < charsA->getLength(); ++i) { + TextChar *ch = (TextChar *)charsA->get(i); + if (i == 0 || + ch->yMin > yyMax - lineOverlapThreshold * (yyMax - yyMin)) { + if (i > 0 && ch->yMin > yyMax) { + horizGaps->addGap(0.5 * (ch->yMin + yyMax), ch->yMin - yyMax); + } + yyMin = ch->yMin; + yyMax = ch->yMax; + splitLine = new SplitLine(i, i, yyMin, yyMax); + splitLines->append(splitLine); + } else { + splitLine->lastCharIdx = i; + if (ch->yMax > yyMax) { + yyMax = ch->yMax; + splitLine->yMax = yyMax; + } } } } +} - //----- build the list of vertical gaps +void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { + if (rot & 1) { - for (start = xMinI; start < xMaxI && !vertProfile[start - xMinI]; ++start) ; - for (x = start; x < xMaxI; ++x) { - if (vertProfile[x - xMinI]) { - if (!vertProfile[x + 1 - xMinI]) { - start = x; + // build the list of chars in each line, sort by y + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + splitLine->chars = new GList(); + for (int j = splitLine->firstCharIdx; j <= splitLine->lastCharIdx; ++j) { + splitLine->chars->append(charsA->get(j)); } - } else { - if (vertProfile[x + 1 - xMinI]) { - w = (x - start) * splitPrecision; - vertGaps->addGap((start + 1) * splitPrecision + 0.5 * w, w); + splitLine->chars->sort(&TextChar::cmpY); + } + + // look for sub/superscripts accidentally split into separate lines + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + SplitLine *prevLine = NULL; + SplitLine *nextLine = NULL; + + // check for overlapping lines + GBool maybeSub = gFalse; + if (i > 0) { + prevLine = (SplitLine *)splitLines->get(i-1); + double minOverlap = minSubSuperscriptVertOverlap + * (prevLine->yMax - prevLine->yMin); + maybeSub = prevLine->yMax - splitLine->yMin > minOverlap; + } + GBool maybeSuper = gFalse; + if (i < splitLines->getLength() - 1) { + nextLine = (SplitLine *)splitLines->get(i+1); + double minOverlap = minSubSuperscriptVertOverlap + * (nextLine->yMax - nextLine->yMin); + maybeSuper = splitLine->yMax - nextLine->yMin > minOverlap; + } + if (!maybeSub && !maybeSuper) { + continue; + } + + // check whether each char in the line is a subscript or + // superscript: look at the two chars above-left and above-right + // the subscript (or below-left and below-right the superscript) + // and check that they are either to the left and right of the + // subscript (superscript), or above the subscript (below the + // superscript) to account for cases with both a subscript and + // superscript + int idxAbove = 0; + int idxBelow = 0; + GBool allSubSuper = gTrue; + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + double maxOverlap = maxSubSuperscriptHorizOverlap + * (ch->xMax - ch->xMin); + GBool isSub = gFalse; + if (maybeSub) { + while (idxAbove < prevLine->chars->getLength() && + ((TextChar *)prevLine->chars->get(idxAbove))->yMin < ch->yMin) { + ++idxAbove; + } + isSub = ch->xMin < prevLine->yMax && + (idxAbove == 0 || + ch->yMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->yMax - maxOverlap || + ch->xMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->xMax) && + (idxAbove == prevLine->chars->getLength() || + ch->yMax < ((TextChar *)prevLine->chars->get(idxAbove))->yMin + maxOverlap || + ch->xMin > ((TextChar *)prevLine->chars->get(idxAbove))->xMax); + } + GBool isSuper = gFalse; + if (maybeSuper) { + while (idxBelow < nextLine->chars->getLength() && + ((TextChar *)nextLine->chars->get(idxBelow))->yMin < ch->yMin) { + ++idxBelow; + } + isSuper = ch->xMax > nextLine->yMin && + (idxBelow == 0 || + ch->yMin > ((TextChar *)nextLine->chars->get(idxBelow - 1))->yMax - maxOverlap || + ch->xMax < ((TextChar *)nextLine->chars->get(idxBelow - 1))->xMin) && + (idxBelow == nextLine->chars->getLength() || + ch->yMax < ((TextChar *)nextLine->chars->get(idxBelow))->yMin + maxOverlap || + ch->xMax < ((TextChar *)nextLine->chars->get(idxBelow))->xMin); + } + if (!isSub && !isSuper) { + allSubSuper = gFalse; + break; + } + } + + // merge sub/superscripts into correct lines + if (allSubSuper) { + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + if (maybeSub && ch->xMin < prevLine->yMax) { + prevLine->chars->append(ch); + if (ch->xMin < prevLine->yMin) { + prevLine->yMin = ch->xMin; + } + if (ch->xMax > prevLine->yMax) { + prevLine->yMax = ch->xMax; + } + } else { + nextLine->chars->append(ch); + if (ch->xMin < nextLine->yMin) { + nextLine->yMin = ch->xMin; + } + if (ch->xMax > nextLine->yMax) { + nextLine->yMax = ch->xMax; + } + } + } + if (maybeSub) { + prevLine->chars->sort(&TextChar::cmpY); + } + if (maybeSuper) { + nextLine->chars->sort(&TextChar::cmpY); + } + delete splitLine; + splitLines->del(i); + } + } + + } else { + + // build the list of chars in each line, sort by x + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + splitLine->chars = new GList(); + for (int j = splitLine->firstCharIdx; j <= splitLine->lastCharIdx; ++j) { + splitLine->chars->append(charsA->get(j)); + } + splitLine->chars->sort(&TextChar::cmpX); + } + + // look for sub/superscripts accidentally split into separate lines + for (int i = 0; i < splitLines->getLength(); ++i) { + SplitLine *splitLine = (SplitLine *)splitLines->get(i); + SplitLine *prevLine = NULL; + SplitLine *nextLine = NULL; + + // check for overlapping lines + GBool maybeSub = gFalse; + if (i > 0) { + prevLine = (SplitLine *)splitLines->get(i-1); + double minOverlap = minSubSuperscriptVertOverlap + * (prevLine->yMax - prevLine->yMin); + maybeSub = prevLine->yMax - splitLine->yMin > minOverlap; + } + GBool maybeSuper = gFalse; + if (i < splitLines->getLength() - 1) { + nextLine = (SplitLine *)splitLines->get(i+1); + double minOverlap = minSubSuperscriptVertOverlap + * (nextLine->yMax - nextLine->yMin); + maybeSuper = splitLine->yMax - nextLine->yMin > minOverlap; + } + if (!maybeSub && !maybeSuper) { + continue; + } + + // check whether each char in the line is a subscript or + // superscript: look at the two chars above-left and above-right + // the subscript (or below-left and below-right the superscript) + // and check that they are either to the left and right of the + // subscript (superscript), or above the subscript (below the + // superscript) to account for cases with both a subscript and + // superscript + int idxAbove = 0; + int idxBelow = 0; + GBool allSubSuper = gTrue; + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + double maxOverlap = maxSubSuperscriptHorizOverlap + * (ch->yMax - ch->yMin); + GBool isSub = gFalse; + if (maybeSub) { + while (idxAbove < prevLine->chars->getLength() && + ((TextChar *)prevLine->chars->get(idxAbove))->xMin < ch->xMin) { + ++idxAbove; + } + isSub = ch->yMin < prevLine->yMax && + (idxAbove == 0 || + ch->xMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->xMax - maxOverlap || + ch->yMin > ((TextChar *)prevLine->chars->get(idxAbove - 1))->yMax) && + (idxAbove == prevLine->chars->getLength() || + ch->xMax < ((TextChar *)prevLine->chars->get(idxAbove))->xMin + maxOverlap || + ch->yMin > ((TextChar *)prevLine->chars->get(idxAbove))->yMax); + } + GBool isSuper = gFalse; + if (maybeSuper) { + while (idxBelow < nextLine->chars->getLength() && + ((TextChar *)nextLine->chars->get(idxBelow))->xMin < ch->xMin) { + ++idxBelow; + } + isSuper = ch->yMax > nextLine->yMin && + (idxBelow == 0 || + ch->xMin > ((TextChar *)nextLine->chars->get(idxBelow - 1))->xMax - maxOverlap || + ch->yMax < ((TextChar *)nextLine->chars->get(idxBelow - 1))->yMin) && + (idxBelow == nextLine->chars->getLength() || + ch->xMax < ((TextChar *)nextLine->chars->get(idxBelow))->xMin + maxOverlap || + ch->yMax < ((TextChar *)nextLine->chars->get(idxBelow))->yMin); + } + if (!isSub && !isSuper) { + allSubSuper = gFalse; + break; + } + } + + // merge sub/superscripts into correct lines + if (allSubSuper) { + for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { + TextChar *ch = (TextChar *)splitLine->chars->get(idx); + if (maybeSub && ch->yMin < prevLine->yMax) { + prevLine->chars->append(ch); + if (ch->yMin < prevLine->yMin) { + prevLine->yMin = ch->yMin; + } + if (ch->yMax > prevLine->yMax) { + prevLine->yMax = ch->yMax; + } + } else { + nextLine->chars->append(ch); + if (ch->yMin < nextLine->yMin) { + nextLine->yMin = ch->yMin; + } + if (ch->yMax > nextLine->yMax) { + nextLine->yMax = ch->yMax; + } + } + } + if (maybeSub) { + prevLine->chars->sort(&TextChar::cmpX); + } + if (maybeSuper) { + nextLine->chars->sort(&TextChar::cmpX); + } + delete splitLine; + splitLines->del(i); } } - } - gfree(horizProfile); - gfree(vertProfile); + } } // Decide whether this block is a line, column, or multiple columns: @@ -4668,7 +5107,12 @@ TextLine *TextPage::buildLine(GList *charsA, int rot, while (i < charsA->getLength()) { sp = wordSp - 1; spaceAfter = gFalse; - dir = getCharDirection((TextChar *)charsA->get(i)); + dir = getCharDirection( + (TextChar *)charsA->get(i), + (i > 0 && !spaceAfter) ? (TextChar *)charsA->get(i-1) + : (TextChar *)NULL, + (i < charsA->getLength() - 1) ? (TextChar *)charsA->get(i+1) + : (TextChar *)NULL); rotated = ((TextChar *)charsA->get(i))->rotated; for (j = i+1; j < charsA->getLength(); ++j) { ch = (TextChar *)charsA->get(j-1); @@ -4684,7 +5128,10 @@ TextLine *TextPage::buildLine(GList *charsA, int rot, spaceAfter = gTrue; break; } - dir2 = getCharDirection(ch2); + dir2 = getCharDirection( + ch2, ch, + (j < charsA->getLength() - 1) ? (TextChar *)charsA->get(j+1) + : (TextChar *)NULL); if (ch->font != ch2->font || fabs(ch->fontSize - ch2->fontSize) > 0.01 || (control.splitRotatedWords && ch2->rotated != rotated) || @@ -4830,7 +5277,7 @@ double TextPage::computeWordSpacingThreshold(GList *charsA, int rot) { } } -// Check the characters direction: returns 1 for L or Num; -1 for R; 0 +// Check the character's direction: returns 1 for L or Num; -1 for R; 0 // for others. int TextPage::getCharDirection(TextChar *ch) { if (unicodeTypeL(ch->c) || unicodeTypeNum(ch->c)) { @@ -4842,6 +5289,46 @@ int TextPage::getCharDirection(TextChar *ch) { return 0; } +// Check the character's direction, in the context of the left and +// right neighboring characters (either of which may be NULL). +// Returns 1 for L or Num; -1 for R; 0 for others. +int TextPage::getCharDirection(TextChar *ch, TextChar *left, TextChar *right) { + GBool open; + Unicode opposite; + if (unicodeBracketInfo(ch->c, &open, &opposite)) { + // bracket takes the direction of the first char inside the bracket + Unicode first = 0; + if (open && right) { + first = right->c; + } else if (!open && left) { + first = left->c; + } + if (unicodeTypeL(first) || unicodeTypeNum(first)) { + return 1; + } + if (unicodeTypeR(first)) { + return -1; + } + return 0; + } else if (unicodeTypeNumSep(ch->c)) { + // numeric separator is numeric if either side is a digit; neutral + // otherwise + if ((left && unicodeTypeDigit(left->c)) || + (right && unicodeTypeDigit(right->c))) { + return 1; + } + return 0; + } else { + if (unicodeTypeL(ch->c) || unicodeTypeDigit(ch->c)) { + return 1; + } + if (unicodeTypeR(ch->c)) { + return -1; + } + return 0; + } +} + int TextPage::assignPhysLayoutPositions(GList *columns) { assignLinePhysPositions(columns); return assignColumnPhysPositions(columns); @@ -5130,11 +5617,11 @@ GBool TextPage::findText(Unicode *s, int len, buildFindCols(); - // convert the search string to uppercase + // convert the search string to lowercase if (!caseSensitive) { s2 = (Unicode *)gmallocn(len, sizeof(Unicode)); for (i = 0; i < len; ++i) { - s2[i] = unicodeToUpper(s[i]); + s2[i] = unicodeToLower(s[i]); } } else { s2 = s; @@ -5214,7 +5701,7 @@ GBool TextPage::findText(Unicode *s, int len, continue; } - // convert the line to uppercase + // convert the line to lowercase m = line->len; if (!caseSensitive) { if (m > txtSize) { @@ -5222,7 +5709,7 @@ GBool TextPage::findText(Unicode *s, int len, txtSize = m; } for (k = 0; k < m; ++k) { - txt[k] = unicodeToUpper(line->text[k]); + txt[k] = unicodeToLower(line->text[k]); } } else { txt = line->text; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h index a1d19c22d7d..302975cd5f1 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h @@ -99,7 +99,12 @@ public: class TextFontInfo { public: + // Create a TextFontInfo for the current font in [state]. TextFontInfo(GfxState *state); + + // Create a dummy TextFontInfo. + TextFontInfo(); + ~TextFontInfo(); GBool matches(GfxState *state); @@ -225,6 +230,7 @@ public: double getBaseline(); int getRotation() { return rot; } GList *getWords() { return words; } + Unicode *getUnicode() { return text; } int getLength() { return len; } double getEdge(int idx) { return edge[idx]; } GBool getHyphenated() { return hyphenated; } @@ -476,6 +482,16 @@ public: // be problematic when converting text to Unicode. GBool problematicForUnicode() { return problematic; } + // Add a 'special' character to this TextPage. This is currently + // used by pdftohtml to insert markers for form fields. + void addSpecialChar(double xMin, double yMin, double xMax, double yMax, + int rot, TextFontInfo *font, double fontSize, + Unicode u); + + // Remove characters that fall inside a region. + void removeChars(double xMin, double yMin, double xMax, double yMax, + double xOverlapThresh, double yOverlapThresh); + private: void startPage(GfxState *state); @@ -524,6 +540,8 @@ private: char *eol, int eolLen); void encodeFragment(Unicode *text, int len, UnicodeMap *uMap, GBool primaryLR, GString *s); + GBool unicodeEffectiveTypeLOrNum(Unicode u, Unicode left, Unicode right); + GBool unicodeEffectiveTypeR(Unicode u, Unicode left, Unicode right); // analysis int rotateChars(GList *charsA); @@ -539,14 +557,16 @@ private: GList *separateOverlappingText(GList *charsA); TextColumn *buildOverlappingTextColumn(GList *overlappingChars); TextBlock *splitChars(GList *charsA); - TextBlock *split(GList *charsA, int rot); + TextBlock *split(GList *charsA, int rot, GBool vertOnly); GList *getChars(GList *charsA, double xMin, double yMin, double xMax, double yMax); void findGaps(GList *charsA, int rot, double *xMinOut, double *yMinOut, double *xMaxOut, double *yMaxOut, - double *avgFontSizeOut, + double *avgFontSizeOut, double *minFontSizeOut, + GList *splitLines, TextGaps *horizGaps, TextGaps *vertGaps); + void mergeSplitLines(GList *charsA, int rot, GList *splitLines); void tagBlock(TextBlock *blk); void insertLargeChars(GList *largeChars, TextBlock *blk); void insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk); @@ -570,6 +590,7 @@ private: void getLineChars(TextBlock *blk, GList *charsA); double computeWordSpacingThreshold(GList *charsA, int rot); int getCharDirection(TextChar *ch); + int getCharDirection(TextChar *ch, TextChar *left, TextChar *right); int assignPhysLayoutPositions(GList *columns); void assignLinePhysPositions(GList *columns); void computeLinePhysWidth(TextLine *line, UnicodeMap *uMap); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc index d1a5aea2963..d5916627082 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc @@ -786,17 +786,18 @@ GBool TileMap::cvtDevToWindow(int pg, int xd, int yd, break; case displaySideBySideSingle: - if (!(pg == state->getScrollPage() || - (pg == state->getScrollPage() + 1 && - state->getScrollPage() + 1 <= state->getDoc()->getNumPages()))) { + leftPg = (state->getScrollPage() - 1) | 1; + if (!(pg == leftPg || + (pg == leftPg + 1 && + leftPg + 1 <= state->getDoc()->getNumPages()))) { *xw = *yw = 0; return gFalse; } - pageW1 = pageW[state->getScrollPage() - 1]; - pageH1 = pageH[state->getScrollPage() - 1]; - if (state->getScrollPage() + 1 <= state->getDoc()->getNumPages()) { - pageW2 = pageW[state->getScrollPage()]; - pageH2 = pageH[state->getScrollPage()]; + pageW1 = pageW[leftPg - 1]; + pageH1 = pageH[leftPg - 1]; + if (leftPg + 1 <= state->getDoc()->getNumPages()) { + pageW2 = pageW[leftPg]; + pageH2 = pageH[leftPg]; } else { // display a single page as though there were a blank facing // page of the same size @@ -819,13 +820,12 @@ GBool TileMap::cvtDevToWindow(int pg, int xd, int yd, } else { offsetY = 0; } - if (pg == state->getScrollPage()) { + if (pg == leftPg) { *xw = xd + offsetX - state->getScrollX(); - *yw = yd + offsetY - state->getScrollY(); } else { *xw = xd + offsetX2 - state->getScrollX(); - *yw = yd + offsetY - state->getScrollY(); } + *yw = yd + offsetY - state->getScrollY(); break; case displaySideBySideContinuous: diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h index 60ac55d124e..d103c2ea382 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h @@ -11,8 +11,7 @@ static UnicodeMapRange latin1UnicodeMapRanges[] = { { 0x000c, 0x000d, 0x0c, 1 }, { 0x0020, 0x007e, 0x20, 1 }, { 0x00a0, 0x00a0, 0x20, 1 }, - { 0x00a1, 0x00ac, 0xa1, 1 }, - { 0x00ae, 0x00ff, 0xae, 1 }, + { 0x00a1, 0x00ff, 0xa1, 1 }, { 0x010c, 0x010c, 0x43, 1 }, { 0x010d, 0x010d, 0x63, 1 }, { 0x0131, 0x0131, 0x69, 1 }, @@ -29,7 +28,7 @@ static UnicodeMapRange latin1UnicodeMapRanges[] = { { 0x02da, 0x02da, 0xb0, 1 }, { 0x02dc, 0x02dc, 0x7e, 1 }, { 0x2010, 0x2010, 0x2d, 1 }, - { 0x2013, 0x2013, 0xad, 1 }, + { 0x2013, 0x2013, 0x2d, 1 }, { 0x2014, 0x2014, 0x2d2d, 2 }, { 0x2018, 0x2018, 0x60, 1 }, { 0x2019, 0x2019, 0x27, 1 }, @@ -76,6 +75,7 @@ static UnicodeMapRange ascii7UnicodeMapRanges[] = { { 0x000c, 0x000d, 0x0c, 1 }, { 0x0020, 0x005f, 0x20, 1 }, { 0x0061, 0x007e, 0x61, 1 }, + { 0x00a0, 0x00a0, 0x20, 1 }, { 0x00a6, 0x00a6, 0x7c, 1 }, { 0x00a9, 0x00a9, 0x286329, 3 }, { 0x00ae, 0x00ae, 0x285229, 3 }, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc index e4f09e19ae3..72dbc0e159c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc @@ -83,7 +83,7 @@ UnicodeRemapping::~UnicodeRemapping() { } void UnicodeRemapping::addRemapping(Unicode in, Unicode *out, int len) { - int i; + int i, j; if (in < 256 && len == 1) { page0[in] = out[0]; @@ -96,11 +96,16 @@ void UnicodeRemapping::addRemapping(Unicode in, Unicode *out, int len) { sMap = (UnicodeRemappingString *) greallocn(sMap, sMapSize, sizeof(UnicodeRemappingString)); } - sMap[sMapLen].in = in; - for (i = 0; i < len && i < maxUnicodeString; ++i) { - sMap[sMapLen].out[i] = out[i]; + i = findSMap(in); + if (i < sMapLen) { + memmove(sMap + i + 1, sMap + i, + (sMapLen - i) * sizeof(UnicodeRemappingString)); } - sMap[sMapLen].len = i; + sMap[i].in = in; + for (j = 0; j < len && j < maxUnicodeString; ++j) { + sMap[i].out[j] = out[j]; + } + sMap[i].len = j; ++sMapLen; } } @@ -148,6 +153,24 @@ void UnicodeRemapping::parseFile(GString *fileName) { fclose(f); } +// Determine the location in sMap to insert/replace the entry for [u]. +int UnicodeRemapping::findSMap(Unicode u) { + int a, b, m; + + a = -1; + b = sMapLen; + // invariant: sMap[a].in < u <= sMap[b].in + while (b - a > 1) { + m = (a + b) / 2; + if (sMap[m].in < u) { + a = m; + } else { + b = m; + } + } + return b; +} + int UnicodeRemapping::map(Unicode in, Unicode *out, int size) { int a, b, m, i; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h index 950c93afc8e..dbf435e7dd1 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h @@ -43,6 +43,8 @@ public: private: + int findSMap(Unicode u); + Unicode page0[256]; UnicodeRemappingString *sMap; int sMapLen, sMapSize; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc index 328d2478167..e6a91af2756 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc @@ -2,7 +2,7 @@ // // UnicodeTypeTable.cc // -// Copyright 2004-2013 Glyph & Cog, LLC +// Copyright 2004-2021 Glyph & Cog, LLC // //======================================================================== @@ -25,54 +25,54 @@ static UnicodeMapTableEntry typeTable[256] = { { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N....NNNNLNNNNN..##NLNNN#LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLNNNNNNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLNNLLLLLLLLNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, - { "RRRR.........RNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNN#################.##RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' }, - { "RRRRRRRRRRRRRRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'N' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL..LLLLLLLNNNNN", 'X' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLL..NNNNNNNNNNNNNN", 'X' }, - { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN.NLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR###########", 'X' }, + { "######NNR..R.RNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNN##########.##RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNN#NNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' }, + { "RRRRRRRRRRRRRRRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNRRNNNNRNNNRR", 'X' }, + { "RRRRRRRRRRRRRRRRRRRRRRNNNNRNNNNNNNNNRNNNRNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNN#NNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLLLLNNNNNNNNLLLLNLLLNNNNNNNLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL..LLLLLLL.LLNN", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNLNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLL.LLLLLLLLNNNNNN", 'X' }, + { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNNLLLLLLLLNNNNNNNNNNLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN.NNNNNN", 'X' }, + { "NLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLNNNNNNNNNNNNN", 'X' }, + { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNN.....LLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL.LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNNNLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLNNNLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNLLNNLLLLLLNLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNN", 'X' }, + { "NLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL.LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLNNLLLLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLNNLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNNNNNNNLNLLNNNNNNNNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNNNLNLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNLLLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLNNLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNLLLNLNNNLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLNNNNNNNNNNNNNLNNNNNNNLLLLNLLLLLLNLLLNNLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' }, - { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRN.....NNNNNNNNNNNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#L########..NNNL##########..NNN...................................NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL.LLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLR......NNNNNNNNNNNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLRNNNNNNNN#L########..NNNL##########..NNNLLLLLLLLLLLLLL...................................NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL.LLLLLLLLLLLNNLLLLNNNNNLLLLLNNNNLLNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNN..NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN####################LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'N' }, - { NULL, 'N' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'N' }, { NULL, 'L' }, { NULL, 'N' }, { NULL, 'N' }, { NULL, 'N' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNLLNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'N' }, { NULL, 'N' }, - { NULL, 'N' }, - { NULL, 'N' }, - { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNNNNNNNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNNNNLLNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN", 'X' }, { NULL, 'L' }, { NULL, 'L' }, @@ -99,7 +99,7 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { NULL, 'L' }, { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'L' }, { NULL, 'L' }, { NULL, 'L' }, @@ -188,12 +188,12 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, - { NULL, 'L' }, + { "LLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLNLLLNLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNLLLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLNNLLNNLLLLLLLLLLLLNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLNNLLLLLNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLNLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNLLLLNLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, { NULL, 'L' }, { NULL, 'L' }, @@ -356,9 +356,9 @@ static UnicodeCaseTableVector caseTable02 = {{ 0x019e, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, 0x0231, 0x0231, 0x0233, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, - 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f, - 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f, + 0x0238, 0x0239, 0x2c65, 0x023c, 0x023c, 0x019a, 0x2c66, 0x023f, + 0x0240, 0x0242, 0x0242, 0x0180, 0x0289, 0x028c, 0x0247, 0x0247, + 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x024f, 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, @@ -397,8 +397,8 @@ static UnicodeCaseTableVector caseTable03 = {{ 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, - 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, - 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, 0x037d, 0x037e, 0x037f, + 0x0371, 0x0371, 0x0373, 0x0373, 0x0374, 0x0375, 0x0377, 0x0377, + 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, 0x037d, 0x037e, 0x03f3, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03ac, 0x0387, 0x03ad, 0x03ae, 0x03af, 0x038b, 0x03cc, 0x038d, 0x03cd, 0x03ce, 0x0390, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, @@ -408,13 +408,13 @@ static UnicodeCaseTableVector caseTable03 = {{ 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, - 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x03cf, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x03d7, 0x03b2, 0x03b8, 0x03d2, 0x03d3, 0x03d4, 0x03c6, 0x03c0, 0x03d7, 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03ef, 0x03ba, 0x03c1, 0x03f2, 0x03f3, 0x03b8, 0x03b5, 0x03f6, 0x03f8, - 0x03f8, 0x03f2, 0x03fb, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff + 0x03f8, 0x03f2, 0x03fb, 0x03fb, 0x03fc, 0x037b, 0x037c, 0x037d }}; static UnicodeCaseTableVector caseTable04 = {{ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, @@ -441,22 +441,22 @@ static UnicodeCaseTableVector caseTable04 = {{ 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, - 0x04c0, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, + 0x04cf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04ce, 0x04cf, 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, - 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f6, 0x04f7, - 0x04f9, 0x04f9, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff + 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7, + 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff }}; static UnicodeCaseTableVector caseTable05 = {{ 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, - 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, - 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f, - 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, - 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f, + 0x0511, 0x0511, 0x0513, 0x0513, 0x0515, 0x0515, 0x0517, 0x0517, + 0x0519, 0x0519, 0x051b, 0x051b, 0x051d, 0x051d, 0x051f, 0x051f, + 0x0521, 0x0521, 0x0523, 0x0523, 0x0525, 0x0525, 0x0527, 0x0527, + 0x0529, 0x0529, 0x052b, 0x052b, 0x052d, 0x052d, 0x052f, 0x052f, 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, @@ -484,6 +484,108 @@ static UnicodeCaseTableVector caseTable05 = {{ 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x05f5, 0x05f6, 0x05f7, 0x05f8, 0x05f9, 0x05fa, 0x05fb, 0x05fc, 0x05fd, 0x05fe, 0x05ff }}; +static UnicodeCaseTableVector caseTable10 = {{ + 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, + 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f, + 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, + 0x1018, 0x1019, 0x101a, 0x101b, 0x101c, 0x101d, 0x101e, 0x101f, + 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, + 0x1028, 0x1029, 0x102a, 0x102b, 0x102c, 0x102d, 0x102e, 0x102f, + 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, + 0x1038, 0x1039, 0x103a, 0x103b, 0x103c, 0x103d, 0x103e, 0x103f, + 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, + 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, + 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, + 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f, + 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, + 0x1068, 0x1069, 0x106a, 0x106b, 0x106c, 0x106d, 0x106e, 0x106f, + 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, + 0x1078, 0x1079, 0x107a, 0x107b, 0x107c, 0x107d, 0x107e, 0x107f, + 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, + 0x1088, 0x1089, 0x108a, 0x108b, 0x108c, 0x108d, 0x108e, 0x108f, + 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, + 0x1098, 0x1099, 0x109a, 0x109b, 0x109c, 0x109d, 0x109e, 0x109f, + 0x2d00, 0x2d01, 0x2d02, 0x2d03, 0x2d04, 0x2d05, 0x2d06, 0x2d07, + 0x2d08, 0x2d09, 0x2d0a, 0x2d0b, 0x2d0c, 0x2d0d, 0x2d0e, 0x2d0f, + 0x2d10, 0x2d11, 0x2d12, 0x2d13, 0x2d14, 0x2d15, 0x2d16, 0x2d17, + 0x2d18, 0x2d19, 0x2d1a, 0x2d1b, 0x2d1c, 0x2d1d, 0x2d1e, 0x2d1f, + 0x2d20, 0x2d21, 0x2d22, 0x2d23, 0x2d24, 0x2d25, 0x10c6, 0x2d27, + 0x10c8, 0x10c9, 0x10ca, 0x10cb, 0x10cc, 0x2d2d, 0x10ce, 0x10cf, + 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, + 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, + 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, + 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, + 0x10f8, 0x10f9, 0x10fa, 0x10fb, 0x10fc, 0x10fd, 0x10fe, 0x10ff +}}; +static UnicodeCaseTableVector caseTable13 = {{ + 0x1300, 0x1301, 0x1302, 0x1303, 0x1304, 0x1305, 0x1306, 0x1307, + 0x1308, 0x1309, 0x130a, 0x130b, 0x130c, 0x130d, 0x130e, 0x130f, + 0x1310, 0x1311, 0x1312, 0x1313, 0x1314, 0x1315, 0x1316, 0x1317, + 0x1318, 0x1319, 0x131a, 0x131b, 0x131c, 0x131d, 0x131e, 0x131f, + 0x1320, 0x1321, 0x1322, 0x1323, 0x1324, 0x1325, 0x1326, 0x1327, + 0x1328, 0x1329, 0x132a, 0x132b, 0x132c, 0x132d, 0x132e, 0x132f, + 0x1330, 0x1331, 0x1332, 0x1333, 0x1334, 0x1335, 0x1336, 0x1337, + 0x1338, 0x1339, 0x133a, 0x133b, 0x133c, 0x133d, 0x133e, 0x133f, + 0x1340, 0x1341, 0x1342, 0x1343, 0x1344, 0x1345, 0x1346, 0x1347, + 0x1348, 0x1349, 0x134a, 0x134b, 0x134c, 0x134d, 0x134e, 0x134f, + 0x1350, 0x1351, 0x1352, 0x1353, 0x1354, 0x1355, 0x1356, 0x1357, + 0x1358, 0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, + 0x1360, 0x1361, 0x1362, 0x1363, 0x1364, 0x1365, 0x1366, 0x1367, + 0x1368, 0x1369, 0x136a, 0x136b, 0x136c, 0x136d, 0x136e, 0x136f, + 0x1370, 0x1371, 0x1372, 0x1373, 0x1374, 0x1375, 0x1376, 0x1377, + 0x1378, 0x1379, 0x137a, 0x137b, 0x137c, 0x137d, 0x137e, 0x137f, + 0x1380, 0x1381, 0x1382, 0x1383, 0x1384, 0x1385, 0x1386, 0x1387, + 0x1388, 0x1389, 0x138a, 0x138b, 0x138c, 0x138d, 0x138e, 0x138f, + 0x1390, 0x1391, 0x1392, 0x1393, 0x1394, 0x1395, 0x1396, 0x1397, + 0x1398, 0x1399, 0x139a, 0x139b, 0x139c, 0x139d, 0x139e, 0x139f, + 0x13a0, 0x13a1, 0x13a2, 0x13a3, 0x13a4, 0x13a5, 0x13a6, 0x13a7, + 0x13a8, 0x13a9, 0x13aa, 0x13ab, 0x13ac, 0x13ad, 0x13ae, 0x13af, + 0x13b0, 0x13b1, 0x13b2, 0x13b3, 0x13b4, 0x13b5, 0x13b6, 0x13b7, + 0x13b8, 0x13b9, 0x13ba, 0x13bb, 0x13bc, 0x13bd, 0x13be, 0x13bf, + 0x13c0, 0x13c1, 0x13c2, 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, + 0x13c8, 0x13c9, 0x13ca, 0x13cb, 0x13cc, 0x13cd, 0x13ce, 0x13cf, + 0x13d0, 0x13d1, 0x13d2, 0x13d3, 0x13d4, 0x13d5, 0x13d6, 0x13d7, + 0x13d8, 0x13d9, 0x13da, 0x13db, 0x13dc, 0x13dd, 0x13de, 0x13df, + 0x13e0, 0x13e1, 0x13e2, 0x13e3, 0x13e4, 0x13e5, 0x13e6, 0x13e7, + 0x13e8, 0x13e9, 0x13ea, 0x13eb, 0x13ec, 0x13ed, 0x13ee, 0x13ef, + 0x13f0, 0x13f1, 0x13f2, 0x13f3, 0x13f4, 0x13f5, 0x13f6, 0x13f7, + 0x13f0, 0x13f1, 0x13f2, 0x13f3, 0x13f4, 0x13f5, 0x13fe, 0x13ff +}}; +static UnicodeCaseTableVector caseTable1c = {{ + 0x1c00, 0x1c01, 0x1c02, 0x1c03, 0x1c04, 0x1c05, 0x1c06, 0x1c07, + 0x1c08, 0x1c09, 0x1c0a, 0x1c0b, 0x1c0c, 0x1c0d, 0x1c0e, 0x1c0f, + 0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17, + 0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f, + 0x1c20, 0x1c21, 0x1c22, 0x1c23, 0x1c24, 0x1c25, 0x1c26, 0x1c27, + 0x1c28, 0x1c29, 0x1c2a, 0x1c2b, 0x1c2c, 0x1c2d, 0x1c2e, 0x1c2f, + 0x1c30, 0x1c31, 0x1c32, 0x1c33, 0x1c34, 0x1c35, 0x1c36, 0x1c37, + 0x1c38, 0x1c39, 0x1c3a, 0x1c3b, 0x1c3c, 0x1c3d, 0x1c3e, 0x1c3f, + 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, + 0x1c48, 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, + 0x1c50, 0x1c51, 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, + 0x1c58, 0x1c59, 0x1c5a, 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f, + 0x1c60, 0x1c61, 0x1c62, 0x1c63, 0x1c64, 0x1c65, 0x1c66, 0x1c67, + 0x1c68, 0x1c69, 0x1c6a, 0x1c6b, 0x1c6c, 0x1c6d, 0x1c6e, 0x1c6f, + 0x1c70, 0x1c71, 0x1c72, 0x1c73, 0x1c74, 0x1c75, 0x1c76, 0x1c77, + 0x1c78, 0x1c79, 0x1c7a, 0x1c7b, 0x1c7c, 0x1c7d, 0x1c7e, 0x1c7f, + 0x0432, 0x0434, 0x043e, 0x0441, 0x0442, 0x0442, 0x044a, 0x0463, + 0xa64b, 0x1c89, 0x1c8a, 0x1c8b, 0x1c8c, 0x1c8d, 0x1c8e, 0x1c8f, + 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, + 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, + 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, + 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, + 0x10f8, 0x10f9, 0x10fa, 0x1cbb, 0x1cbc, 0x10fd, 0x10fe, 0x10ff, + 0x1cc0, 0x1cc1, 0x1cc2, 0x1cc3, 0x1cc4, 0x1cc5, 0x1cc6, 0x1cc7, + 0x1cc8, 0x1cc9, 0x1cca, 0x1ccb, 0x1ccc, 0x1ccd, 0x1cce, 0x1ccf, + 0x1cd0, 0x1cd1, 0x1cd2, 0x1cd3, 0x1cd4, 0x1cd5, 0x1cd6, 0x1cd7, + 0x1cd8, 0x1cd9, 0x1cda, 0x1cdb, 0x1cdc, 0x1cdd, 0x1cde, 0x1cdf, + 0x1ce0, 0x1ce1, 0x1ce2, 0x1ce3, 0x1ce4, 0x1ce5, 0x1ce6, 0x1ce7, + 0x1ce8, 0x1ce9, 0x1cea, 0x1ceb, 0x1cec, 0x1ced, 0x1cee, 0x1cef, + 0x1cf0, 0x1cf1, 0x1cf2, 0x1cf3, 0x1cf4, 0x1cf5, 0x1cf6, 0x1cf7, + 0x1cf8, 0x1cf9, 0x1cfa, 0x1cfb, 0x1cfc, 0x1cfd, 0x1cfe, 0x1cff +}}; static UnicodeCaseTableVector caseTable1e = {{ 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, @@ -504,7 +606,7 @@ static UnicodeCaseTableVector caseTable1e = {{ 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e95, 0x1e96, 0x1e97, - 0x1e98, 0x1e99, 0x1e9a, 0x1e61, 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, + 0x1e98, 0x1e99, 0x1e9a, 0x1e61, 0x1e9c, 0x1e9d, 0x00df, 0x1e9f, 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, @@ -516,7 +618,7 @@ static UnicodeCaseTableVector caseTable1e = {{ 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, - 0x1ef9, 0x1ef9, 0x1efa, 0x1efb, 0x1efc, 0x1efd, 0x1efe, 0x1eff + 0x1ef9, 0x1ef9, 0x1efb, 0x1efb, 0x1efd, 0x1efd, 0x1eff, 0x1eff }}; static UnicodeCaseTableVector caseTable1f = {{ 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, @@ -559,7 +661,7 @@ static UnicodeCaseTableVector caseTable21 = {{ 0x2118, 0x2119, 0x211a, 0x211b, 0x211c, 0x211d, 0x211e, 0x211f, 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x03c9, 0x2127, 0x2128, 0x2129, 0x006b, 0x00e5, 0x212c, 0x212d, 0x212e, 0x212f, - 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, + 0x2130, 0x2131, 0x214e, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b, 0x213c, 0x213d, 0x213e, 0x213f, 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214a, 0x214b, 0x214c, 0x214d, 0x214e, 0x214f, @@ -569,7 +671,7 @@ static UnicodeCaseTableVector caseTable21 = {{ 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, - 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, + 0x2180, 0x2181, 0x2182, 0x2184, 0x2184, 0x2185, 0x2186, 0x2187, 0x2188, 0x2189, 0x218a, 0x218b, 0x218c, 0x218d, 0x218e, 0x218f, 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, 0x219a, 0x219b, 0x219c, 0x219d, 0x219e, 0x219f, @@ -620,6 +722,142 @@ static UnicodeCaseTableVector caseTable24 = {{ 0x24f0, 0x24f1, 0x24f2, 0x24f3, 0x24f4, 0x24f5, 0x24f6, 0x24f7, 0x24f8, 0x24f9, 0x24fa, 0x24fb, 0x24fc, 0x24fd, 0x24fe, 0x24ff }}; +static UnicodeCaseTableVector caseTable2c = {{ + 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, + 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, + 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, + 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f, + 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57, + 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c2f, + 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, + 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, + 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, + 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f, + 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57, + 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c5f, + 0x2c61, 0x2c61, 0x026b, 0x1d7d, 0x027d, 0x2c65, 0x2c66, 0x2c68, + 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x0251, 0x0271, 0x0250, + 0x0252, 0x2c71, 0x2c73, 0x2c73, 0x2c74, 0x2c76, 0x2c76, 0x2c77, + 0x2c78, 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x023f, 0x0240, + 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87, + 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f, + 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97, + 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f, + 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7, + 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf, + 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7, + 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf, + 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7, + 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf, + 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7, + 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf, + 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce3, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, + 0x2ce8, 0x2ce9, 0x2cea, 0x2cec, 0x2cec, 0x2cee, 0x2cee, 0x2cef, + 0x2cf0, 0x2cf1, 0x2cf3, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, + 0x2cf8, 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff +}}; +static UnicodeCaseTableVector caseTablea6 = {{ + 0xa600, 0xa601, 0xa602, 0xa603, 0xa604, 0xa605, 0xa606, 0xa607, + 0xa608, 0xa609, 0xa60a, 0xa60b, 0xa60c, 0xa60d, 0xa60e, 0xa60f, + 0xa610, 0xa611, 0xa612, 0xa613, 0xa614, 0xa615, 0xa616, 0xa617, + 0xa618, 0xa619, 0xa61a, 0xa61b, 0xa61c, 0xa61d, 0xa61e, 0xa61f, + 0xa620, 0xa621, 0xa622, 0xa623, 0xa624, 0xa625, 0xa626, 0xa627, + 0xa628, 0xa629, 0xa62a, 0xa62b, 0xa62c, 0xa62d, 0xa62e, 0xa62f, + 0xa630, 0xa631, 0xa632, 0xa633, 0xa634, 0xa635, 0xa636, 0xa637, + 0xa638, 0xa639, 0xa63a, 0xa63b, 0xa63c, 0xa63d, 0xa63e, 0xa63f, + 0xa641, 0xa641, 0xa643, 0xa643, 0xa645, 0xa645, 0xa647, 0xa647, + 0xa649, 0xa649, 0xa64b, 0xa64b, 0xa64d, 0xa64d, 0xa64f, 0xa64f, + 0xa651, 0xa651, 0xa653, 0xa653, 0xa655, 0xa655, 0xa657, 0xa657, + 0xa659, 0xa659, 0xa65b, 0xa65b, 0xa65d, 0xa65d, 0xa65f, 0xa65f, + 0xa661, 0xa661, 0xa663, 0xa663, 0xa665, 0xa665, 0xa667, 0xa667, + 0xa669, 0xa669, 0xa66b, 0xa66b, 0xa66d, 0xa66d, 0xa66e, 0xa66f, + 0xa670, 0xa671, 0xa672, 0xa673, 0xa674, 0xa675, 0xa676, 0xa677, + 0xa678, 0xa679, 0xa67a, 0xa67b, 0xa67c, 0xa67d, 0xa67e, 0xa67f, + 0xa681, 0xa681, 0xa683, 0xa683, 0xa685, 0xa685, 0xa687, 0xa687, + 0xa689, 0xa689, 0xa68b, 0xa68b, 0xa68d, 0xa68d, 0xa68f, 0xa68f, + 0xa691, 0xa691, 0xa693, 0xa693, 0xa695, 0xa695, 0xa697, 0xa697, + 0xa699, 0xa699, 0xa69b, 0xa69b, 0xa69c, 0xa69d, 0xa69e, 0xa69f, + 0xa6a0, 0xa6a1, 0xa6a2, 0xa6a3, 0xa6a4, 0xa6a5, 0xa6a6, 0xa6a7, + 0xa6a8, 0xa6a9, 0xa6aa, 0xa6ab, 0xa6ac, 0xa6ad, 0xa6ae, 0xa6af, + 0xa6b0, 0xa6b1, 0xa6b2, 0xa6b3, 0xa6b4, 0xa6b5, 0xa6b6, 0xa6b7, + 0xa6b8, 0xa6b9, 0xa6ba, 0xa6bb, 0xa6bc, 0xa6bd, 0xa6be, 0xa6bf, + 0xa6c0, 0xa6c1, 0xa6c2, 0xa6c3, 0xa6c4, 0xa6c5, 0xa6c6, 0xa6c7, + 0xa6c8, 0xa6c9, 0xa6ca, 0xa6cb, 0xa6cc, 0xa6cd, 0xa6ce, 0xa6cf, + 0xa6d0, 0xa6d1, 0xa6d2, 0xa6d3, 0xa6d4, 0xa6d5, 0xa6d6, 0xa6d7, + 0xa6d8, 0xa6d9, 0xa6da, 0xa6db, 0xa6dc, 0xa6dd, 0xa6de, 0xa6df, + 0xa6e0, 0xa6e1, 0xa6e2, 0xa6e3, 0xa6e4, 0xa6e5, 0xa6e6, 0xa6e7, + 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0xa6ec, 0xa6ed, 0xa6ee, 0xa6ef, + 0xa6f0, 0xa6f1, 0xa6f2, 0xa6f3, 0xa6f4, 0xa6f5, 0xa6f6, 0xa6f7, + 0xa6f8, 0xa6f9, 0xa6fa, 0xa6fb, 0xa6fc, 0xa6fd, 0xa6fe, 0xa6ff +}}; +static UnicodeCaseTableVector caseTablea7 = {{ + 0xa700, 0xa701, 0xa702, 0xa703, 0xa704, 0xa705, 0xa706, 0xa707, + 0xa708, 0xa709, 0xa70a, 0xa70b, 0xa70c, 0xa70d, 0xa70e, 0xa70f, + 0xa710, 0xa711, 0xa712, 0xa713, 0xa714, 0xa715, 0xa716, 0xa717, + 0xa718, 0xa719, 0xa71a, 0xa71b, 0xa71c, 0xa71d, 0xa71e, 0xa71f, + 0xa720, 0xa721, 0xa723, 0xa723, 0xa725, 0xa725, 0xa727, 0xa727, + 0xa729, 0xa729, 0xa72b, 0xa72b, 0xa72d, 0xa72d, 0xa72f, 0xa72f, + 0xa730, 0xa731, 0xa733, 0xa733, 0xa735, 0xa735, 0xa737, 0xa737, + 0xa739, 0xa739, 0xa73b, 0xa73b, 0xa73d, 0xa73d, 0xa73f, 0xa73f, + 0xa741, 0xa741, 0xa743, 0xa743, 0xa745, 0xa745, 0xa747, 0xa747, + 0xa749, 0xa749, 0xa74b, 0xa74b, 0xa74d, 0xa74d, 0xa74f, 0xa74f, + 0xa751, 0xa751, 0xa753, 0xa753, 0xa755, 0xa755, 0xa757, 0xa757, + 0xa759, 0xa759, 0xa75b, 0xa75b, 0xa75d, 0xa75d, 0xa75f, 0xa75f, + 0xa761, 0xa761, 0xa763, 0xa763, 0xa765, 0xa765, 0xa767, 0xa767, + 0xa769, 0xa769, 0xa76b, 0xa76b, 0xa76d, 0xa76d, 0xa76f, 0xa76f, + 0xa770, 0xa771, 0xa772, 0xa773, 0xa774, 0xa775, 0xa776, 0xa777, + 0xa778, 0xa77a, 0xa77a, 0xa77c, 0xa77c, 0x1d79, 0xa77f, 0xa77f, + 0xa781, 0xa781, 0xa783, 0xa783, 0xa785, 0xa785, 0xa787, 0xa787, + 0xa788, 0xa789, 0xa78a, 0xa78c, 0xa78c, 0x0265, 0xa78e, 0xa78f, + 0xa791, 0xa791, 0xa793, 0xa793, 0xa794, 0xa795, 0xa797, 0xa797, + 0xa799, 0xa799, 0xa79b, 0xa79b, 0xa79d, 0xa79d, 0xa79f, 0xa79f, + 0xa7a1, 0xa7a1, 0xa7a3, 0xa7a3, 0xa7a5, 0xa7a5, 0xa7a7, 0xa7a7, + 0xa7a9, 0xa7a9, 0x0266, 0x025c, 0x0261, 0x026c, 0x026a, 0xa7af, + 0x029e, 0x0287, 0x029d, 0xab53, 0xa7b5, 0xa7b5, 0xa7b7, 0xa7b7, + 0xa7b9, 0xa7b9, 0xa7bb, 0xa7bb, 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, + 0xa7c0, 0xa7c1, 0xa7c3, 0xa7c3, 0xa794, 0x0282, 0x1d8e, 0xa7c8, + 0xa7c8, 0xa7ca, 0xa7ca, 0xa7cb, 0xa7cc, 0xa7cd, 0xa7ce, 0xa7cf, + 0xa7d0, 0xa7d1, 0xa7d2, 0xa7d3, 0xa7d4, 0xa7d5, 0xa7d6, 0xa7d7, + 0xa7d8, 0xa7d9, 0xa7da, 0xa7db, 0xa7dc, 0xa7dd, 0xa7de, 0xa7df, + 0xa7e0, 0xa7e1, 0xa7e2, 0xa7e3, 0xa7e4, 0xa7e5, 0xa7e6, 0xa7e7, + 0xa7e8, 0xa7e9, 0xa7ea, 0xa7eb, 0xa7ec, 0xa7ed, 0xa7ee, 0xa7ef, + 0xa7f0, 0xa7f1, 0xa7f2, 0xa7f3, 0xa7f4, 0xa7f6, 0xa7f6, 0xa7f7, + 0xa7f8, 0xa7f9, 0xa7fa, 0xa7fb, 0xa7fc, 0xa7fd, 0xa7fe, 0xa7ff +}}; +static UnicodeCaseTableVector caseTableab = {{ + 0xab00, 0xab01, 0xab02, 0xab03, 0xab04, 0xab05, 0xab06, 0xab07, + 0xab08, 0xab09, 0xab0a, 0xab0b, 0xab0c, 0xab0d, 0xab0e, 0xab0f, + 0xab10, 0xab11, 0xab12, 0xab13, 0xab14, 0xab15, 0xab16, 0xab17, + 0xab18, 0xab19, 0xab1a, 0xab1b, 0xab1c, 0xab1d, 0xab1e, 0xab1f, + 0xab20, 0xab21, 0xab22, 0xab23, 0xab24, 0xab25, 0xab26, 0xab27, + 0xab28, 0xab29, 0xab2a, 0xab2b, 0xab2c, 0xab2d, 0xab2e, 0xab2f, + 0xab30, 0xab31, 0xab32, 0xab33, 0xab34, 0xab35, 0xab36, 0xab37, + 0xab38, 0xab39, 0xab3a, 0xab3b, 0xab3c, 0xab3d, 0xab3e, 0xab3f, + 0xab40, 0xab41, 0xab42, 0xab43, 0xab44, 0xab45, 0xab46, 0xab47, + 0xab48, 0xab49, 0xab4a, 0xab4b, 0xab4c, 0xab4d, 0xab4e, 0xab4f, + 0xab50, 0xab51, 0xab52, 0xab53, 0xab54, 0xab55, 0xab56, 0xab57, + 0xab58, 0xab59, 0xab5a, 0xab5b, 0xab5c, 0xab5d, 0xab5e, 0xab5f, + 0xab60, 0xab61, 0xab62, 0xab63, 0xab64, 0xab65, 0xab66, 0xab67, + 0xab68, 0xab69, 0xab6a, 0xab6b, 0xab6c, 0xab6d, 0xab6e, 0xab6f, + 0x13a0, 0x13a1, 0x13a2, 0x13a3, 0x13a4, 0x13a5, 0x13a6, 0x13a7, + 0x13a8, 0x13a9, 0x13aa, 0x13ab, 0x13ac, 0x13ad, 0x13ae, 0x13af, + 0x13b0, 0x13b1, 0x13b2, 0x13b3, 0x13b4, 0x13b5, 0x13b6, 0x13b7, + 0x13b8, 0x13b9, 0x13ba, 0x13bb, 0x13bc, 0x13bd, 0x13be, 0x13bf, + 0x13c0, 0x13c1, 0x13c2, 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, + 0x13c8, 0x13c9, 0x13ca, 0x13cb, 0x13cc, 0x13cd, 0x13ce, 0x13cf, + 0x13d0, 0x13d1, 0x13d2, 0x13d3, 0x13d4, 0x13d5, 0x13d6, 0x13d7, + 0x13d8, 0x13d9, 0x13da, 0x13db, 0x13dc, 0x13dd, 0x13de, 0x13df, + 0x13e0, 0x13e1, 0x13e2, 0x13e3, 0x13e4, 0x13e5, 0x13e6, 0x13e7, + 0x13e8, 0x13e9, 0x13ea, 0x13eb, 0x13ec, 0x13ed, 0x13ee, 0x13ef, + 0xabc0, 0xabc1, 0xabc2, 0xabc3, 0xabc4, 0xabc5, 0xabc6, 0xabc7, + 0xabc8, 0xabc9, 0xabca, 0xabcb, 0xabcc, 0xabcd, 0xabce, 0xabcf, + 0xabd0, 0xabd1, 0xabd2, 0xabd3, 0xabd4, 0xabd5, 0xabd6, 0xabd7, + 0xabd8, 0xabd9, 0xabda, 0xabdb, 0xabdc, 0xabdd, 0xabde, 0xabdf, + 0xabe0, 0xabe1, 0xabe2, 0xabe3, 0xabe4, 0xabe5, 0xabe6, 0xabe7, + 0xabe8, 0xabe9, 0xabea, 0xabeb, 0xabec, 0xabed, 0xabee, 0xabef, + 0xabf0, 0xabf1, 0xabf2, 0xabf3, 0xabf4, 0xabf5, 0xabf6, 0xabf7, + 0xabf8, 0xabf9, 0xabfa, 0xabfb, 0xabfc, 0xabfd, 0xabfe, 0xabff +}}; static UnicodeCaseTableVector caseTableff = {{ 0xff00, 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, @@ -671,8 +909,10 @@ static UnicodeCaseTableVector *caseTable[256] = { NULL, NULL, NULL, + &caseTable10, NULL, NULL, + &caseTable13, NULL, NULL, NULL, @@ -681,9 +921,7 @@ static UnicodeCaseTableVector *caseTable[256] = { NULL, NULL, NULL, - NULL, - NULL, - NULL, + &caseTable1c, NULL, &caseTable1e, &caseTable1f, @@ -699,6 +937,7 @@ static UnicodeCaseTableVector *caseTable[256] = { NULL, NULL, NULL, + &caseTable2c, NULL, NULL, NULL, @@ -820,9 +1059,12 @@ static UnicodeCaseTableVector *caseTable[256] = { NULL, NULL, NULL, + &caseTablea6, + &caseTablea7, NULL, NULL, NULL, + &caseTableab, NULL, NULL, NULL, @@ -906,11 +1148,640 @@ static UnicodeCaseTableVector *caseTable[256] = { NULL, NULL, NULL, + &caseTableff +}; + +static Unicode bracketTable00[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80000029, 0x0028, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000005d, 0, 0x005b, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000007d, 0, 0x007b, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable0f[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0x80000f3b, 0x0f3a, 0x80000f3d, 0x0f3c, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable16[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000169c, 0x169b, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable20[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x80002046, 0x2045, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x8000207e, 0x207d, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x8000208e, 0x208d, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable23[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80002309, 0x2308, 0x8000230b, 0x230a, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x8000232a, 0x2329, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable27[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80002769, 0x2768, 0x8000276b, 0x276a, 0x8000276d, 0x276c, 0x8000276f, 0x276e, + 0x80002771, 0x2770, 0x80002773, 0x2772, 0x80002775, 0x2774, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x800027c6, 0x27c5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x800027e7, 0x27e6, + 0x800027e9, 0x27e8, 0x800027eb, 0x27ea, 0x800027ed, 0x27ec, 0x800027ef, 0x27ee, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable29[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x80002984, 0x2983, 0x80002986, 0x2985, 0x80002988, + 0x2987, 0x8000298a, 0x2989, 0x8000298c, 0x298b, 0x80002990, 0x298f, 0x8000298e, + 0x298d, 0x80002992, 0x2991, 0x80002994, 0x2993, 0x80002996, 0x2995, 0x80002998, + 0x2997, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x800029d9, 0x29d8, 0x800029db, 0x29da, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x800029fd, 0x29fc, 0, 0 +}; +static Unicode bracketTable2e[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0x80002e23, 0x2e22, 0x80002e25, 0x2e24, 0x80002e27, 0x2e26, + 0x80002e29, 0x2e28, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTable30[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0x80003009, 0x3008, 0x8000300b, 0x300a, 0x8000300d, 0x300c, 0x8000300f, 0x300e, + 0x80003011, 0x3010, 0, 0, 0x80003015, 0x3014, 0x80003017, 0x3016, + 0x80003019, 0x3018, 0x8000301b, 0x301a, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTablefe[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x8000fe5a, 0xfe59, 0x8000fe5c, 0xfe5b, 0x8000fe5e, 0xfe5d, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode bracketTableff[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0x8000ff09, 0xff08, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000ff3d, 0, 0xff3b, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x8000ff5d, 0, 0xff5b, 0, 0x8000ff60, + 0xff5f, 0, 0x8000ff63, 0xff62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Unicode *bracketTable[256] = { + bracketTable00, NULL, NULL, NULL, NULL, - &caseTableff + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTable0f, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTable16, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTable20, + NULL, + NULL, + bracketTable23, + NULL, + NULL, + NULL, + bracketTable27, + NULL, + bracketTable29, + NULL, + NULL, + NULL, + NULL, + bracketTable2e, + NULL, + bracketTable30, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + bracketTablefe, + bracketTableff }; static inline char getType(Unicode c) { @@ -936,6 +1807,14 @@ GBool unicodeTypeR(Unicode c) { return getType(c) == 'R'; } +GBool unicodeTypeDigit(Unicode c) { + return getType(c) == '#'; +} + +GBool unicodeTypeNumSep(Unicode c) { + return getType(c) == '.'; +} + GBool unicodeTypeNum(Unicode c) { char t; @@ -957,7 +1836,7 @@ GBool unicodeTypeWord(Unicode c) { return t == 'L' || t == 'R' || t == '#'; } -Unicode unicodeToUpper(Unicode c) { +Unicode unicodeToLower(Unicode c) { int i; if (c > 0xffff) { @@ -970,3 +1849,28 @@ Unicode unicodeToUpper(Unicode c) { return c; } +GBool unicodeBracketInfo(Unicode c, GBool *open, Unicode *opposite) { + int i; + Unicode bracket; + + if (c > 0xffff) { + return gFalse; + } + i = (c >> 8) & 0xff; + if (!bracketTable[i]) { + return gFalse; + } + bracket = bracketTable[i][c & 0xff]; + if (!bracket) { + return gFalse; + } + if (bracket & 0x80000000) { + *open = gTrue; + *opposite = bracket & 0x7fffffff; + } else { + *open = gFalse; + *opposite = bracket; + } + return gTrue; +} + diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h index 3230d927891..e1149fd6bc2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h @@ -15,12 +15,18 @@ extern GBool unicodeTypeL(Unicode c); extern GBool unicodeTypeR(Unicode c); +extern GBool unicodeTypeDigit(Unicode c); + +extern GBool unicodeTypeNumSep(Unicode c); + extern GBool unicodeTypeNum(Unicode c); extern GBool unicodeTypeAlphaNum(Unicode c); extern GBool unicodeTypeWord(Unicode c); -extern Unicode unicodeToUpper(Unicode c); +extern Unicode unicodeToLower(Unicode c); + +extern GBool unicodeBracketInfo(Unicode c, GBool *open, Unicode *opposite); #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc index 9ae636226ae..c04b52f937a 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc @@ -71,8 +71,11 @@ static void writeToFile(void *stream, const char *data, int len) { fwrite(data, 1, len, (FILE *)stream); } -GBool WebFont::writeTTF(const char *fontFilePath) { - FILE *out; +static void writeToString(void *stream, const char *data, int len) { + ((GString *)stream)->append(data, len); +} + +GBool WebFont::generateTTF(FoFiOutputFunc outFunc, void *stream) { int *codeToGID; Guchar *cmapTable; GBool freeCodeToGID; @@ -100,22 +103,35 @@ GBool WebFont::writeTTF(const char *fontFilePath) { if (!cmapTable) { return gFalse; } - if (!(out = fopen(fontFilePath, "wb"))) { - gfree(cmapTable); - return gFalse; - } - ffTrueType->writeTTF(writeToFile, out, NULL, NULL, + ffTrueType->writeTTF(outFunc, stream, NULL, NULL, cmapTable, cmapTableLength); - fclose(out); gfree(cmapTable); return gTrue; } -GBool WebFont::writeOTF(const char *fontFilePath) { +GBool WebFont::writeTTF(const char *fontFilePath) { + FILE *out = fopen(fontFilePath, "wb"); + if (!out) { + return gFalse; + } + GBool ret = generateTTF(writeToFile, out); + fclose(out); + return ret; +} + +GString *WebFont::getTTFData() { + GString *s = new GString(); + if (!generateTTF(writeToString, s)) { + delete s; + return NULL; + } + return s; +} + +GBool WebFont::generateOTF(FoFiOutputFunc outFunc, void *stream) { int *codeToGID; Gushort *widths; Guchar *cmapTable; - FILE *out; int nCodes, nWidths, cmapTableLength; if (ffType1C) { @@ -138,27 +154,13 @@ GBool WebFont::writeOTF(const char *fontFilePath) { widths = makeCIDType0CWidths(codeToGID, nCodes, &nWidths); gfree(codeToGID); } - if (!(out = fopen(fontFilePath, "wb"))) { - gfree(cmapTable); - gfree(widths); - return gFalse; - } - ffType1C->convertToOpenType(writeToFile, out, - nWidths, widths, + ffType1C->convertToOpenType(outFunc, stream, 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); + outFunc(stream, fontBuf, fontLength); } else { return gFalse; @@ -167,6 +169,25 @@ GBool WebFont::writeOTF(const char *fontFilePath) { return gTrue; } +GBool WebFont::writeOTF(const char *fontFilePath) { + FILE *out = fopen(fontFilePath, "wb"); + if (!out) { + return gFalse; + } + GBool ret = generateOTF(writeToFile, out); + fclose(out); + return ret; +} + +GString *WebFont::getOTFData() { + GString *s = new GString(); + if (!generateOTF(writeToString, s)) { + delete s; + return NULL; + } + return s; +} + Gushort *WebFont::makeType1CWidths(int *codeToGID, int nCodes, int *nWidths) { Gushort *widths; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h index a967e2e490a..283bdbe914d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h @@ -18,6 +18,7 @@ #endif #include "gtypes.h" +#include "FoFiBase.h" #include "GfxFont.h" class FoFiTrueType; @@ -45,13 +46,23 @@ public: // called if canWriteTTF() returns true. Returns true on success. GBool writeTTF(const char *fontFilePath); + // Return the TrueType file as a string. This can only be called if + // canWriteTTF() returns true. Returns null on error. + GString *getTTFData(); + // 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); + // Return the OpenType file as a string. This can only be called if + // canWriteOTF() returns true. Returns null on error. + GString *getOTFData(); + private: + GBool generateTTF(FoFiOutputFunc outFunc, void *stream); + GBool generateOTF(FoFiOutputFunc outFunc, void *stream); Gushort *makeType1CWidths(int *codeToGID, int nCodes, int *nWidths); Gushort *makeCIDType0CWidths(int *codeToGID, int nCodes, int *nWidths); Guchar *makeUnicodeCmapTable(int *codeToGID, int nCodes, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc index 6928fa9c9a8..8002a07a7f6 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc @@ -293,8 +293,10 @@ void XFAScanner::scanNode(ZxElement *elem, } if (elem->isElement("field")) { - scanField(elem, childName, childFullName, exclGroupName, - dataElem, formValues); + if (childName && childFullName) { + scanField(elem, childName, childFullName, exclGroupName, + dataElem, formValues); + } } else { GString *childExclGroupName; if (elem->isElement("exclGroup")) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc index 0c364638b39..51af86db5ba 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc @@ -299,6 +299,7 @@ XRef::XRef(BaseStream *strA, GBool repair) { ok = gTrue; errCode = errNone; + repaired = gFalse; size = 0; last = -1; entries = NULL; @@ -336,6 +337,7 @@ XRef::XRef(BaseStream *strA, GBool repair) { errCode = errDamaged; return; } + repaired = gTrue; // if the 'repair' flag is not set, read the xref table } else { @@ -512,7 +514,7 @@ GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { char buf[6]; GFileOffset off, pos2; GBool more; - int first, n, newSize, gen, i, c; + int first, n, digit, newSize, gen, i, c; str->setPos(start + *pos + offset); @@ -531,7 +533,11 @@ GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { } first = 0; do { - first = (first * 10) + (c - '0'); + digit = c - '0'; + if (first > (INT_MAX - digit) / 10) { + goto err1; + } + first = (first * 10) + digit; c = str->getChar(); } while (c >= '0' && c <= '9'); if (!Lexer::isSpace(c)) { @@ -542,13 +548,17 @@ GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { } while (Lexer::isSpace(c)); n = 0; do { - n = (n * 10) + (c - '0'); + digit = c - '0'; + if (n > (INT_MAX - digit) / 10) { + goto err1; + } + n = (n * 10) + digit; c = str->getChar(); } while (c >= '0' && c <= '9'); if (!Lexer::isSpace(c)) { goto err1; } - if (first < 0 || n < 0 || first > INT_MAX - n) { + if (first > INT_MAX - n) { goto err1; } if (first + n > size) { @@ -822,7 +832,8 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { } gen = (gen << 8) + c; } - if (gen < 0 || gen > INT_MAX) { + // some PDF generators include a free entry with gen=0xffffffff + if ((gen < 0 || gen > INT_MAX) && type != 0) { return gFalse; } if (entries[i].offset == (GFileOffset)-1) { @@ -908,7 +919,9 @@ GBool XRef::constructXRef() { // skip any PDF whitespace except for '\0' while (*p == '\t' || *p == '\n' || *p == '\x0c' || *p == '\r' || *p == ' ') { - startOfLine = *p == '\n' || *p == '\r'; + if (*p == '\n' || *p == '\r') { + startOfLine = gTrue; + } ++p; } if (!strncmp(p, "stream", 6)) { @@ -924,7 +937,11 @@ GBool XRef::constructXRef() { startOfLine = gFalse; } } else { - startOfLine = *p == '\n' || *p == '\r'; + if (*p == '\n' || *p == '\r') { + startOfLine = gTrue; + } else if (!Lexer::isSpace(*p & 0xff)) { + startOfLine = gFalse; + } ++p; } } @@ -949,6 +966,16 @@ GBool XRef::constructXRef() { gfree(streamObjNums); + // if the file is encrypted, then any objects fetched here will be + // incorrect (because decryption is not yet enabled), so clear the + // cache to avoid that problem + for (int i = 0; i < xrefCacheSize; ++i) { + if (cache[i].num >= 0) { + cache[i].obj.free(); + cache[i].num = -1; + } + } + if (rootNum < 0) { error(errSyntaxError, -1, "Couldn't find trailer dictionary"); return gFalse; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h index 00a8644f3a9..10e4e6a7501 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h @@ -70,6 +70,9 @@ public: // Get the error code (if isOk() returns false). int getErrorCode() { return errCode; } + // Was the xref constructed by the repair code? + GBool isRepaired() { return repaired; } + // Set the encryption parameters. void setEncryption(int permFlagsA, GBool ownerPasswordOkA, Guchar *fileKeyA, int keyLengthA, int encVersionA, @@ -135,6 +138,8 @@ private: int rootNum, rootGen; // catalog dict GBool ok; // true if xref table is valid int errCode; // error code (if <ok> is false) + GBool repaired; // set if the xref table was constructed by + // the repair code Object trailerDict; // trailer dictionary GFileOffset lastXRefPos; // offset of last xref table GFileOffset lastStartxrefPos; // offset of 'startxref' at end of file diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/config.h b/Build/source/libs/xpdf/xpdf-src/xpdf/config.h index 39cade1682c..b41dd492248 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/config.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/config.h @@ -2,7 +2,7 @@ // // config.h // -// Copyright 1996-2021 Glyph & Cog, LLC +// Copyright 1996-2022 Glyph & Cog, LLC // //======================================================================== @@ -14,13 +14,13 @@ //------------------------------------------------------------------------ // xpdf version -#define xpdfVersion "4.03" -#define xpdfVersionNum 4.03 +#define xpdfVersion "4.04" +#define xpdfVersionNum 4.04 #define xpdfMajorVersion 4 -#define xpdfMinorVersion 3 +#define xpdfMinorVersion 4 #define xpdfUpdateVersion 0 #define xpdfMajorVersionStr "4" -#define xpdfMinorVersionStr "3" +#define xpdfMinorVersionStr "4" #define xpdfUpdateVersionStr "0" // supported PDF version @@ -28,11 +28,11 @@ #define supportedPDFVersionNum 2.0 // copyright notice -#define xpdfCopyright "Copyright 1996-2021 Glyph & Cog, LLC" +#define xpdfCopyright "Copyright 1996-2022 Glyph & Cog, LLC" // Windows resource file stuff -#define winxpdfVersion "WinXpdf 4.03" -#define xpdfCopyrightAmp "Copyright 1996-2021 Glyph && Cog, LLC" +#define winxpdfVersion "WinXpdf 4.04" +#define xpdfCopyrightAmp "Copyright 1996-2022 Glyph && Cog, LLC" //------------------------------------------------------------------------ // paper size diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc index e8b74381017..581383fe730 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc @@ -94,6 +94,10 @@ int main(int argc, char *argv[]) { fileName = argv[1]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); if (textEncName[0]) { globalParams->setTextEncoding(textEncName); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc index 42c46223d8b..bde57557c3c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc @@ -123,6 +123,10 @@ int main(int argc, char *argv[]) { fileName = argv[1]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); globalParams->setupBaseFonts(NULL); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc index cd5d34014f4..346346bce77 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc @@ -35,6 +35,7 @@ static GBool dumpRaw = gFalse; static GBool list = gFalse; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; +static GBool verbose = gFalse; static GBool quiet = gFalse; static char cfgFileName[256] = ""; static GBool printVersion = gFalse; @@ -55,6 +56,8 @@ static ArgDesc argDesc[] = { "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, {"-cfg", argString, cfgFileName, sizeof(cfgFileName), @@ -98,7 +101,14 @@ int main(int argc, char *argv[]) { imgRoot = argv[2]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } if (quiet) { globalParams->setErrQuiet(quiet); } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc index 621fb69ea6f..88829b993c3 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc @@ -126,6 +126,10 @@ int main(int argc, char *argv[]) { fileName = argv[1]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); if (textEncName[0]) { globalParams->setTextEncoding(textEncName); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc index af8fe93fbd5..4c98afed50c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc @@ -31,48 +31,66 @@ static int firstPage = 1; static int lastPage = 0; static double zoom = 1; static int resolution = 150; +static double vStretch = 1; +static GBool embedBackground = gFalse; static GBool noFonts = gFalse; +static GBool embedFonts = gFalse; static GBool skipInvisible = gFalse; static GBool allInvisible = gFalse; +static GBool formFields = gFalse; +static GBool tableMode = gFalse; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; +static GBool verbose = gFalse; static GBool quiet = gFalse; static char cfgFileName[256] = ""; static GBool printVersion = gFalse; static GBool printHelp = gFalse; static ArgDesc argDesc[] = { - {"-f", argInt, &firstPage, 0, + {"-f", argInt, &firstPage, 0, "first page to convert"}, - {"-l", argInt, &lastPage, 0, + {"-l", argInt, &lastPage, 0, "last page to convert"}, - {"-z", argFP, &zoom, 0, + {"-z", argFP, &zoom, 0, "initial zoom level (1.0 means 72dpi)"}, - {"-r", argInt, &resolution, 0, + {"-r", argInt, &resolution, 0, "resolution, in DPI (default is 150)"}, - {"-nofonts", argFlag, &noFonts, 0, + {"-vstretch", argFP, &vStretch, 0, + "vertical stretch factor (1.0 means no stretching)"}, + {"-embedbackground", argFlag, &embedBackground, 0, + "embed the background image as base64-encoded data" }, + {"-nofonts", argFlag, &noFonts, 0, "do not extract embedded fonts"}, - {"-skipinvisible", argFlag, &skipInvisible, 0, + {"-embedfonts", argFlag, &embedFonts, 0, + "embed the fonts as base64-encoded data" }, + {"-skipinvisible", argFlag, &skipInvisible, 0, "do not draw invisible text"}, - {"-allinvisible", argFlag, &allInvisible, 0, + {"-allinvisible", argFlag, &allInvisible, 0, "treat all text as invisible"}, - {"-opw", argString, ownerPassword, sizeof(ownerPassword), + {"-formfields", argFlag, &formFields, 0, + "convert form fields to HTML"}, + {"-table", argFlag, &tableMode, 0, + "use table mode for text extraction"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), "owner password (for encrypted files)"}, - {"-upw", argString, userPassword, sizeof(userPassword), + {"-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)"}, - {"-q", argFlag, &quiet, 0, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, + {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, - {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), "configuration file to use in place of .xpdfrc"}, - {"-v", argFlag, &printVersion, 0, + {"-v", argFlag, &printVersion, 0, "print copyright and version info"}, - {"-h", argFlag, &printHelp, 0, + {"-h", argFlag, &printHelp, 0, "print usage information"}, - {"-help", argFlag, &printHelp, 0, + {"-help", argFlag, &printHelp, 0, "print usage information"}, - {"--help", argFlag, &printHelp, 0, + {"--help", argFlag, &printHelp, 0, "print usage information"}, - {"-?", argFlag, &printHelp, 0, + {"-?", argFlag, &printHelp, 0, "print usage information"}, {NULL} }; @@ -111,7 +129,14 @@ int main(int argc, char *argv[]) { htmlDir = argv[2]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } if (quiet) { globalParams->setErrQuiet(quiet); } @@ -166,19 +191,28 @@ int main(int argc, char *argv[]) { } // set up the HTMLGen object - htmlGen = new HTMLGen(resolution); + htmlGen = new HTMLGen(resolution, tableMode); if (!htmlGen->isOk()) { exitCode = 99; goto err1; } htmlGen->setZoom(zoom); + htmlGen->setVStretch(vStretch); htmlGen->setDrawInvisibleText(!skipInvisible); htmlGen->setAllTextInvisible(allInvisible); + htmlGen->setEmbedBackgroundImage(embedBackground); htmlGen->setExtractFontFiles(!noFonts); + htmlGen->setEmbedFonts(embedFonts); + htmlGen->setConvertFormFields(formFields); htmlGen->startDoc(doc); // convert the pages for (pg = firstPage; pg <= lastPage; ++pg) { + if (globalParams->getPrintStatusInfo()) { + fflush(stderr); + printf("[processing page %d]\n", pg); + fflush(stdout); + } htmlFileName = GString::format("{0:s}/page{1:d}.html", htmlDir, pg); pngFileName = GString::format("{0:s}/page{1:d}.png", htmlDir, pg); if (!(htmlFile = openFile(htmlFileName->getCString(), "wb"))) { @@ -187,12 +221,16 @@ int main(int argc, char *argv[]) { delete pngFileName; goto err2; } - if (!(pngFile = openFile(pngFileName->getCString(), "wb"))) { - error(errIO, -1, "Couldn't open PNG file '{0:t}'", pngFileName); - fclose(htmlFile); - delete htmlFileName; - delete pngFileName; - goto err2; + if (embedBackground) { + pngFile = NULL; + } else { + if (!(pngFile = openFile(pngFileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open PNG file '{0:t}'", pngFileName); + fclose(htmlFile); + delete htmlFileName; + delete pngFileName; + goto err2; + } } pngURL = GString::format("page{0:d}.png", pg); err = htmlGen->convertPage(pg, pngURL->getCString(), htmlDir, @@ -200,7 +238,9 @@ int main(int argc, char *argv[]) { &writeToFile, pngFile); delete pngURL; fclose(htmlFile); - fclose(pngFile); + if (!embedBackground) { + fclose(pngFile); + } delete htmlFileName; delete pngFileName; if (err != errNone) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc index f19baccf581..7f3b97b9d94 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc @@ -25,6 +25,7 @@ #include "SplashBitmap.h" #include "Splash.h" #include "SplashOutputDev.h" +#include "Error.h" #include "config.h" static int firstPage = 1; @@ -39,6 +40,7 @@ static char antialiasStr[16] = ""; static char vectorAntialiasStr[16] = ""; static char ownerPassword[33] = ""; static char userPassword[33] = ""; +static GBool verbose = gFalse; static GBool quiet = gFalse; static char cfgFileName[256] = ""; static GBool printVersion = gFalse; @@ -71,6 +73,8 @@ static ArgDesc argDesc[] = { "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, {"-cfg", argString, cfgFileName, sizeof(cfgFileName), @@ -102,7 +106,7 @@ int main(int argc, char *argv[]) { GString *ownerPW, *userPW; SplashColor paperColor; SplashOutputDev *splashOut; - GBool ok; + GBool ok, toStdout, printStatusInfo; int exitCode; int pg; png_structp png; @@ -134,6 +138,10 @@ int main(int argc, char *argv[]) { pngRoot = argv[2]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); globalParams->setupBaseFonts(NULL); if (enableFreeTypeStr[0]) { @@ -151,6 +159,9 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Bad '-aaVector' value on command line\n"); } } + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } if (quiet) { globalParams->setErrQuiet(quiet); } @@ -185,6 +196,10 @@ int main(int argc, char *argv[]) { lastPage = doc->getNumPages(); + // check for stdout; set up to print per-page status info + toStdout = !strcmp(pngRoot, "-"); + printStatusInfo = !toStdout && globalParams->getPrintStatusInfo(); + // write PNG files if (mono) { paperColor[0] = 0xff; @@ -201,10 +216,15 @@ int main(int argc, char *argv[]) { } splashOut->startDoc(doc->getXRef()); for (pg = firstPage; pg <= lastPage; ++pg) { + if (printStatusInfo) { + fflush(stderr); + printf("[processing page %d]\n", pg); + fflush(stdout); + } doc->displayPage(splashOut, pg, resolution, resolution, rotate, gFalse, gTrue, gFalse); if (mono) { - if (!strcmp(pngRoot, "-")) { + if (toStdout) { f = stdout; #ifdef _WIN32 _setmode(_fileno(f), _O_BINARY); @@ -222,7 +242,7 @@ int main(int argc, char *argv[]) { finishPNG(&png, &pngInfo); fclose(f); } else if (gray) { - if (!strcmp(pngRoot, "-")) { + if (toStdout) { f = stdout; #ifdef _WIN32 _setmode(_fileno(f), _O_BINARY); @@ -241,7 +261,7 @@ int main(int argc, char *argv[]) { finishPNG(&png, &pngInfo); fclose(f); } else { // RGB - if (!strcmp(pngRoot, "-")) { + if (toStdout) { f = stdout; #ifdef _WIN32 _setmode(_fileno(f), _O_BINARY); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc index 0b084b014e5..28861ef948b 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc @@ -26,6 +26,7 @@ #include "SplashBitmap.h" #include "Splash.h" #include "SplashOutputDev.h" +#include "Error.h" #include "config.h" static int firstPage = 1; @@ -42,6 +43,7 @@ static char antialiasStr[16] = ""; static char vectorAntialiasStr[16] = ""; static char ownerPassword[33] = ""; static char userPassword[33] = ""; +static GBool verbose = gFalse; static GBool quiet = gFalse; static char cfgFileName[256] = ""; static GBool printVersion = gFalse; @@ -76,6 +78,8 @@ static ArgDesc argDesc[] = { "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, {"-cfg", argString, cfgFileName, sizeof(cfgFileName), @@ -101,7 +105,7 @@ int main(int argc, char *argv[]) { GString *ownerPW, *userPW; SplashColor paperColor; SplashOutputDev *splashOut; - GBool ok; + GBool ok, toStdout, printStatusInfo; int exitCode; int pg, n; const char *ext; @@ -147,6 +151,10 @@ int main(int argc, char *argv[]) { ppmRoot = argv[2]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); globalParams->setupBaseFonts(NULL); if (enableFreeTypeStr[0]) { @@ -164,6 +172,9 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Bad '-aaVector' value on command line\n"); } } + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } if (quiet) { globalParams->setErrQuiet(quiet); } @@ -211,6 +222,10 @@ int main(int argc, char *argv[]) { } + // check for stdout; set up to print per-page status info + toStdout = !strcmp(ppmRoot, "-"); + printStatusInfo = !toStdout && globalParams->getPrintStatusInfo(); + // write PPM files if (mono) { paperColor[0] = 0xff; @@ -229,9 +244,14 @@ int main(int argc, char *argv[]) { } splashOut->startDoc(doc->getXRef()); for (pg = firstPage; pg <= lastPage; ++pg) { + if (printStatusInfo) { + fflush(stderr); + printf("[processing page %d]\n", pg); + fflush(stdout); + } doc->displayPage(splashOut, pg, resolution, resolution, rotate, gFalse, gTrue, gFalse); - if (!strcmp(ppmRoot, "-")) { + if (toStdout) { #ifdef _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc index 36294551a3b..77e90fe0165 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc @@ -64,6 +64,7 @@ static GBool userUnit = gFalse; static GBool duplex = gFalse; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; +static GBool verbose = gFalse; static GBool quiet = gFalse; static char cfgFileName[256] = ""; static GBool printVersion = gFalse; @@ -132,6 +133,8 @@ static ArgDesc argDesc[] = { "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, {"-cfg", argString, cfgFileName, sizeof(cfgFileName), @@ -231,6 +234,10 @@ int main(int argc, char *argv[]) { fileName = argv[1]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); #if HAVE_SPLASH globalParams->setupBaseFonts(NULL); @@ -291,6 +298,9 @@ int main(int argc, char *argv[]) { globalParams->setPSOPI(doOPI); } #endif + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } if (quiet) { globalParams->setErrQuiet(quiet); } @@ -337,6 +347,9 @@ int main(int argc, char *argv[]) { } psFileName->append(doEPS ? ".eps" : ".ps"); } + if (psFileName->cmp("-") == 0) { + globalParams->setPrintStatusInfo(gFalse); + } // get page range if (firstPage < 1) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc index 975cd6a1959..d8bf6df5e67 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc @@ -58,6 +58,7 @@ static double marginTop = 0; static double marginBottom = 0; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; +static GBool verbose = gFalse; static GBool quiet = gFalse; static char cfgFileName[256] = ""; static GBool listEncodings = gFalse; @@ -94,7 +95,7 @@ static ArgDesc argDesc[] = { {"-eol", argString, textEOL, sizeof(textEOL), "output end-of-line convention (unix, dos, or mac)"}, {"-nopgbrk", argFlag, &noPageBreaks, 0, - "don't insert page breaks between pages"}, + "don't insert a page break at the end of each page"}, {"-bom", argFlag, &insertBOM, 0, "insert a Unicode BOM at the start of the text file"}, {"-marginl", argFP, &marginLeft, 0, @@ -109,6 +110,8 @@ static ArgDesc argDesc[] = { "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)"}, + {"-verbose", argFlag, &verbose, 0, + "print per-page status information"}, {"-q", argFlag, &quiet, 0, "don't print any messages or errors"}, {"-cfg", argString, cfgFileName, sizeof(cfgFileName), @@ -162,6 +165,10 @@ int main(int argc, char *argv[]) { ok = parseArgs(argDesc, &argc, argv); if (ok && listEncodings) { // list available encodings + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); GList *encs = globalParams->getAvailableTextEncodings(); for (int i = 0; i < encs->getLength(); ++i) { @@ -182,6 +189,10 @@ int main(int argc, char *argv[]) { fileName = argv[1]; // read config file + if (cfgFileName[0] && !pathIsFile(cfgFileName)) { + error(errConfig, -1, "Config file '{0:s}' doesn't exist or isn't a file", + cfgFileName); + } globalParams = new GlobalParams(cfgFileName); if (textEncName[0]) { globalParams->setTextEncoding(textEncName); @@ -194,6 +205,9 @@ int main(int argc, char *argv[]) { if (noPageBreaks) { globalParams->setTextPageBreaks(gFalse); } + if (verbose) { + globalParams->setPrintStatusInfo(verbose); + } if (quiet) { globalParams->setErrQuiet(quiet); } @@ -247,6 +261,9 @@ int main(int argc, char *argv[]) { } textFileName->append(".txt"); } + if (textFileName->cmp("-") == 0) { + globalParams->setPrintStatusInfo(gFalse); + } // get page range if (firstPage < 1) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest b/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest new file mode 100644 index 00000000000..f46054662fc --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel> + </requestedPrivileges> + </security> + </trustInfo> + <application xmlns="urn:schemas-microsoft-com:asm.v3"> + <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> + <ws2:longPathAware>true</ws2:longPathAware> + </windowsSettings> + </application> +</assembly> |