texlive[63119] Build/source/libs: xpdf 4.04

commits+kakuto at tug.org commits+kakuto at tug.org
Sun Apr 24 05:42:27 CEST 2022


Revision: 63119
          http://tug.org/svn/texlive?view=revision&revision=63119
Author:   kakuto
Date:     2022-04-24 05:42:26 +0200 (Sun, 24 Apr 2022)
Log Message:
-----------
xpdf 4.04

Modified Paths:
--------------
    trunk/Build/source/libs/README
    trunk/Build/source/libs/xpdf/ChangeLog
    trunk/Build/source/libs/xpdf/TLpatches/ChangeLog
    trunk/Build/source/libs/xpdf/TLpatches/TL-Changes
    trunk/Build/source/libs/xpdf/TLpatches/patch-bunched
    trunk/Build/source/libs/xpdf/configure
    trunk/Build/source/libs/xpdf/version.ac
    trunk/Build/source/libs/xpdf/xpdf-src/ANNOUNCE
    trunk/Build/source/libs/xpdf/xpdf-src/CHANGES
    trunk/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt
    trunk/Build/source/libs/xpdf/xpdf-src/INSTALL
    trunk/Build/source/libs/xpdf/xpdf-src/README
    trunk/Build/source/libs/xpdf/xpdf-src/cmake-config.txt
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1
    trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat
    trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5
    trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat
    trunk/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt
    trunk/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc
    trunk/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt
    trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc
    trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.h
    trunk/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt
    trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
    trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.h
    trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc
    trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/config.h
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc

Added Paths:
-----------
    trunk/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest

Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/README	2022-04-24 03:42:26 UTC (rev 63119)
@@ -58,7 +58,7 @@
 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
 

Modified: trunk/Build/source/libs/xpdf/ChangeLog
===================================================================
--- trunk/Build/source/libs/xpdf/ChangeLog	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/ChangeLog	2022-04-24 03:42:26 UTC (rev 63119)
@@ -1,3 +1,8 @@
+2022-04-24  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	* Import xpdf-4.04.
+	* version.ac: Adjust.
+
 2021-05-10  Karl Berry  <karl at freefriends.org>
 
 	* xpdf-src/xpdf/Error.cc (error): label error messages

Modified: trunk/Build/source/libs/xpdf/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/xpdf/TLpatches/ChangeLog	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/TLpatches/ChangeLog	2022-04-24 03:42:26 UTC (rev 63119)
@@ -1,3 +1,7 @@
+2022-04-24  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	* patch-bunched: Adjust.
+
 2021-02-01  Akira Kakuto  <kakuto at w32tex.org>
 
 	* patch-bunched: Adjust.

Modified: trunk/Build/source/libs/xpdf/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/xpdf/TLpatches/TL-Changes	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/TLpatches/TL-Changes	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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:

Modified: trunk/Build/source/libs/xpdf/TLpatches/patch-bunched
===================================================================
--- trunk/Build/source/libs/xpdf/TLpatches/patch-bunched	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/TLpatches/patch-bunched	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
  
  #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 @@
  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 @@
  
  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 @@
  #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 @@
  
  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 @@
  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 @@
 +#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 at 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 @@
  #endif
  
  #if MULTITHREADED
-@@ -787,6 +794,7 @@
+@@ -794,6 +798,7 @@
    f = NULL;
    fileName = NULL;
    if (cfgFileName && cfgFileName[0]) {
@@ -157,7 +153,7 @@
      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 @@
    }
  }
  
-@@ -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.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 @@
  
    ~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 @@
  #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,19 +214,19 @@
  
  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);
@@ -237,10 +233,10 @@
  
  #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 @@
  #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,7 +286,7 @@
    GfxState *state;
    int i;
  
-@@ -504,5 +504,5 @@
+@@ -550,5 +550,5 @@
      ctm[i] = state->getCTM()[i];
    }
    delete state;
@@ -297,9 +293,9 @@
 -}
  #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 @@
  #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);

Modified: trunk/Build/source/libs/xpdf/configure
===================================================================
--- trunk/Build/source/libs/xpdf/configure	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/configure	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 at tug.org>.
 #
@@ -610,8 +610,8 @@
 # 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 at tug.org'
 PACKAGE_URL=''
 
@@ -1324,7 +1324,7 @@
   # 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 @@
 
 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 @@
 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 @@
 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 @@
 
 # Define the identity of the package.
  PACKAGE='xpdf--tex-live-'
- VERSION='4.03'
+ VERSION='4.04'
 
 
 # Some tools Automake needs.
@@ -7419,7 +7419,7 @@
 # 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 @@
 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\\"
 

Modified: trunk/Build/source/libs/xpdf/version.ac
===================================================================
--- trunk/Build/source/libs/xpdf/version.ac	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/version.ac	2022-04-24 03:42:26 UTC (rev 63119)
@@ -8,4 +8,4 @@
 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])

Modified: trunk/Build/source/libs/xpdf/xpdf-src/ANNOUNCE
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/ANNOUNCE	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/ANNOUNCE	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/CHANGES
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/CHANGES	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/CHANGES	2022-04-24 03:42:26 UTC (rev 63119)
@@ -2740,3 +2740,73 @@
   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.]

Modified: trunk/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/CMakeLists.txt	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
   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)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/INSTALL
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/INSTALL	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/INSTALL	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 at xpdfreader.com
 WWW: http://www.xpdfreader.com/
@@ -33,7 +33,7 @@
 
     - 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)
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/README
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/README	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/README	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 at xpdfreader.com
 WWW: http://www.xpdfreader.com/
@@ -154,6 +154,7 @@
 * 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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/cmake-config.txt
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/cmake-config.txt	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/cmake-config.txt	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 
 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 @@
 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 @@
 
 
 #--- 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 @@
   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 @@
       set(EXTRA_QT_LIBRARIES "")
     endif ()
   endif ()
-else()
+else ()
   message(STATUS "No Qt library found")
-endif()
+endif ()
 
 #--- look for libpaper
 find_library(PAPER_LIBRARY

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfdetach.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 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 @@
 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 @@
        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 @@
 
 
 
-                                  28 Jan 2021                     pdfdetach(1)
+                                  18 Apr 2022                     pdfdetach(1)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdffonts.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -3,7 +3,7 @@
 
 
 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 @@
 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 @@
        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 @@
 
 
 
-                                  28 Jan 2021                      pdffonts(1)
+                                  18 Apr 2022                      pdffonts(1)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfimages.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 NAME
        pdfimages  -  Portable  Document  Format (PDF) image extractor (version
-       4.03)
+       4.04)
 
 SYNOPSIS
        pdfimages [options] PDF-file image-root
@@ -26,9 +26,9 @@
 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 @@
        -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 @@
        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)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdfinfo.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 NAME
        pdfinfo - Portable Document Format (PDF) document information extractor
-       (version 4.03)
+       (version 4.04)
 
 SYNOPSIS
        pdfinfo [options] [PDF-file]
@@ -40,9 +40,9 @@
 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 @@
        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 @@
 
 
 
-                                  28 Jan 2021                       pdfinfo(1)
+                                  18 Apr 2022                       pdfinfo(1)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 \'-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 @@
 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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftohtml.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 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 @@
 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 @@
               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 @@
        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 @@
 
 
 
-                                  28 Jan 2021                     pdftohtml(1)
+                                  18 Apr 2022                     pdftohtml(1)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftopng.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 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 @@
 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 @@
        -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 @@
        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)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftoppm.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 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 @@
 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 @@
        -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 @@
        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)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftops.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 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 @@
 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 @@
        -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 @@
        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)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 .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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/pdftotext.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -4,7 +4,7 @@
 
 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 @@
 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 @@
               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 @@
        -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 @@
 
        -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 @@
        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 @@
 
 
 
-                                  28 Jan 2021                     pdftotext(1)
+                                  18 Apr 2022                     pdftotext(1)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.1	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 .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 @@
 .BI help
 Open the help URL.
 .TP
+.B hideMenuBar
+Hide the menu bar.
+.TP
 .B hideToolbar
 Hide the toolbar.
 .TP
@@ -591,6 +594,25 @@
 .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 @@
 .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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdf.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -3,7 +3,7 @@
 
 
 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 @@
 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 @@
 
        help   Open the help URL.
 
+       hideMenuBar
+              Hide the menu bar.
+
        hideToolbar
               Hide the toolbar.
 
@@ -538,6 +541,18 @@
        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 @@
               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 @@
        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 @@
        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 @@
 
 
 
-                                  28 Jan 2021                          xpdf(1)
+                                  18 Apr 2022                          xpdf(1)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.5	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 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 @@
 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 @@
 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 @@
 .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 @@
 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),

Modified: trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/doc/xpdfrc.cat	2022-04-24 03:42:26 UTC (rev 63119)
@@ -3,16 +3,20 @@
 
 
 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
        ignored.
@@ -385,8 +389,14 @@
               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,97 +405,102 @@
 
 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
@@ -492,17 +507,17 @@
        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 @@
               "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 @@
               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 @@
               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 @@
               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 @@
               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 @@
               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 @@
                   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 @@
               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 @@
 
 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 @@
 
 
 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 @@
               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 @@
 
 
 
-                                  28 Jan 2021                        xpdfrc(5)
+                                  18 Apr 202                         xpdfrc(5)

Modified: trunk/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/fofi/CMakeLists.txt	2022-04-24 03:42:26 UTC (rev 63119)
@@ -20,6 +20,8 @@
   FoFiType1.cc
   FoFiType1C.cc
 )
+set_property(TARGET fofi_objs
+             PROPERTY POSITION_INDEPENDENT_CODE True)
 
 add_library(fofi
   $<TARGET_OBJECTS:fofi_objs>

Modified: trunk/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -405,7 +405,9 @@
   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 @@
   }
   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 @@
   }
   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 @@
   }
   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());

Modified: trunk/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/goo/CMakeLists.txt	2022-04-24 03:42:26 UTC (rev 63119)
@@ -22,6 +22,8 @@
   parseargs.c
   Trace.cc
 )
+set_property(TARGET goo_objs
+             PROPERTY POSITION_INDEPENDENT_CODE True)
 
 add_library(goo
   $<TARGET_OBJECTS:goo_objs>

Modified: trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -54,16 +54,23 @@
   //---------- 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 @@
 
 #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 @@
 #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 @@
 #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 @@
     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 @@
 
 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);

Modified: trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/goo/gfile.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 // 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 @@
 // 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().

Modified: trunk/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt	2022-04-24 03:42:26 UTC (rev 63119)
@@ -40,6 +40,8 @@
     SplashXPathScanner.cc
     ${DTYPE_SRCS}
   )
+  set_property(TARGET splash_objs
+               PROPERTY POSITION_INDEPENDENT_CODE True)
 
   add_library(splash
     $<TARGET_OBJECTS:splash_objs>

Modified: trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -469,6 +469,12 @@
 
     if (pipe->noTransparency && !state->blendFunc) {
 
+      //----- handle overprint
+
+      if (overprintMaskPtr) {
+	*overprintMaskPtr++ = 0xffffffff;
+      }
+
       //----- result color
 
       switch (bitmap->mode) {
@@ -650,7 +656,19 @@
 	// 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 @@
 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 @@
 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 @@
 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 @@
     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 @@
     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::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::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::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 @@
   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 @@
   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 @@
 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,6 +5941,7 @@
 
   //--- 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;
@@ -5769,23 +5948,29 @@
   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)
     int yy = splashRound(mat[5]);
@@ -5860,7 +6045,7 @@
   if (clipRes == splashClipAllInside) {
     drawRowFunc = &Splash::drawImageMaskRowNoClip;
   } else {
-    if (vectorAntialias) {
+    if (antialias) {
       drawRowFunc = &Splash::drawImageMaskRowClipAA;
     } else {
       drawRowFunc = &Splash::drawImageMaskRowClipNoAA;
@@ -5873,7 +6058,7 @@
       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 @@
       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 @@
     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 @@
     }
 
     // draw it
-    if (interpolate) {
+    if (interpolate && antialias) {
       drawImageMaskArbitraryInterp(scaledMask,
 				   &dd, drawRowFunc, invMat,
 				   scaledWidth, scaledHeight,
@@ -6259,6 +6488,7 @@
 
   //--- 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;
@@ -6265,23 +6495,29 @@
   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)
     int yy = splashRound(mat[5]);
@@ -6435,6 +6671,83 @@
       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 @@
 				    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 @@
 			    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;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/splash/Splash.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -182,12 +182,13 @@
 			 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 @@
   //    [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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -63,6 +63,21 @@
   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 @@
     cmykTransferK[i] = (Guchar)i;
 #endif
   }
+  transferIsShared = gFalse;
   overprintMask = 0xffffffff;
   enablePathSimplification = gFalse;
   next = NULL;
@@ -110,6 +126,21 @@
   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 @@
     cmykTransferK[i] = (Guchar)i;
 #endif
   }
+  transferIsShared = gFalse;
   overprintMask = 0xffffffff;
   enablePathSimplification = gFalse;
   next = NULL;
@@ -156,16 +188,17 @@
   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 @@
   if (!clipIsShared) {
     delete clip;
   }
+  if (!transferIsShared) {
+    gfree(rgbTransferR);
+  }
   if (deleteSoftMask && softMask) {
     delete softMask;
   }
@@ -265,12 +301,12 @@
 			  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 @@
   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);

Modified: trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -81,7 +81,7 @@
   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 @@
   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;
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
   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();

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -224,6 +224,11 @@
     }
   }
   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 ||

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CMakeLists.txt	2022-04-24 03:42:26 UTC (rev 63119)
@@ -23,6 +23,11 @@
 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 @@
   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 @@
     TileMap.cc
     ${HIGHLIGHT_SRC}
   )
+  set_property(TARGET xpdf_widget_objs
+               PROPERTY POSITION_INDEPENDENT_CODE True)
 endif ()
 
 #--- pdftops
@@ -107,6 +116,7 @@
     ShadingImage.cc
     SplashOutputDev.cc
     pdftops.cc
+    ${MANIFEST}
   )
   target_link_libraries(pdftops goo fofi splash
                         ${PAPER_LIBRARY}
@@ -121,6 +131,7 @@
     PreScanOutputDev.cc
     PSOutputDev.cc
     pdftops.cc
+    ${MANIFEST}
   )
   target_link_libraries(pdftops goo fofi
                         ${PAPER_LIBRARY}
@@ -137,6 +148,7 @@
   $<TARGET_OBJECTS:xpdf_objs>
   TextOutputDev.cc
   pdftotext.cc
+  ${MANIFEST}
 )
 target_link_libraries(pdftotext goo fofi
                       ${PAPER_LIBRARY}
@@ -157,6 +169,7 @@
     TextOutputDev.cc
     WebFont.cc
     pdftohtml.cc
+    ${MANIFEST}
   )
   target_link_libraries(pdftohtml goo fofi splash
                         ${PAPER_LIBRARY}
@@ -175,6 +188,7 @@
 add_executable(pdfinfo
   $<TARGET_OBJECTS:xpdf_objs>
   pdfinfo.cc
+  ${MANIFEST}
 )
 target_link_libraries(pdfinfo goo fofi
                       ${PAPER_LIBRARY}
@@ -189,6 +203,7 @@
 add_executable(pdffonts
   $<TARGET_OBJECTS:xpdf_objs>
   pdffonts.cc
+  ${MANIFEST}
 )
 target_link_libraries(pdffonts goo fofi
                       ${PAPER_LIBRARY}
@@ -203,6 +218,7 @@
 add_executable(pdfdetach
   $<TARGET_OBJECTS:xpdf_objs>
   pdfdetach.cc
+  ${MANIFEST}
 )
 target_link_libraries(pdfdetach goo fofi
                       ${PAPER_LIBRARY}
@@ -220,6 +236,7 @@
     ShadingImage.cc
     SplashOutputDev.cc
     pdftoppm.cc
+    ${MANIFEST}
   )
   target_link_libraries(pdftoppm goo fofi splash
                         ${PAPER_LIBRARY}
@@ -240,6 +257,7 @@
     ShadingImage.cc
     SplashOutputDev.cc
     pdftopng.cc
+    ${MANIFEST}
   )
   target_link_libraries(pdftopng goo fofi splash
                         ${PAPER_LIBRARY}
@@ -259,6 +277,7 @@
   $<TARGET_OBJECTS:xpdf_objs>
   ImageOutputDev.cc
   pdfimages.cc
+  ${MANIFEST}
 )
 target_link_libraries(pdfimages goo fofi
                       ${PAPER_LIBRARY}

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -623,7 +623,7 @@
     // 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()) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -232,6 +232,10 @@
   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,13 +474,8 @@
 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.
@@ -483,11 +482,9 @@
     // (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 @@
       map[i] = 0;
     }
   }
-#if 1 //~utf16
   if (uLen == 1) {
     map[code] = u[0] + offset;
   } else {
@@ -517,34 +513,6 @@
     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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -49,6 +49,11 @@
   // 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);
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -527,6 +527,7 @@
   xref = doc->getXRef();
   subPage = gFalse;
   printCommands = globalParams->getPrintCommands();
+  defaultFont = NULL;
 
   // start the resource stack
   res = new GfxResources(xref, resDict, NULL);
@@ -574,6 +575,7 @@
   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() {
+  if (defaultFont) {
+    delete defaultFont;
+  }
   if (!subPage) {
     out->endPage();
   }
@@ -2080,12 +2085,19 @@
   // 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::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 @@
     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::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 @@
     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 (!obj1.isStream()) {
+  if (!refObj.fetch(xref, &xObj)) {
+    refObj.free();
+    return;
+  }
+  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 @@
   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 @@
 #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 @@
     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 @@
 
     // 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 @@
 	goto err1;
       }
       maskStr = smaskObj.getStream();
+      maskStr->disableDecompressionBombChecking();
       maskDict = smaskObj.streamGetDict();
       maskDict->lookup("Width", &obj1);
       if (obj1.isNull()) {
@@ -4487,6 +4519,7 @@
 	goto err1;
       }
       maskStr = maskObj.getStream();
+      maskStr->disableDecompressionBombChecking();
       maskDict = maskObj.streamGetDict();
       maskDict->lookup("Width", &obj1);
       if (obj1.isNull()) {
@@ -4559,6 +4592,7 @@
 	      " 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 @@
     // 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,7 +4688,7 @@
 
   // 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;
@@ -4661,6 +4695,11 @@
   }
   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 @@
 
   // 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 @@
     groupAttrsObj.free();
     strObj.free();
 
-    traceBegin(oldBaseMatrix, softMask ? "begin soft mask" : "begin t-group");
-    if (state->getBlendMode() != gfxBlendNormal) {
-      state->setBlendMode(gfxBlendNormal);
-      out->updateBlendMode(state);
+    if (!out->beginTransparencyGroup(state, bbox, blendingColorSpace,
+				     isolated, knockout, softMask)) {
+      transpGroup = gFalse;
     }
-    if (state->getFillOpacity() != 1) {
-      state->setFillOpacity(1);
-      out->updateFillOpacity(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);
     }
-    if (state->getStrokeOpacity() != 1) {
-      state->setStrokeOpacity(1);
-      out->updateStrokeOpacity(state);
-    }
-    out->clearSoftMask(state);
-    out->beginTransparencyGroup(state, bbox, blendingColorSpace,
-				isolated, knockout, softMask);
   }
 
   // set new base matrix

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -188,6 +188,7 @@
   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)
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -198,6 +198,27 @@
   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 @@
   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 @@
     }
   }
 
-  // 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 @@
   }
 }
 
+// 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) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -135,6 +135,10 @@
   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 @@
 
 private:
 
+  void readTrueTypeUnicodeMapping(XRef *xref);
   void getHorizontalMetrics(CID cid, double *w);
   void getVerticalMetrics(CID cid, double *h,
 			  double *vx, double *vy);
@@ -398,9 +403,11 @@
 
 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
 				//   two tags map to the same font

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -2071,6 +2071,7 @@
   Function *funcsA[gfxColorMaxComps];
   int nFuncsA;
   Object obj1, obj2;
+  GBool ok;
   int i;
 
   x0A = y0A = 0;
@@ -2139,14 +2140,21 @@
     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 @@
   double t0A, t1A;
   Function *funcsA[gfxColorMaxComps];
   int nFuncsA;
-  GBool extend0A, extend1A;
+  GBool extend0A, extend1A, ok;
   Object obj1, obj2;
   int i;
 
@@ -2319,14 +2327,21 @@
     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 @@
   double t0A, t1A;
   Function *funcsA[gfxColorMaxComps];
   int nFuncsA;
-  GBool extend0A, extend1A;
+  GBool extend0A, extend1A, ok;
   Object obj1, obj2;
   int i;
 
@@ -2501,14 +2516,21 @@
     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 @@
   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 @@
     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 @@
   Guint ci;
   GfxShadingBitBuf *bitBuf;
   Object obj1, obj2;
+  GBool ok;
   int i, j;
 
   nPatchesA = 0;
@@ -3555,14 +3588,23 @@
     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 @@
     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,66 +4643,144 @@
 }
 
 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;
+  double xx, yy;
+  transform(xMin, yMin, &xx, &yy);
+  if (xx < clipXMin) {
+    clipXMin = xx;
+  } else if (xx > clipXMax) {
+    clipXMax = xx;
   }
-  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 (yy < clipYMin) {
+    clipYMin = yy;
+  } else if (yy > clipYMax) {
+    clipYMax = yy;
   }
-
-  if (xMin > clipXMin) {
-    clipXMin = xMin;
+  transform(xMin, yMax, &xx, &yy);
+  if (xx < clipXMin) {
+    clipXMin = xx;
+  } else if (xx > clipXMax) {
+    clipXMax = xx;
   }
-  if (yMin > clipYMin) {
-    clipYMin = yMin;
+  if (yy < clipYMin) {
+    clipYMin = yy;
+  } else if (yy > clipYMax) {
+    clipYMax = yy;
   }
-  if (xMax < clipXMax) {
-    clipXMax = xMax;
+  transform(xMax, yMin, &xx, &yy);
+  if (xx < clipXMin) {
+    clipXMin = xx;
+  } else if (xx > clipXMax) {
+    clipXMax = xx;
   }
-  if (yMax < clipYMax) {
-    clipYMax = yMax;
+  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;
+  }
 }
 
 void GfxState::clipToRect(double xMin, double yMin, double xMax, double yMax) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -1076,6 +1076,10 @@
   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);
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -5,9 +5,6 @@
 // Copyright 2001-2003 Glyph & Cog, LLC
 //
 //========================================================================
-//  Modified for TeX Live by Peter Breitenlohner <tex-live at tug.org>
-//  See top-level ChangeLog for a list of all modifications
-//========================================================================
 
 #include <aconf.h>
 
@@ -219,7 +216,7 @@
   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 *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 @@
   disableFreeTypeHinting = gFalse;
   antialias = gTrue;
   vectorAntialias = gTrue;
+  imageMaskAntialias = gTrue;
   antialiasPrinting = gFalse;
   strokeAdjust = strokeAdjustNormal;
   screenType = screenUnset;
@@ -741,6 +741,7 @@
   enablePathSimplification = gFalse;
   drawAnnotations = gTrue;
   drawFormFields = gTrue;
+  enableXFA = gTrue;
   overprintPreview = gFalse;
   paperColor = new GString("#ffffff");
   matteColor = new GString("#808080");
@@ -753,11 +754,14 @@
   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 @@
     } 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 @@
     } 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 @@
       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 @@
       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 @@
       } 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 @@
   deleteGList(keyBindings, KeyBinding);
   deleteGList(popupMenuCmds, PopupMenuCmd);
   delete tabStateFile;
+  delete debugLogFile;
 
   cMapDirs->startIter(&iter);
   while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
@@ -3060,6 +3077,15 @@
   return f;
 }
 
+GBool GlobalParams::getImageMaskAntialias() {
+  GBool f;
+
+  lockGlobalParams;
+  f = imageMaskAntialias;
+  unlockGlobalParams;
+  return f;
+}
+
 GBool GlobalParams::getAntialiasPrinting() {
   GBool f;
 
@@ -3168,8 +3194,17 @@
   return draw;
 }
 
+GBool GlobalParams::getEnableXFA() {
+  GBool xfa;
 
+  lockGlobalParams;
+  xfa = enableXFA;
+  unlockGlobalParams;
+  return xfa;
+}
 
+
+
 GString *GlobalParams::getPaperColor() {
   GString *s;
 
@@ -3251,6 +3286,15 @@
   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 @@
   return s;
 }
 
+GBool GlobalParams::getSavePageNumbers() {
+  GBool s;
+
+  lockGlobalParams;
+  s = savePageNumbers;
+  unlockGlobalParams;
+  return s;
+}
+
 GBool GlobalParams::getPrintCommands() {
   GBool p;
 
@@ -3330,6 +3383,15 @@
   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 @@
   unlockGlobalParams;
 }
 
+void GlobalParams::setPrintStatusInfo(GBool printStatusInfoA) {
+  lockGlobalParams;
+  printStatusInfo = printStatusInfoA;
+  unlockGlobalParams;
+}
+
 void GlobalParams::setErrQuiet(GBool errQuietA) {
   lockGlobalParams;
   errQuiet = errQuietA;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -316,6 +316,7 @@
   GBool getDisableFreeTypeHinting();
   GBool getAntialias();
   GBool getVectorAntialias();
+  GBool getImageMaskAntialias();
   GBool getAntialiasPrinting();
   StrokeAdjustMode getStrokeAdjust();
   ScreenType getScreenType();
@@ -328,6 +329,7 @@
   GBool getEnablePathSimplification();
   GBool getDrawAnnotations();
   GBool getDrawFormFields();
+  GBool getEnableXFA();
   GBool getOverprintPreview() { return overprintPreview; }
   GString *getPaperColor();
   GString *getMatteColor();
@@ -340,6 +342,7 @@
   GBool getMapNumericCharNames();
   GBool getMapUnknownCharNames();
   GBool getMapExtTrueTypeFontsViaUnicode();
+  GBool getUseTrueTypeUnicodeMapping();
   GBool isDroppedFont(const char *fontName);
   GList *getKeyBinding(int code, int mods, int context);
   GList *getAllKeyBindings();
@@ -346,7 +349,9 @@
   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 @@
   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 @@
   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 @@
     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 @@
   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
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 @@
 
 //------------------------------------------------------------------------
 
+class HTMLGenFormFieldInfo {
+public:
 
+  HTMLGenFormFieldInfo(AcroFormField *acroFormFieldA)
+    : acroFormField(acroFormFieldA) {}
+
+  AcroFormField *acroFormField;
+};
+
 //------------------------------------------------------------------------
 
-HTMLGen::HTMLGen(double backgroundResolutionA) {
+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, GBool tableMode) {
   TextOutputControl textOutControl;
   SplashColor paperColor;
 
@@ -207,12 +290,16 @@
 
   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 @@
 }
 
 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 @@
 
   // 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,6 +414,71 @@
   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");
@@ -351,6 +485,15 @@
   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 @@
     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 @@
   } 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 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, "<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, "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 @@
 	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 @@
   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 @@
 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;
+	  }
 	}
-      } else {
-	sp = word1->getSpaceAfter();
-      }
-      if (sp) {
-	s->append(' ');
-      }
-    }
+	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,13 +955,32 @@
   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);
@@ -707,15 +987,31 @@
       ++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);
@@ -722,8 +1018,6 @@
       ++nextFontFaceIdx;
       fontDefn = new HTMLGenFontDefn(id, fontFace, fontSpec, 1.0);
     }
-    delete fontPath;
-    delete fontFile;
   }
 
   delete webFont;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -2,7 +2,7 @@
 //
 // HTMLGen.h
 //
-// Copyright 2010 Glyph & Cog, LLC
+// Copyright 2010-2021 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -27,7 +27,7 @@
 class HTMLGen {
 public:
 
-  HTMLGen(double backgroundResolutionA);
+  HTMLGen(double backgroundResolutionA, GBool tableMode);
   ~HTMLGen();
 
   GBool isOk() { return ok; }
@@ -39,6 +39,8 @@
   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 @@
   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 @@
 
   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 @@
   GList *fontDefns;		// [HTMLGenFontDefn]
   int nextFontFaceIdx;
 
+  TextFontInfo *formFieldFont;
+  GList *formFieldInfo;		// [HTMLGenFormFieldInfo]
+  int nextFieldID;
+
   GBool ok;
 };
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -1147,6 +1147,7 @@
 JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
   FilterStream(strA)
 {
+  decoded = gFalse;
   pageBitmap = NULL;
 
   arithDecoder = new JArithmeticDecoder();
@@ -1205,40 +1206,9 @@
 }
 
 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 @@
 }
 
 int JBIG2Stream::getChar() {
+  if (!decoded) {
+    decodeImage();
+  }
   if (dataPtr && dataPtr < dataEnd) {
     return (*dataPtr++ ^ 0xff) & 0xff;
   }
@@ -1266,6 +1239,9 @@
 }
 
 int JBIG2Stream::lookChar() {
+  if (!decoded) {
+    decodeImage();
+  }
   if (dataPtr && dataPtr < dataEnd) {
     return (*dataPtr ^ 0xff) & 0xff;
   }
@@ -1275,6 +1251,9 @@
 int JBIG2Stream::getBlock(char *blk, int size) {
   int n, i;
 
+  if (!decoded) {
+    decodeImage();
+  }
   if (size <= 0) {
     return 0;
   }
@@ -1298,6 +1277,42 @@
   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 @@
   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 @@
   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;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -48,6 +48,7 @@
 
 private:
 
+  void decodeImage();
   void readSegments();
   GBool readSymbolDictSeg(Guint segNum, Guint length,
 			  Guint *refSegs, Guint nRefSegs);
@@ -117,6 +118,7 @@
   GBool readULong(Guint *x);
   GBool readLong(int *x);
 
+  GBool decoded;
   Object globalsStream;
   Guint pageW, pageH, curPageH;
   Guint pageDefPixel;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -230,6 +230,7 @@
 {
   bufStr = new BufStream(str, 3);
 
+  decoded = gFalse;
   nComps = 0;
   bpc = NULL;
   width = height = 0;
@@ -270,15 +271,7 @@
 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 @@
   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::lookChar() {
   int c;
 
+  if (!decoded) {
+    decodeImage();
+  }
   if (readBufLen < 8) {
     fillReadBuf();
   }
@@ -420,10 +432,18 @@
 #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 @@
 	    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 @@
 	    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 @@
 	    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 @@
 	    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 @@
   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 @@
     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 @@
       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 @@
 	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 @@
 
   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 @@
     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;
     }
   }

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -202,6 +202,7 @@
 
   //----- 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 @@
   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 @@
 
 private:
 
+  void decodeImage();
   void fillReadBuf();
   void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode);
   JPXDecodeResult readBoxes();
@@ -329,6 +333,7 @@
 
   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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -229,10 +229,10 @@
   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,

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -421,7 +421,15 @@
   }
 
   // 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 @@
 
   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) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -125,11 +125,11 @@
   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,19 +166,18 @@
 
 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);
@@ -185,14 +184,14 @@
 
 #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 @@
   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::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;
   }

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -162,6 +162,10 @@
   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();
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -1481,6 +1481,7 @@
   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 @@
     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 @@
   }
 
   // filters
+  str->disableDecompressionBombChecking();
   if (level < psLevel2) {
     useLZW = useRLE = gFalse;
     useCompressed = gFalse;
@@ -4265,6 +4272,7 @@
       }
       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 @@
 	processColors |= psProcessBlack;
       }
       break;
+      // if !SPLASH_CMYK: fall through
+#endif
     case psLevel2:
     case psLevel2Gray:
     case psLevel2Sep:
@@ -4510,7 +4520,7 @@
     } else if ((globalParams->getPSShrinkLarger() &&
 		(width * userUnit > imgWidth2 ||
 		 height * userUnit > imgHeight2)) ||
-	       (globalParams->getPSExpandSmaller() &&
+	       (expandSmallPages &&
 		(width * userUnit < imgWidth2 &&
 		 height * userUnit < imgHeight2))) {
       xScale = (double)imgWidth2 / (double)width;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -264,6 +264,8 @@
     { 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 @@
   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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -64,7 +64,7 @@
 // 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 @@
     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 @@
     cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
     haveCropBox = gFalse;
     rotate = 0;
-    resources.initNull();
   }
 
   // media box
@@ -137,12 +135,59 @@
   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 @@
   metadata.initNull();
   pieceInfo.initNull();
   separationInfo.initNull();
+  userUnit = 1;
   resources.initNull();
 }
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -46,7 +46,7 @@
   // 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).

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -152,36 +152,35 @@
 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,48 +188,79 @@
   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)
+      Object obj;
+      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)
-    dict->copy(&obj);
-    delete str;
-    length += 5000;
-    str = baseStr->makeSubStream(pos, gTrue, length, &obj);
-  }
 
   // free the copied base stream
   delete baseStr;
@@ -237,8 +267,25 @@
 
   // 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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -248,13 +248,14 @@
   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,

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -103,10 +103,10 @@
 				   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
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -203,18 +203,15 @@
 	    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();
       }

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -1882,10 +1882,10 @@
     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 @@
     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,11 +1957,66 @@
   } 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;
   origSplash = splash;
@@ -2068,8 +2091,8 @@
   } 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 @@
   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 @@
 		     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 @@
     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::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 @@
     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 @@
   state->shiftCTM(-tx, -ty);
   updateCTM(state, 0, 0, 0, 0, 0, 0);
   ++nestCount;
+
+  return gTrue;
 }
 
 void SplashOutputDev::endTransparencyGroup(GfxState *state) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -167,10 +167,10 @@
 		       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,

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -52,6 +52,14 @@
 #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 @@
   } 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, &params2, recursion);
       else
 	params2.initNull();
@@ -305,6 +313,8 @@
     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 @@
 }
 
 void ImageStream::reset() {
+  str->disableDecompressionBombChecking();
   str->reset();
 }
 
@@ -935,7 +946,11 @@
   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 @@
   eof = gFalse;
   inputBits = 0;
   clearTable();
+  checkForDecompressionBombs = gTrue;
 }
 
 LZWStream::~LZWStream() {
@@ -1240,6 +1256,11 @@
   }
 }
 
+void LZWStream::disableDecompressionBombChecking() {
+  checkForDecompressionBombs = gFalse;
+  FilterStream::disableDecompressionBombChecking();
+}
+
 int LZWStream::getChar() {
   if (pred) {
     return pred->getChar();
@@ -1386,8 +1407,10 @@
   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 @@
     FilterStream(strA) {
   int i;
 
+  prepared = gFalse;
   colorXform = colorXformA;
   progressive = interleaved = gFalse;
   width = height = 0;
@@ -2683,6 +2707,7 @@
     // force an EOF condition
     progressive = gTrue;
     y = height;
+    prepared = gTrue;
     return;
   }
 
@@ -2719,56 +2744,7 @@
     }
   }
 
-  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 @@
 int DCTStream::getChar() {
   int c;
 
+  if (!prepared) {
+    prepare();
+  }
   if (progressive || !interleaved) {
     if (y >= height) {
       return EOF;
@@ -2837,6 +2816,9 @@
 }
 
 int DCTStream::lookChar() {
+  if (!prepared) {
+    prepare();
+  }
   if (progressive || !interleaved) {
     if (y >= height) {
       return EOF;
@@ -2859,6 +2841,9 @@
 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 @@
   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 @@
       if (!readScanInfo()) {
 	return gFalse;
       }
+      if (frame) {
+	interleaved = scanInfo.numComps == numComps;
+      }
       doScan = gTrue;
       break;
     case 0xdb:			// DQT
@@ -4006,7 +4064,6 @@
     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 @@
   litCodeTab.codes = NULL;
   distCodeTab.codes = NULL;
   memset(buf, 0, flateWindow);
+  checkForDecompressionBombs = gTrue;
 }
 
 FlateStream::~FlateStream() {
@@ -4936,6 +4994,11 @@
   }
 }
 
+void FlateStream::disableDecompressionBombChecking() {
+  checkForDecompressionBombs = gFalse;
+  FilterStream::disableDecompressionBombChecking();
+}
+
 void FlateStream::reset() {
   int cmf, flg;
 
@@ -5198,7 +5261,9 @@
   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 @@
       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;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -80,6 +80,13 @@
 
   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 @@
 
   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 @@
   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 @@
   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 @@
 
 #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 @@
   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 @@
   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 @@
   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
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -58,28 +58,43 @@
 // 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
+// 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
 
-// Vertical gap threshold for table mode.
-#define vertGapThresholdTableMin 0.2
-#define vertGapThresholdTableMax 0.5
-#define vertGapThresholdTableSlope -0.02
-
 // 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
 // shadows) which is to be discarded.
@@ -257,6 +272,16 @@
   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 @@
 }
 
 //------------------------------------------------------------------------
+// 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() {
+  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 @@
     }
   }
 
-  // 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 @@
   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::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 @@
       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 @@
 	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 @@
 	}
       }
 
-    } 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 @@
   }
 }
 
+// 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 @@
 	}
       }
       if (chars2->getLength() > 0) {
-	tree[rot] = split(chars2, rot);
+	tree[rot] = split(chars2, rot, gFalse);
       }
     }
     delete chars2;
@@ -3457,26 +3610,29 @@
 }
 
 // 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 @@
 
   //----- 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);
     }
-  } else if (control.mode == textOutSimpleLayout) {
-    vertGapThreshold = simpleLayoutGapThreshold;
+    if (minGapSize * avgFontSize > gapThreshold) {
+      gapThreshold = minGapSize * avgFontSize;
+    }
+    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 @@
   }
 
   // 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 @@
       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 @@
       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 @@
 	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 @@
   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 @@
 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, and average font size
 
-  //----- compute bbox, min font size, average font size, and split precision
-
-  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 @@
     }
   }
   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;
+  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 (y = yMinI2; y <= yMaxI2; ++y) {
-      horizProfile[y - yMinI] = 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;
+      }
     }
-    for (x = xMinI2; x <= xMaxI2; ++x) {
-      vertProfile[x - xMinI] = 1;
-    }
   }
 
-  //----- 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 @@
   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 @@
 	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 @@
   }
 }
 
-// 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 @@
   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 @@
 
   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 @@
 	  continue;
 	}
 
-	// convert the line to uppercase
+	// convert the line to lowercase
 	m = line->len;
 	if (!caseSensitive) {
 	  if (m > txtSize) {
@@ -5222,7 +5709,7 @@
 	    txtSize = m;
 	  }
 	  for (k = 0; k < m; ++k) {
-	    txt[k] = unicodeToUpper(line->text[k]);
+	    txt[k] = unicodeToLower(line->text[k]);
 	  }
 	} else {
 	  txt = line->text;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -99,7 +99,12 @@
 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 @@
   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 @@
   // 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 @@
 		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 @@
   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 @@
   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);

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -786,17 +786,18 @@
     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 @@
     } 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:

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMapTables.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -11,8 +11,7 @@
   { 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 @@
   { 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 @@
   { 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 },

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -83,7 +83,7 @@
 }
 
 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 @@
       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 @@
   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;
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -43,6 +43,8 @@
 
 private:
 
+  int findSMap(Unicode u);
+
   Unicode page0[256];
   UnicodeRemappingString *sMap;
   int sMapLen, sMapSize;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -2,7 +2,7 @@
 //
 // UnicodeTypeTable.cc
 //
-// Copyright 2004-2013 Glyph & Cog, LLC
+// Copyright 2004-2021 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -25,54 +25,54 @@
   { "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' },
+  { "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' },
-  { NULL, 'L' },
-  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
-  { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL.LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' },
-  { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
-  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNNNLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { 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' },
+  { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
   { NULL, 'N' },
-  { 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 @@
   { NULL, 'L' },
   { NULL, 'L' },
   { NULL, 'L' },
-  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
+  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' },
   { NULL, 'L' },
   { NULL, 'L' },
   { NULL, 'L' },
@@ -188,6 +188,12 @@
   { NULL, 'L' },
   { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
   { NULL, 'L' },
+  { "LLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLNNNNNNNN", 'X' },
+  { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
+  { "LLNLLLNLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNLLLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLN", 'X' },
+  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' },
+  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLNNLLNNLLLLLLLLLLLLNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLNNLLLLLNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLNLLLLLLLLL", 'X' },
+  { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNLLLLNLLLLLLLLLLLLLLLLLL", 'X' },
   { NULL, 'L' },
   { NULL, 'L' },
   { NULL, 'L' },
@@ -267,12 +273,6 @@
   { NULL, 'L' },
   { NULL, 'L' },
   { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
-  { NULL, 'L' },
   { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' },
   { NULL, 'R' },
   { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' },
@@ -356,9 +356,9 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   NULL,
   NULL,
   NULL,
+  &caseTable10,
   NULL,
   NULL,
+  &caseTable13,
   NULL,
   NULL,
   NULL,
@@ -681,10 +921,8 @@
   NULL,
   NULL,
   NULL,
+  &caseTable1c,
   NULL,
-  NULL,
-  NULL,
-  NULL,
   &caseTable1e,
   &caseTable1f,
   NULL,
@@ -699,6 +937,7 @@
   NULL,
   NULL,
   NULL,
+  &caseTable2c,
   NULL,
   NULL,
   NULL,
@@ -820,9 +1059,12 @@
   NULL,
   NULL,
   NULL,
+  &caseTablea6,
+  &caseTablea7,
   NULL,
   NULL,
   NULL,
+  &caseTableab,
   NULL,
   NULL,
   NULL,
@@ -906,11 +1148,640 @@
   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 @@
   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 @@
   return t == 'L' || t == 'R' || t == '#';
 }
 
-Unicode unicodeToUpper(Unicode c) {
+Unicode unicodeToLower(Unicode c) {
   int i;
 
   if (c > 0xffff) {
@@ -970,3 +1849,28 @@
   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;
+}
+

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -15,6 +15,10 @@
 
 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);
@@ -21,6 +25,8 @@
 
 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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -71,8 +71,11 @@
   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 @@
   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 @@
       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 @@
   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;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -18,6 +18,7 @@
 #endif
 
 #include "gtypes.h"
+#include "FoFiBase.h"
 #include "GfxFont.h"
 
 class FoFiTrueType;
@@ -45,13 +46,23 @@
   // 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,

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -293,8 +293,10 @@
   }
 
   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")) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -299,6 +299,7 @@
 
   ok = gTrue;
   errCode = errNone;
+  repaired = gFalse;
   size = 0;
   last = -1;
   entries = NULL;
@@ -336,6 +337,7 @@
       errCode = errDamaged;
       return;
     }
+    repaired = gTrue;
 
   // if the 'repair' flag is not set, read the xref table
   } else {
@@ -512,7 +514,7 @@
   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 @@
     }
     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 @@
     } 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 @@
       }
       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 @@
       // 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 @@
 	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 @@
 
   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;

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -70,6 +70,9 @@
   // 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 @@
   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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/config.h
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/config.h	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/config.h	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -94,6 +94,10 @@
   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);

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -123,6 +123,10 @@
   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);
 

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -35,6 +35,7 @@
 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 @@
    "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 @@
   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);
   }

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -126,6 +126,10 @@
   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);

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -31,11 +31,17 @@
 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;
@@ -42,37 +48,49 @@
 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 @@
   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 @@
   }
 
   // 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 @@
       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 @@
 			       &writeToFile, pngFile);
     delete pngURL;
     fclose(htmlFile);
-    fclose(pngFile);
+    if (!embedBackground) {
+      fclose(pngFile);
+    }
     delete htmlFileName;
     delete pngFileName;
     if (err != errNone) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 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 @@
    "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 @@
   GString *ownerPW, *userPW;
   SplashColor paperColor;
   SplashOutputDev *splashOut;
-  GBool ok;
+  GBool ok, toStdout, printStatusInfo;
   int exitCode;
   int pg;
   png_structp png;
@@ -134,6 +138,10 @@
   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 @@
       fprintf(stderr, "Bad '-aaVector' value on command line\n");
     }
   }
+  if (verbose) {
+    globalParams->setPrintStatusInfo(verbose);
+  }
   if (quiet) {
     globalParams->setErrQuiet(quiet);
   }
@@ -185,6 +196,10 @@
     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 @@
   }
   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 @@
       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 @@
       finishPNG(&png, &pngInfo);
       fclose(f);
     } else { // RGB
-      if (!strcmp(pngRoot, "-")) {
+      if (toStdout) {
 	f = stdout;
 #ifdef _WIN32
 	_setmode(_fileno(f), _O_BINARY);

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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 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 @@
    "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 @@
   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 @@
   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 @@
       fprintf(stderr, "Bad '-aaVector' value on command line\n");
     }
   }
+  if (verbose) {
+    globalParams->setPrintStatusInfo(verbose);
+  }
   if (quiet) {
     globalParams->setErrQuiet(quiet);
   }
@@ -211,6 +222,10 @@
   }
 
 
+  // 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 @@
   }
   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

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -64,6 +64,7 @@
 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 @@
    "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 @@
   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 @@
     globalParams->setPSOPI(doOPI);
   }
 #endif
+  if (verbose) {
+    globalParams->setPrintStatusInfo(verbose);
+  }
   if (quiet) {
     globalParams->setErrQuiet(quiet);
   }
@@ -337,6 +347,9 @@
     }
     psFileName->append(doEPS ? ".eps" : ".ps");
   }
+  if (psFileName->cmp("-") == 0) {
+    globalParams->setPrintStatusInfo(gFalse);
+  }
 
   // get page range
   if (firstPage < 1) {

Modified: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc	2022-04-23 23:50:13 UTC (rev 63118)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc	2022-04-24 03:42:26 UTC (rev 63119)
@@ -58,6 +58,7 @@
 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 @@
   {"-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 @@
    "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 @@
   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 @@
   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 @@
   if (noPageBreaks) {
     globalParams->setTextPageBreaks(gFalse);
   }
+  if (verbose) {
+    globalParams->setPrintStatusInfo(verbose);
+  }
   if (quiet) {
     globalParams->setErrQuiet(quiet);
   }
@@ -247,6 +261,9 @@
     }
     textFileName->append(".txt");
   }
+  if (textFileName->cmp("-") == 0) {
+    globalParams->setPrintStatusInfo(gFalse);
+  }
 
   // get page range
   if (firstPage < 1) {

Added: trunk/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest
===================================================================
--- trunk/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest	                        (rev 0)
+++ trunk/Build/source/libs/xpdf/xpdf-src/xpdf/winLongPath.exe.manifest	2022-04-24 03:42:26 UTC (rev 63119)
@@ -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>



More information about the tex-live-commits mailing list.