diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2014-06-18 11:37:05 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2014-06-18 11:37:05 +0000 |
commit | b1882a1ef3ebf5ab4a1dc8010655c8d5def03b61 (patch) | |
tree | cb9161a5ae062e1fb48641a2a71f8dff00337ecb /Build/source | |
parent | 384d961843d060a692d21c4ea38f266171650f91 (diff) |
xpdf 3.04
git-svn-id: svn://tug.org/texlive/trunk@34281 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source')
-rw-r--r-- | Build/source/libs/xpdf/ChangeLog | 5 | ||||
-rw-r--r-- | Build/source/libs/xpdf/Makefile.am | 12 | ||||
-rw-r--r-- | Build/source/libs/xpdf/Makefile.in | 50 | ||||
-rw-r--r-- | Build/source/libs/xpdf/aconf.h.in | 3 | ||||
-rwxr-xr-x | Build/source/libs/xpdf/configure | 39 | ||||
-rw-r--r-- | Build/source/libs/xpdf/configure.ac | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/version.ac | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-30-include-strings_h | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-40-W32TeX | 28 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/ANNOUNCE | 45 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.cat | 115 | ||||
-rwxr-xr-x | Build/source/libs/xpdf/xpdf-3.03/ms_make.bat | 132 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.cc | 399 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.cc | 188 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.cc | 538 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.h | 95 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.in | 269 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.cc | 4330 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/ChangeLog (renamed from Build/source/libs/xpdf/xpdf-3.03-PATCHES/ChangeLog) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/TL-Changes | 6 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-10-exclude-body-of-Page_getDefaultCTM (renamed from Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-10-exclude-body-of-Page_getDefaultCTM) | 21 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-20-skip-reading-config-file (renamed from Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-20-skip-reading-config-file) | 20 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-22-exclude-openTempFile (renamed from Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-22-exclude-openTempFile) | 20 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-30-include-strings_h | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-40-W32TeX | 29 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04-foolabs/README (renamed from Build/source/libs/xpdf/xpdf-3.03-foolabs/README) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/ANNOUNCE | 33 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/CHANGES (renamed from Build/source/libs/xpdf/xpdf-3.03/CHANGES) | 174 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/COPYING (renamed from Build/source/libs/xpdf/xpdf-3.03/COPYING) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/COPYING3 (renamed from Build/source/libs/xpdf/xpdf-3.03/COPYING3) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/INSTALL (renamed from Build/source/libs/xpdf/xpdf-3.03/INSTALL) | 44 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/Makefile.in (renamed from Build/source/libs/xpdf/xpdf-3.03/Makefile.in) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/README (renamed from Build/source/libs/xpdf/xpdf-3.03/README) | 25 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/aclocal.m4 (renamed from Build/source/libs/xpdf/xpdf-3.03/aclocal.m4) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/aconf-dj.h (renamed from Build/source/libs/xpdf/xpdf-3.03/aconf-dj.h) | 5 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/aconf-win32.h (renamed from Build/source/libs/xpdf/xpdf-3.03/aconf-win32.h) | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/aconf.h.in (renamed from Build/source/libs/xpdf/xpdf-3.03/aconf.h.in) | 11 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/aconf2.h (renamed from Build/source/libs/xpdf/xpdf-3.03/aconf2.h) | 7 | ||||
-rwxr-xr-x | Build/source/libs/xpdf/xpdf-3.04/configure (renamed from Build/source/libs/xpdf/xpdf-3.03/configure) | 1141 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/configure.in (renamed from Build/source/libs/xpdf/xpdf-3.03/configure.in) | 112 | ||||
-rwxr-xr-x | Build/source/libs/xpdf/xpdf-3.04/dj_make.bat (renamed from Build/source/libs/xpdf/xpdf-3.03/dj_make.bat) | 8 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.1) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.cat) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.1) | 25 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.cat) | 21 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.1) | 14 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.cat) | 14 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.1) | 12 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.cat) | 12 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.1 | 106 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.cat | 87 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.1 | 119 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.cat | 96 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.1) | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.cat) | 20 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.1) | 11 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.cat) | 60 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.1) | 61 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.cat | 137 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/sample-xpdfrc (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/sample-xpdfrc) | 3 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.1 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.1) | 30 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.cat) | 152 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.5 (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.5) | 57 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.cat (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.cat) | 334 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.hlp (renamed from Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.hlp) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiBase.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiBase.cc) | 12 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiBase.h (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiBase.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiEncodings.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiEncodings.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiEncodings.h (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiEncodings.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiIdentifier.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiIdentifier.cc) | 255 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiIdentifier.h (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiIdentifier.h) | 11 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiTrueType.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiTrueType.cc) | 220 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiTrueType.h (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiTrueType.h) | 33 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1.h (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1C.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1C.cc) | 140 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1C.h (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1C.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/Makefile.dep (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/Makefile.dep) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/Makefile.in (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/Makefile.in) | 4 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/fofi/vms_make.com (renamed from Build/source/libs/xpdf/xpdf-3.03/fofi/vms_make.com) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/FixedPoint.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/FixedPoint.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/FixedPoint.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/FixedPoint.h) | 58 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GHash.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GHash.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GHash.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GHash.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GList.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GList.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GList.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GList.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GMutex.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GMutex.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GString.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GString.cc) | 68 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/GString.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/GString.h) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/Makefile.dep (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/Makefile.dep) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/Makefile.in (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/Makefile.in) | 6 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/gfile.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/gfile.cc) | 90 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/gfile.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/gfile.h) | 37 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/gmem.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/gmem.cc) | 77 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/gmem.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/gmem.h) | 5 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/gmempp.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/gmempp.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/gtypes.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/gtypes.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/parseargs.c (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/parseargs.c) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/parseargs.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/parseargs.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_directory.c (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_directory.c) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_dirent.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_dirent.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_make.com (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_make.com) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_sys_dirent.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_sys_dirent.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_unix_time.h (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_unix_time.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_unix_times.c (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_unix_times.c) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/goo/vms_unlink.c (renamed from Build/source/libs/xpdf/xpdf-3.03/goo/vms_unlink.c) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/misc/hello.pdf (renamed from Build/source/libs/xpdf/xpdf-3.03/misc/hello.pdf) | bin | 917 -> 917 bytes | |||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/misc/xpdf.dt (renamed from Build/source/libs/xpdf/xpdf-3.03/misc/xpdf.dt) | 0 | ||||
-rwxr-xr-x | Build/source/libs/xpdf/xpdf-3.04/ms_make.bat | 134 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/Makefile.dep (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/Makefile.dep) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/Makefile.in (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/Makefile.in) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/Splash.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/Splash.cc) | 4548 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/Splash.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/Splash.h) | 117 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashBitmap.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashBitmap.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashBitmap.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashBitmap.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.cc | 520 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.h) | 55 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashErrorCodes.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashErrorCodes.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFont.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFont.cc) | 31 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFont.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFont.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.cc | 385 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.h) | 56 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontFile.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontFile.cc) | 71 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontFile.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontFile.h) | 34 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFont.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFont.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFont.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFont.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontEngine.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontEngine.cc) | 123 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontEngine.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontEngine.h) | 63 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFile.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFile.cc) | 21 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFile.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFile.h) | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFileID.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFileID.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFileID.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFileID.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashGlyphBitmap.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashGlyphBitmap.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashMath.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashMath.h) | 93 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashPath.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashPath.cc) | 3 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashPath.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashPath.h) | 4 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashPattern.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashPattern.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashPattern.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashPattern.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashScreen.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashScreen.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashScreen.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashScreen.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashState.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashState.cc) | 48 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashState.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashState.h) | 11 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1Font.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1Font.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1Font.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1Font.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontEngine.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontEngine.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontEngine.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontEngine.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontFile.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontFile.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontFile.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontFile.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashTypes.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashTypes.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPath.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPath.cc) | 346 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPath.h (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPath.h) | 63 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.cc | 567 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.h | 75 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/splash/vms_make.com (renamed from Build/source/libs/xpdf/xpdf-3.03/splash/vms_make.com) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/vms_make.com (renamed from Build/source/libs/xpdf/xpdf-3.03/vms_make.com) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Annot.cc) | 1264 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.h | 128 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.cc | 1131 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Annot.h) | 59 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Array.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Array.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Array.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Array.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFont.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFont.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFont.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFont.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFontTables.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFontTables.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFontTables.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFontTables.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CMap.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CMap.cc) | 52 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CMap.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CMap.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Catalog.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Catalog.cc) | 85 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Catalog.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Catalog.h) | 5 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CharCodeToUnicode.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CharCodeToUnicode.cc) | 16 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CharCodeToUnicode.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CharCodeToUnicode.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CharTypes.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CharTypes.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CompactFontTables.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CompactFontTables.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CoreOutputDev.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CoreOutputDev.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/CoreOutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/CoreOutputDev.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Decrypt.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Decrypt.cc) | 853 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Decrypt.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Decrypt.h) | 18 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Dict.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Dict.cc) | 78 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Dict.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Dict.h) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Error.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Error.cc) | 30 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Error.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Error.h) | 6 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/ErrorCodes.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/ErrorCodes.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/FontEncodingTables.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/FontEncodingTables.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/FontEncodingTables.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/FontEncodingTables.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.cc | 67 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.h | 64 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Function.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Function.cc) | 1176 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Function.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Function.h) | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Gfx.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Gfx.cc) | 720 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Gfx.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Gfx.h) | 59 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxFont.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxFont.cc) | 129 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxFont.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxFont.h) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxState.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxState.cc) | 449 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxState.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxState.h) | 79 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/GlobalParams.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/GlobalParams.cc) | 507 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/GlobalParams.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/GlobalParams.h) | 28 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.cc | 583 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.h | 63 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/ImageOutputDev.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/ImageOutputDev.cc) | 84 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/ImageOutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/ImageOutputDev.h) | 18 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/JArithmeticDecoder.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/JArithmeticDecoder.cc) | 18 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/JArithmeticDecoder.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/JArithmeticDecoder.h) | 1 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/JBIG2Stream.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/JBIG2Stream.cc) | 73 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/JBIG2Stream.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/JBIG2Stream.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/JPXStream.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/JPXStream.cc) | 505 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/JPXStream.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/JPXStream.h) | 24 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Lexer.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Lexer.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Lexer.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Lexer.h) | 9 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Link.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Link.cc) | 132 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Link.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Link.h) | 82 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.dep (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.dep) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.in | 687 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToCharCode.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToCharCode.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToCharCode.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToCharCode.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToUnicodeTable.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToUnicodeTable.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Object.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Object.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Object.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Object.h) | 13 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/OptionalContent.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/OptionalContent.cc) | 207 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/OptionalContent.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/OptionalContent.h) | 21 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Outline.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Outline.cc) | 92 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Outline.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Outline.h) | 17 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/OutputDev.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/OutputDev.cc) | 38 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/OutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/OutputDev.h) | 14 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFCore.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFCore.cc) | 79 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFCore.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFCore.h) | 6 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDoc.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDoc.cc) | 65 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDoc.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDoc.h) | 9 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDocEncoding.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDocEncoding.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDocEncoding.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDocEncoding.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PSOutputDev.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PSOutputDev.cc) | 1639 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PSOutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PSOutputDev.h) | 65 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PSTokenizer.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PSTokenizer.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PSTokenizer.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PSTokenizer.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Page.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Page.cc) | 37 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Page.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Page.h) | 3 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Parser.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Parser.cc) | 27 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Parser.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Parser.h) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PreScanOutputDev.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PreScanOutputDev.cc) | 27 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/PreScanOutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/PreScanOutputDev.h) | 11 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/SecurityHandler.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/SecurityHandler.cc) | 14 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/SecurityHandler.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/SecurityHandler.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/SplashOutputDev.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/SplashOutputDev.cc) | 549 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/SplashOutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/SplashOutputDev.h) | 25 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream-CCITT.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream-CCITT.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream.cc) | 889 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream.h) | 121 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.cc | 4463 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.h) | 513 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.cc | 164 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.h | 66 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/UTF8.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/UTF8.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMap.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMap.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMap.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMap.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMapTables.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMapTables.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeTypeTable.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeTypeTable.cc) | 40 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeTypeTable.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeTypeTable.h) | 4 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.cc | 1458 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.h | 126 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFApp.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFApp.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFApp.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFApp.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFCore.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFCore.cc) | 19 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFCore.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFCore.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTree.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTree.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTree.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTree.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTreeP.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTreeP.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFViewer.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFViewer.cc) | 35 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFViewer.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFViewer.h) | 1 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XRef.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XRef.cc) | 433 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XRef.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XRef.h) | 40 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XpdfPluginAPI.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XpdfPluginAPI.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/XpdfPluginAPI.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/XpdfPluginAPI.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.cc | 839 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.h | 241 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/about-text.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/about-text.h) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/about.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/about.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/backArrow.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/backArrow.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/backArrowDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/backArrowDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/config.h (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/config.h) | 20 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/dblLeftArrow.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/dblLeftArrow.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/dblLeftArrowDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/dblLeftArrowDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/dblRightArrow.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/dblRightArrow.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/dblRightArrowDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/dblRightArrowDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/find.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/find.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/findDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/findDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/forwardArrow.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/forwardArrow.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/forwardArrowDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/forwardArrowDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/leftArrow.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/leftArrow.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/leftArrowDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/leftArrowDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfdetach.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfdetach.cc) | 2 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdffonts.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdffonts.cc) | 158 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfimages.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfimages.cc) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfinfo.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfinfo.cc) | 47 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftohtml.cc | 246 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftopng.cc | 289 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftoppm.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftoppm.cc) | 36 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftops.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftops.cc) | 31 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftotext.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftotext.cc) | 189 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/print.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/print.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/printDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/printDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/rightArrow.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/rightArrow.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/rightArrowDis.xbm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/rightArrowDis.xbm) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/vms_make.com (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/vms_make.com) | 0 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/xpdf.cc (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/xpdf.cc) | 10 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-3.04/xpdf/xpdfIcon.xpm (renamed from Build/source/libs/xpdf/xpdf-3.03/xpdf/xpdfIcon.xpm) | 0 | ||||
-rw-r--r-- | Build/source/texk/web2c/pdftexdir/ChangeLog | 8 | ||||
-rw-r--r-- | Build/source/texk/web2c/pdftexdir/pdftosrc.cc | 4 |
314 files changed, 26720 insertions, 13873 deletions
diff --git a/Build/source/libs/xpdf/ChangeLog b/Build/source/libs/xpdf/ChangeLog index 8ae901cb4a0..093926711ca 100644 --- a/Build/source/libs/xpdf/ChangeLog +++ b/Build/source/libs/xpdf/ChangeLog @@ -1,3 +1,8 @@ +2014-06-16 Peter Breitenlohner <peb@mppmu.mpg.de> + + Import xpdf-3.04. + * configure.ac, version.ac, Makefile.am: Adapted. + 2013-07-06 Peter Breitenlohner <peb@mppmu.mpg.de> * Makefile.am: Use ../../am/rebuild.am. diff --git a/Build/source/libs/xpdf/Makefile.am b/Build/source/libs/xpdf/Makefile.am index 331c5dea141..291bf90cd16 100644 --- a/Build/source/libs/xpdf/Makefile.am +++ b/Build/source/libs/xpdf/Makefile.am @@ -62,9 +62,9 @@ goo_libGoo_a_sources = \ @XPDF_TREE@/goo/GHash.cc \ @XPDF_TREE@/goo/GList.cc \ @XPDF_TREE@/goo/GString.cc \ + @XPDF_TREE@/goo/gfile.cc \ @XPDF_TREE@/goo/gmem.cc \ - @XPDF_TREE@/goo/gmempp.cc \ - @XPDF_TREE@/goo/gfile.cc + @XPDF_TREE@/goo/gmempp.cc fofi_libfofi_a_sources = \ @XPDF_TREE@/fofi/FoFiBase.cc \ @@ -75,6 +75,7 @@ fofi_libfofi_a_sources = \ @XPDF_TREE@/fofi/FoFiType1C.cc xpdf_libxpdf_a_sources = \ + @XPDF_TREE@/xpdf/AcroForm.cc \ @XPDF_TREE@/xpdf/Array.cc \ @XPDF_TREE@/xpdf/BuiltinFont.cc \ @XPDF_TREE@/xpdf/BuiltinFontTables.cc \ @@ -85,7 +86,9 @@ xpdf_libxpdf_a_sources = \ @XPDF_TREE@/xpdf/Dict.cc \ @XPDF_TREE@/xpdf/Error.cc \ @XPDF_TREE@/xpdf/FontEncodingTables.cc \ + @XPDF_TREE@/xpdf/Form.cc \ @XPDF_TREE@/xpdf/Function.cc \ + @XPDF_TREE@/xpdf/Gfx.cc \ @XPDF_TREE@/xpdf/GfxFont.cc \ @XPDF_TREE@/xpdf/GfxState.cc \ @XPDF_TREE@/xpdf/GlobalParams.cc \ @@ -106,8 +109,11 @@ xpdf_libxpdf_a_sources = \ @XPDF_TREE@/xpdf/Parser.cc \ @XPDF_TREE@/xpdf/SecurityHandler.cc \ @XPDF_TREE@/xpdf/Stream.cc \ + @XPDF_TREE@/xpdf/TextString.cc \ @XPDF_TREE@/xpdf/UnicodeMap.cc \ - @XPDF_TREE@/xpdf/XRef.cc + @XPDF_TREE@/xpdf/XFAForm.cc \ + @XPDF_TREE@/xpdf/XRef.cc \ + @XPDF_TREE@/xpdf/Zoox.cc # Rebuild rebuild_prereq = diff --git a/Build/source/libs/xpdf/Makefile.in b/Build/source/libs/xpdf/Makefile.in index 1eccb2c0f59..41ffa1999ca 100644 --- a/Build/source/libs/xpdf/Makefile.in +++ b/Build/source/libs/xpdf/Makefile.in @@ -115,16 +115,16 @@ am__objects_1 = @XPDF_TREE@/goo/FixedPoint.$(OBJEXT) \ @XPDF_TREE@/goo/GHash.$(OBJEXT) \ @XPDF_TREE@/goo/GList.$(OBJEXT) \ @XPDF_TREE@/goo/GString.$(OBJEXT) \ - @XPDF_TREE@/goo/gmem.$(OBJEXT) \ - @XPDF_TREE@/goo/gmempp.$(OBJEXT) \ - @XPDF_TREE@/goo/gfile.$(OBJEXT) + @XPDF_TREE@/goo/gfile.$(OBJEXT) @XPDF_TREE@/goo/gmem.$(OBJEXT) \ + @XPDF_TREE@/goo/gmempp.$(OBJEXT) am__objects_2 = @XPDF_TREE@/fofi/FoFiBase.$(OBJEXT) \ @XPDF_TREE@/fofi/FoFiEncodings.$(OBJEXT) \ @XPDF_TREE@/fofi/FoFiIdentifier.$(OBJEXT) \ @XPDF_TREE@/fofi/FoFiTrueType.$(OBJEXT) \ @XPDF_TREE@/fofi/FoFiType1.$(OBJEXT) \ @XPDF_TREE@/fofi/FoFiType1C.$(OBJEXT) -am__objects_3 = @XPDF_TREE@/xpdf/Array.$(OBJEXT) \ +am__objects_3 = @XPDF_TREE@/xpdf/AcroForm.$(OBJEXT) \ + @XPDF_TREE@/xpdf/Array.$(OBJEXT) \ @XPDF_TREE@/xpdf/BuiltinFont.$(OBJEXT) \ @XPDF_TREE@/xpdf/BuiltinFontTables.$(OBJEXT) \ @XPDF_TREE@/xpdf/CMap.$(OBJEXT) \ @@ -134,7 +134,9 @@ am__objects_3 = @XPDF_TREE@/xpdf/Array.$(OBJEXT) \ @XPDF_TREE@/xpdf/Dict.$(OBJEXT) \ @XPDF_TREE@/xpdf/Error.$(OBJEXT) \ @XPDF_TREE@/xpdf/FontEncodingTables.$(OBJEXT) \ + @XPDF_TREE@/xpdf/Form.$(OBJEXT) \ @XPDF_TREE@/xpdf/Function.$(OBJEXT) \ + @XPDF_TREE@/xpdf/Gfx.$(OBJEXT) \ @XPDF_TREE@/xpdf/GfxFont.$(OBJEXT) \ @XPDF_TREE@/xpdf/GfxState.$(OBJEXT) \ @XPDF_TREE@/xpdf/GlobalParams.$(OBJEXT) \ @@ -155,8 +157,11 @@ am__objects_3 = @XPDF_TREE@/xpdf/Array.$(OBJEXT) \ @XPDF_TREE@/xpdf/Parser.$(OBJEXT) \ @XPDF_TREE@/xpdf/SecurityHandler.$(OBJEXT) \ @XPDF_TREE@/xpdf/Stream.$(OBJEXT) \ + @XPDF_TREE@/xpdf/TextString.$(OBJEXT) \ @XPDF_TREE@/xpdf/UnicodeMap.$(OBJEXT) \ - @XPDF_TREE@/xpdf/XRef.$(OBJEXT) + @XPDF_TREE@/xpdf/XFAForm.$(OBJEXT) \ + @XPDF_TREE@/xpdf/XRef.$(OBJEXT) \ + @XPDF_TREE@/xpdf/Zoox.$(OBJEXT) nodist_libxpdf_a_OBJECTS = $(am__objects_1) $(am__objects_2) \ $(am__objects_3) libxpdf_a_OBJECTS = $(nodist_libxpdf_a_OBJECTS) @@ -399,9 +404,9 @@ goo_libGoo_a_sources = \ @XPDF_TREE@/goo/GHash.cc \ @XPDF_TREE@/goo/GList.cc \ @XPDF_TREE@/goo/GString.cc \ + @XPDF_TREE@/goo/gfile.cc \ @XPDF_TREE@/goo/gmem.cc \ - @XPDF_TREE@/goo/gmempp.cc \ - @XPDF_TREE@/goo/gfile.cc + @XPDF_TREE@/goo/gmempp.cc fofi_libfofi_a_sources = \ @XPDF_TREE@/fofi/FoFiBase.cc \ @@ -412,6 +417,7 @@ fofi_libfofi_a_sources = \ @XPDF_TREE@/fofi/FoFiType1C.cc xpdf_libxpdf_a_sources = \ + @XPDF_TREE@/xpdf/AcroForm.cc \ @XPDF_TREE@/xpdf/Array.cc \ @XPDF_TREE@/xpdf/BuiltinFont.cc \ @XPDF_TREE@/xpdf/BuiltinFontTables.cc \ @@ -422,7 +428,9 @@ xpdf_libxpdf_a_sources = \ @XPDF_TREE@/xpdf/Dict.cc \ @XPDF_TREE@/xpdf/Error.cc \ @XPDF_TREE@/xpdf/FontEncodingTables.cc \ + @XPDF_TREE@/xpdf/Form.cc \ @XPDF_TREE@/xpdf/Function.cc \ + @XPDF_TREE@/xpdf/Gfx.cc \ @XPDF_TREE@/xpdf/GfxFont.cc \ @XPDF_TREE@/xpdf/GfxState.cc \ @XPDF_TREE@/xpdf/GlobalParams.cc \ @@ -443,8 +451,11 @@ xpdf_libxpdf_a_sources = \ @XPDF_TREE@/xpdf/Parser.cc \ @XPDF_TREE@/xpdf/SecurityHandler.cc \ @XPDF_TREE@/xpdf/Stream.cc \ + @XPDF_TREE@/xpdf/TextString.cc \ @XPDF_TREE@/xpdf/UnicodeMap.cc \ - @XPDF_TREE@/xpdf/XRef.cc + @XPDF_TREE@/xpdf/XFAForm.cc \ + @XPDF_TREE@/xpdf/XRef.cc \ + @XPDF_TREE@/xpdf/Zoox.cc # Rebuild @@ -523,12 +534,12 @@ clean-noinstLIBRARIES: @XPDF_TREE@/goo/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/goo/GString.$(OBJEXT): @XPDF_TREE@/goo/$(am__dirstamp) \ @XPDF_TREE@/goo/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/goo/gfile.$(OBJEXT): @XPDF_TREE@/goo/$(am__dirstamp) \ + @XPDF_TREE@/goo/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/goo/gmem.$(OBJEXT): @XPDF_TREE@/goo/$(am__dirstamp) \ @XPDF_TREE@/goo/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/goo/gmempp.$(OBJEXT): @XPDF_TREE@/goo/$(am__dirstamp) \ @XPDF_TREE@/goo/$(DEPDIR)/$(am__dirstamp) -@XPDF_TREE@/goo/gfile.$(OBJEXT): @XPDF_TREE@/goo/$(am__dirstamp) \ - @XPDF_TREE@/goo/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/fofi/$(am__dirstamp): @$(MKDIR_P) @XPDF_TREE@/fofi @: > @XPDF_TREE@/fofi/$(am__dirstamp) @@ -558,6 +569,8 @@ clean-noinstLIBRARIES: @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) @XPDF_TREE@/xpdf/$(DEPDIR) @: > @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/xpdf/AcroForm.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ + @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/Array.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/BuiltinFont.$(OBJEXT): \ @@ -582,8 +595,12 @@ clean-noinstLIBRARIES: @XPDF_TREE@/xpdf/FontEncodingTables.$(OBJEXT): \ @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/xpdf/Form.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ + @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/Function.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/xpdf/Gfx.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ + @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/GfxFont.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/GfxState.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ @@ -634,11 +651,18 @@ clean-noinstLIBRARIES: @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/Stream.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/xpdf/TextString.$(OBJEXT): \ + @XPDF_TREE@/xpdf/$(am__dirstamp) \ + @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/UnicodeMap.$(OBJEXT): \ @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/xpdf/XFAForm.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ + @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) @XPDF_TREE@/xpdf/XRef.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) +@XPDF_TREE@/xpdf/Zoox.$(OBJEXT): @XPDF_TREE@/xpdf/$(am__dirstamp) \ + @XPDF_TREE@/xpdf/$(DEPDIR)/$(am__dirstamp) libxpdf.a: $(libxpdf_a_OBJECTS) $(libxpdf_a_DEPENDENCIES) $(EXTRA_libxpdf_a_DEPENDENCIES) $(AM_V_at)-rm -f libxpdf.a @@ -667,6 +691,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/goo/$(DEPDIR)/gfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/goo/$(DEPDIR)/gmem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/goo/$(DEPDIR)/gmempp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/AcroForm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Array.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/BuiltinFont.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/BuiltinFontTables.Po@am__quote@ @@ -677,7 +702,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Dict.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/FontEncodingTables.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Form.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Function.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Gfx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/GfxFont.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/GfxState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/GlobalParams.Po@am__quote@ @@ -698,8 +725,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/SecurityHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Stream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/TextString.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/UnicodeMap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/XFAForm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/XRef.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@@XPDF_TREE@/xpdf/$(DEPDIR)/Zoox.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ diff --git a/Build/source/libs/xpdf/aconf.h.in b/Build/source/libs/xpdf/aconf.h.in index fd9376c92c2..2d95594cb79 100644 --- a/Build/source/libs/xpdf/aconf.h.in +++ b/Build/source/libs/xpdf/aconf.h.in @@ -23,6 +23,9 @@ */ #undef HAVE_DIRENT_H +/* Define to 1 if you have the `fseek64' function. */ +#undef HAVE_FSEEK64 + /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO diff --git a/Build/source/libs/xpdf/configure b/Build/source/libs/xpdf/configure index c0a0cca71fe..a8c06ff7350 100755 --- a/Build/source/libs/xpdf/configure +++ b/Build/source/libs/xpdf/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for xpdf (TeX Live) 3.03. +# Generated by GNU Autoconf 2.69 for xpdf (TeX Live) 3.04. # # Report bugs to <tex-k@tug.org>. # @@ -580,12 +580,12 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='xpdf (TeX Live)' PACKAGE_TARNAME='xpdf--tex-live-' -PACKAGE_VERSION='3.03' -PACKAGE_STRING='xpdf (TeX Live) 3.03' +PACKAGE_VERSION='3.04' +PACKAGE_STRING='xpdf (TeX Live) 3.04' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' -ac_unique_file="xpdf-3.03/xpdf/Array.cc" +ac_unique_file="xpdf-3.04/xpdf/Array.cc" # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> @@ -1290,7 +1290,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures xpdf (TeX Live) 3.03 to adapt to many kinds of systems. +\`configure' configures xpdf (TeX Live) 3.04 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1356,7 +1356,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of xpdf (TeX Live) 3.03:";; + short | recursive ) echo "Configuration of xpdf (TeX Live) 3.04:";; esac cat <<\_ACEOF @@ -1460,7 +1460,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -xpdf (TeX Live) configure 3.03 +xpdf (TeX Live) configure 3.04 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1867,7 +1867,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by xpdf (TeX Live) $as_me 3.03, which was +It was created by xpdf (TeX Live) $as_me 3.04, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3790,7 +3790,7 @@ fi # Define the identity of the package. PACKAGE='xpdf--tex-live-' - VERSION='3.03' + VERSION='3.04' # Some tools Automake needs. @@ -6129,6 +6129,21 @@ $as_echo "#define HAVE_FSEEKO 1" >>confdefs.h fi +ac_fn_c_check_func "$LINENO" "ftell64" "ac_cv_func_ftell64" +if test "x$ac_cv_func_ftell64" = xyes; then : + for ac_func in fseek64 +do : + ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" +if test "x$ac_cv_func_fseek64" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FSEEK64 1 +_ACEOF + +fi +done + +fi + ac_config_headers="$ac_config_headers aconf.h" @@ -6136,7 +6151,7 @@ ac_config_headers="$ac_config_headers aconf.h" -XPDF_TREE=xpdf-3.03 +XPDF_TREE=xpdf-3.04 ac_config_links="$ac_config_links aconf2.h:$XPDF_TREE/aconf2.h" @@ -6687,7 +6702,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by xpdf (TeX Live) $as_me 3.03, which was +This file was extended by xpdf (TeX Live) $as_me 3.04, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6757,7 +6772,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -xpdf (TeX Live) config.status 3.03 +xpdf (TeX Live) config.status 3.04 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/xpdf/configure.ac b/Build/source/libs/xpdf/configure.ac index 2fdd33c1668..93e89db7e88 100644 --- a/Build/source/libs/xpdf/configure.ac +++ b/Build/source/libs/xpdf/configure.ac @@ -58,6 +58,8 @@ dnl **** Checks for library functions **** AC_CHECK_FUNCS([popen mkstemp mkstemps]) AC_SYS_LARGEFILE AC_FUNC_FSEEKO +AC_CHECK_FUNC([ftell64], + [AC_CHECK_FUNCS([fseek64])]) AC_CONFIG_HEADERS([aconf.h], [sed -e 's/^#define PACKAGE/#define XPDF_PACKAGE/' \ diff --git a/Build/source/libs/xpdf/version.ac b/Build/source/libs/xpdf/version.ac index 9d68bcf25ec..19b50b0ad92 100644 --- a/Build/source/libs/xpdf/version.ac +++ b/Build/source/libs/xpdf/version.ac @@ -8,4 +8,4 @@ dnl dnl -------------------------------------------------------- dnl dnl m4-include this file to define the current xpdf version -m4_define([xpdf_version], [3.03]) +m4_define([xpdf_version], [3.04]) diff --git a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-30-include-strings_h b/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-30-include-strings_h deleted file mode 100644 index 2a8bae993de..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-30-include-strings_h +++ /dev/null @@ -1,15 +0,0 @@ - The Posix manpage says strcasecmp() is declared in <strings.h> - and this indeed required for AIX 4.3 and xlc. - -diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc ---- xpdf-3.03.orig/xpdf/GlobalParams.cc 2012-10-19 10:01:03.000000000 +0200 -+++ xpdf-3.03/xpdf/GlobalParams.cc 2012-10-19 10:06:40.000000000 +0200 -@@ -48,6 +48,8 @@ - - #ifdef WIN32 - # define strcasecmp stricmp -+#else -+# include <strings.h> - #endif - - #if MULTITHREADED diff --git a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-40-W32TeX b/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-40-W32TeX deleted file mode 100644 index 33ac1784667..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-40-W32TeX +++ /dev/null @@ -1,28 +0,0 @@ - WIN32TeX uses MSVC 5.0 with the kpathsea headers and library. - -diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc ---- xpdf-3.03.orig/xpdf/GlobalParams.cc 2012-10-19 10:06:40.000000000 +0200 -+++ xpdf-3.03/xpdf/GlobalParams.cc 2012-10-19 10:15:52.000000000 +0200 -@@ -47,6 +47,7 @@ - #include "GlobalParams.h" - - #ifdef WIN32 -+# undef strcasecmp - # define strcasecmp stricmp - #else - # include <strings.h> -diff -ur -N xpdf-3.03.orig/xpdf/config.h xpdf-3.03/xpdf/config.h ---- xpdf-3.03.orig/xpdf/config.h 2011-08-15 23:08:53.000000000 +0200 -+++ xpdf-3.03/xpdf/config.h 2012-10-19 10:22:29.000000000 +0200 -@@ -78,11 +78,6 @@ - // popen - //------------------------------------------------------------------------ - --#if defined(_MSC_VER) || defined(__BORLANDC__) --#define popen _popen --#define pclose _pclose --#endif -- - #if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS) - #define POPEN_READ_MODE "rb" - #else diff --git a/Build/source/libs/xpdf/xpdf-3.03/ANNOUNCE b/Build/source/libs/xpdf/xpdf-3.03/ANNOUNCE deleted file mode 100644 index b4dff6cff19..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/ANNOUNCE +++ /dev/null @@ -1,45 +0,0 @@ -Subject: ANNOUNCE: Xpdf 3.03 - a PDF viewer for X - - -Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the -open source Portable Document Format (PDF) viewer for X. The Xpdf -project also includes a PDF text extractor, PDF-to-PostScript -converter, and various other utilities. - -Xpdf runs under the X Window System on Unix, VMS, and OS/2. The non-X -components (pdftops, pdftotext, etc.) also run on Win32 systems and -should run on pretty much any system with a decent C++ compiler. - -Major changes: -* Added the "fixed pitch" text extraction mode. -* Modified "pdftops -paper match" to handle PDF files with - different-sized pages, i.e., it will now select the matching paper - size on a page-by-page basis. -* Add ability for pdftoppm to write to stdout. -* Added the pdfdetach tool. -* Implemented 256-bit AES decryption. -* Commented out the t1lib section in the configure script -- t1lib has - some potential security holes, and hasn't been updated in years. -* Redesigned the font configuration xpdfrc commands: removed the - displayFontT1, displayFontTT, displayNamedCIDFontT1, - displayCIDFontT1, displayNamedCIDFontTT, displayCIDFontTT, psFont, - psNamedFont16, and psFont16 commands; added the fontFile, - fontFileCC, psResidentFont, psResidentFont16, and psResidentFontCC - commands. -* Switched from GPLv2 to dual v2/v3 licensing. - -See the `CHANGES' file for a complete list of changes. - -Source (C++ and C) is available, and it should be fairly easy to -compile for UNIX, VMS, OS/2, and Win32. - -More information, source code, and precompiled binaries are on the -xpdf web page and ftp site: - - http://www.foolabs.com/xpdf/ - ftp://ftp.foolabs.com/pub/xpdf/ - -For information on commercial licensing and consulting, please see the -Glyph & Cog web site: - - http://www.glyphandcog.com/ diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.cat b/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.cat deleted file mode 100644 index 5c8a70900d8..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.cat +++ /dev/null @@ -1,115 +0,0 @@ -pdftotext(1) pdftotext(1) - - - -NAME - pdftotext - Portable Document Format (PDF) to text converter (version - 3.03) - -SYNOPSIS - pdftotext [options] [PDF-file [text-file]] - -DESCRIPTION - Pdftotext converts Portable Document Format (PDF) files to plain text. - - Pdftotext reads the PDF file, PDF-file, and writes a text file, text- - file. If text-file is not specified, pdftotext converts file.pdf to - file.txt. If text-file is '-', the text is sent to stdout. - -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. - -OPTIONS - Many of the following options can be set with configuration file com- - mands. These are listed in square brackets with the description of the - corresponding command line option. - - -f number - Specifies the first page to convert. - - -l number - Specifies the last page to convert. - - -layout - Maintain (as best as possible) the original physical layout of - the text. The default is to 'undo' physical layout (columns, - hyphenation, etc.) and output the text in reading order. - - -fixed number - Assume fixed-pitch (or tabular) text, with the specified charac- - ter width (in points). This forces physical layout mode. - - -raw Keep the text in content stream order. This is a hack which - often "undoes" column formatting, etc. Use of raw mode is no - longer recommended. - - -htmlmeta - Generate a simple HTML file, including the meta information. - This simply wraps the text in <pre> and </pre> and prepends the - meta headers. - - -enc encoding-name - Sets the encoding to use for text output. The encoding-name - must be defined with the unicodeMap command (see xpdfrc(5)). - The encoding name is case-sensitive. This defaults to "Latin1" - (which is a built-in encoding). [config file: textEncoding] - - -eol unix | dos | mac - Sets the end-of-line convention to use for text output. [config - file: textEOL] - - -nopgbrk - Don't insert page breaks (form feed characters) between pages. - [config file: textPageBreaks] - - -opw password - 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. - - -q Don't print any messages or errors. [config file: errQuiet] - - -cfg config-file - Read config-file in place of ~/.xpdfrc or the system-wide config - file. - - -v Print copyright and version information. - - -h Print usage information. (-help and --help are equivalent.) - -BUGS - 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. - -EXIT CODES - The Xpdf tools use the following exit codes: - - 0 No error. - - 1 Error opening a PDF file. - - 2 Error opening an output file. - - 3 Error related to PDF permissions. - - 99 Other error. - -AUTHOR - The pdftotext software and documentation are copyright 1996-2011 Glyph - & Cog, LLC. - -SEE ALSO - xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdfdetach(1), - pdftoppm(1), pdfimages(1), xpdfrc(5) - http://www.foolabs.com/xpdf/ - - - - 15 August 2011 pdftotext(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/ms_make.bat b/Build/source/libs/xpdf/xpdf-3.03/ms_make.bat deleted file mode 100755 index c4b01a47f36..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/ms_make.bat +++ /dev/null @@ -1,132 +0,0 @@ -set CC=cl
-set CFLAGS=/DWIN32 /I.. /I..\goo /I..\fofi /I..\splash /O2 /nologo
-set CXX=cl
-set CXXFLAGS=%CFLAGS% /TP
-set LIBPROG=lib
-set LINKFLAGS=/MT /nologo
-
-copy aconf-win32.h aconf.h
-
-cd goo
-%CXX% %CXXFLAGS% /c GHash.cc
-%CXX% %CXXFLAGS% /c GList.cc
-%CXX% %CXXFLAGS% /c GString.cc
-%CXX% %CXXFLAGS% /c gmem.cc
-%CXX% %CXXFLAGS% /c gmempp.cc
-%CXX% %CXXFLAGS% /c gfile.cc
-%CC% %CFLAGS% /c parseargs.c
-%LIBPROG% /nologo /out:Goo.lib GHash.obj GList.obj GString.obj gmempp.obj gfile.obj gmem.obj parseargs.obj
-
-cd ..\fofi
-%CXX% %CXXFLAGS% /c FoFiBase.cc
-%CXX% %CXXFLAGS% /c FoFiEncodings.cc
-%CXX% %CXXFLAGS% /c FoFiIdentifier.cc
-%CXX% %CXXFLAGS% /c FoFiTrueType.cc
-%CXX% %CXXFLAGS% /c FoFiType1.cc
-%CXX% %CXXFLAGS% /c FoFiType1C.cc
-%LIBPROG% /nologo /out:fofi.lib FoFiBase.obj FoFiEncodings.obj FoFiIdentifier.obj FoFiTrueType.obj FoFiType1.obj FoFiType1C.obj
-
-cd ..\xpdf
-%CXX% %CXXFLAGS% /c Annot.cc
-%CXX% %CXXFLAGS% /c Array.cc
-%CXX% %CXXFLAGS% /c BuiltinFont.cc
-%CXX% %CXXFLAGS% /c BuiltinFontTables.cc
-%CXX% %CXXFLAGS% /c CMap.cc
-%CXX% %CXXFLAGS% /c Catalog.cc
-%CXX% %CXXFLAGS% /c CharCodeToUnicode.cc
-%CXX% %CXXFLAGS% /c Decrypt.cc
-%CXX% %CXXFLAGS% /c Dict.cc
-%CXX% %CXXFLAGS% /c Error.cc
-%CXX% %CXXFLAGS% /c FontEncodingTables.cc
-%CXX% %CXXFLAGS% /c Function.cc
-%CXX% %CXXFLAGS% /c Gfx.cc
-%CXX% %CXXFLAGS% /c GfxFont.cc
-%CXX% %CXXFLAGS% /c GfxState.cc
-%CXX% %CXXFLAGS% /c GlobalParams.cc
-%CXX% %CXXFLAGS% /c ImageOutputDev.cc
-%CXX% %CXXFLAGS% /c JArithmeticDecoder.cc
-%CXX% %CXXFLAGS% /c JBIG2Stream.cc
-%CXX% %CXXFLAGS% /c JPXStream.cc
-%CXX% %CXXFLAGS% /c Lexer.cc
-%CXX% %CXXFLAGS% /c Link.cc
-%CXX% %CXXFLAGS% /c NameToCharCode.cc
-%CXX% %CXXFLAGS% /c Object.cc
-%CXX% %CXXFLAGS% /c OptionalContent.cc
-%CXX% %CXXFLAGS% /c Outline.cc
-%CXX% %CXXFLAGS% /c OutputDev.cc
-%CXX% %CXXFLAGS% /c PDFDoc.cc
-%CXX% %CXXFLAGS% /c PDFDocEncoding.cc
-%CXX% %CXXFLAGS% /c PSOutputDev.cc
-%CXX% %CXXFLAGS% /c PSTokenizer.cc
-%CXX% %CXXFLAGS% /c Page.cc
-%CXX% %CXXFLAGS% /c Parser.cc
-%CXX% %CXXFLAGS% /c PreScanOutputDev.cc
-%CXX% %CXXFLAGS% /c SecurityHandler.cc
-%CXX% %CXXFLAGS% /c Stream.cc
-%CXX% %CXXFLAGS% /c TextOutputDev.cc
-%CXX% %CXXFLAGS% /c UnicodeMap.cc
-%CXX% %CXXFLAGS% /c UnicodeTypeTable.cc
-%CXX% %CXXFLAGS% /c XRef.cc
-%CXX% %CXXFLAGS% /c pdftops.cc
-%CXX% %CXXFLAGS% /c pdftotext.cc
-%CXX% %CXXFLAGS% /c pdfinfo.cc
-%CXX% %CXXFLAGS% /c pdffonts.cc
-%CXX% %CXXFLAGS% /c pdfdetach.cc
-%CXX% %CXXFLAGS% /c pdfimages.cc
-
-rem --- Comment out this line, and uncomment the other pdftops build line
-rem (see below) to build pdftops with the Splash rasterizer.
-rem You'll also need to define HAVE_SPLASH in aconf-win32.h.
-%CXX% %LINKFLAGS% /Fepdftops.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj PreScanOutputDev.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdftops.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-%CXX% %LINKFLAGS% /Fepdftotext.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextOutputDev.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftotext.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-%CXX% %LINKFLAGS% /Fepdfinfo.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfinfo.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-%CXX% %LINKFLAGS% /Fepdffonts.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdffonts.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-%CXX% %LINKFLAGS% /Fepdfdetach.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfdetach.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-%CXX% %LINKFLAGS% /Fepdfimages.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj ImageOutputDev.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfimages.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-cd ..
-
-rem --- This part will only work if you have FreeType installed ---
-
-set FT2DIR=..\freetype-2.4.6
-set CXXFLAGS=%CXXFLAGS% /I%FT2DIR%\include
-
-cd splash
-%CXX% %CXXFLAGS% /c Splash.cc
-%CXX% %CXXFLAGS% /c SplashBitmap.cc
-%CXX% %CXXFLAGS% /c SplashClip.cc
-%CXX% %CXXFLAGS% /c SplashFTFont.cc
-%CXX% %CXXFLAGS% /c SplashFTFontEngine.cc
-%CXX% %CXXFLAGS% /c SplashFTFontFile.cc
-%CXX% %CXXFLAGS% /c SplashFont.cc
-%CXX% %CXXFLAGS% /c SplashFontEngine.cc
-%CXX% %CXXFLAGS% /c SplashFontFile.cc
-%CXX% %CXXFLAGS% /c SplashFontFileID.cc
-%CXX% %CXXFLAGS% /c SplashPath.cc
-%CXX% %CXXFLAGS% /c SplashPattern.cc
-%CXX% %CXXFLAGS% /c SplashScreen.cc
-%CXX% %CXXFLAGS% /c SplashState.cc
-%CXX% %CXXFLAGS% /c SplashT1Font.cc
-%CXX% %CXXFLAGS% /c SplashT1FontEngine.cc
-%CXX% %CXXFLAGS% /c SplashT1FontFile.cc
-%CXX% %CXXFLAGS% /c SplashXPath.cc
-%CXX% %CXXFLAGS% /c SplashXPathScanner.cc
-%LIBPROG% /nologo /out:splash.lib Splash.obj SplashBitmap.obj SplashClip.obj SplashFTFont.obj SplashFTFontEngine.obj SplashFTFontFile.obj SplashFont.obj SplashFontEngine.obj SplashFontFile.obj SplashFontFileID.obj SplashPath.obj SplashPattern.obj SplashScreen.obj SplashState.obj SplashT1Font.obj SplashT1FontEngine.obj SplashT1FontFile.obj SplashXPath.obj SplashXPathScanner.obj
-
-cd ..\xpdf
-%CXX% %CXXFLAGS% /c SplashOutputDev.cc
-%CXX% %CXXFLAGS% /c pdftoppm.cc
-
-%CXX% %LINKFLAGS% /Fepdftoppm.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftoppm.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-rem --- Uncomment this line, and comment out the other pdftops build
-rem line (see above) to build pdftops with the Splash rasterizer.
-rem You'll also need to define HAVE_SPLASH in aconf-win32.h.
-rem %CXX% %LINKFLAGS% /Fepdftops.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj PreScanOutputDev.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj UnicodeMap.obj XRef.obj pdftops.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
-
-cd ..
diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.cc b/Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.cc deleted file mode 100644 index da857712c94..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.cc +++ /dev/null @@ -1,399 +0,0 @@ -//======================================================================== -// -// SplashClip.cc -// -//======================================================================== - -#include <aconf.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#include "gmem.h" -#include "SplashErrorCodes.h" -#include "SplashPath.h" -#include "SplashXPath.h" -#include "SplashXPathScanner.h" -#include "SplashBitmap.h" -#include "SplashClip.h" - -//------------------------------------------------------------------------ -// SplashClip.flags -//------------------------------------------------------------------------ - -#define splashClipEO 0x01 // use even-odd rule - -//------------------------------------------------------------------------ -// SplashClip -//------------------------------------------------------------------------ - -SplashClip::SplashClip(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - GBool antialiasA) { - antialias = antialiasA; - if (x0 < x1) { - xMin = x0; - xMax = x1; - } else { - xMin = x1; - xMax = x0; - } - if (y0 < y1) { - yMin = y0; - yMax = y1; - } else { - yMin = y1; - yMax = y0; - } - xMinI = splashFloor(xMin); - yMinI = splashFloor(yMin); - xMaxI = splashCeil(xMax) - 1; - yMaxI = splashCeil(yMax) - 1; - paths = NULL; - flags = NULL; - scanners = NULL; - length = size = 0; -} - -SplashClip::SplashClip(SplashClip *clip) { - int yMinAA, yMaxAA; - int i; - - antialias = clip->antialias; - xMin = clip->xMin; - yMin = clip->yMin; - xMax = clip->xMax; - yMax = clip->yMax; - xMinI = clip->xMinI; - yMinI = clip->yMinI; - xMaxI = clip->xMaxI; - yMaxI = clip->yMaxI; - length = clip->length; - size = clip->size; - paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *)); - flags = (Guchar *)gmallocn(size, sizeof(Guchar)); - scanners = (SplashXPathScanner **) - gmallocn(size, sizeof(SplashXPathScanner *)); - for (i = 0; i < length; ++i) { - paths[i] = clip->paths[i]->copy(); - flags[i] = clip->flags[i]; - if (antialias) { - yMinAA = yMinI * splashAASize; - yMaxAA = (yMaxI + 1) * splashAASize - 1; - } else { - yMinAA = yMinI; - yMaxAA = yMaxI; - } - scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO, - yMinAA, yMaxAA); - } -} - -SplashClip::~SplashClip() { - int i; - - for (i = 0; i < length; ++i) { - delete paths[i]; - delete scanners[i]; - } - gfree(paths); - gfree(flags); - gfree(scanners); -} - -void SplashClip::grow(int nPaths) { - if (length + nPaths > size) { - if (size == 0) { - size = 32; - } - while (size < length + nPaths) { - size *= 2; - } - paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *)); - flags = (Guchar *)greallocn(flags, size, sizeof(Guchar)); - scanners = (SplashXPathScanner **) - greallocn(scanners, size, sizeof(SplashXPathScanner *)); - } -} - -void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1) { - int i; - - for (i = 0; i < length; ++i) { - delete paths[i]; - delete scanners[i]; - } - gfree(paths); - gfree(flags); - gfree(scanners); - paths = NULL; - flags = NULL; - scanners = NULL; - length = size = 0; - - if (x0 < x1) { - xMin = x0; - xMax = x1; - } else { - xMin = x1; - xMax = x0; - } - if (y0 < y1) { - yMin = y0; - yMax = y1; - } else { - yMin = y1; - yMax = y0; - } - xMinI = splashFloor(xMin); - yMinI = splashFloor(yMin); - xMaxI = splashCeil(xMax) - 1; - yMaxI = splashCeil(yMax) - 1; -} - -SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1) { - if (x0 < x1) { - if (x0 > xMin) { - xMin = x0; - xMinI = splashFloor(xMin); - } - if (x1 < xMax) { - xMax = x1; - xMaxI = splashCeil(xMax) - 1; - } - } else { - if (x1 > xMin) { - xMin = x1; - xMinI = splashFloor(xMin); - } - if (x0 < xMax) { - xMax = x0; - xMaxI = splashCeil(xMax) - 1; - } - } - if (y0 < y1) { - if (y0 > yMin) { - yMin = y0; - yMinI = splashFloor(yMin); - } - if (y1 < yMax) { - yMax = y1; - yMaxI = splashCeil(yMax) - 1; - } - } else { - if (y1 > yMin) { - yMin = y1; - yMinI = splashFloor(yMin); - } - if (y0 < yMax) { - yMax = y0; - yMaxI = splashCeil(yMax) - 1; - } - } - return splashOk; -} - -SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix, - SplashCoord flatness, GBool eo) { - SplashXPath *xPath; - int yMinAA, yMaxAA; - - xPath = new SplashXPath(path, matrix, flatness, gTrue); - - // check for an empty path - if (xPath->length == 0) { - xMax = xMin - 1; - yMax = yMin - 1; - xMaxI = splashCeil(xMax) - 1; - yMaxI = splashCeil(yMax) - 1; - delete xPath; - - // check for a rectangle - } else if (xPath->length == 4 && - ((xPath->segs[0].x0 == xPath->segs[0].x1 && - xPath->segs[0].x0 == xPath->segs[1].x0 && - xPath->segs[0].x0 == xPath->segs[3].x1 && - xPath->segs[2].x0 == xPath->segs[2].x1 && - xPath->segs[2].x0 == xPath->segs[1].x1 && - xPath->segs[2].x0 == xPath->segs[3].x0 && - xPath->segs[1].y0 == xPath->segs[1].y1 && - xPath->segs[1].y0 == xPath->segs[0].y1 && - xPath->segs[1].y0 == xPath->segs[2].y0 && - xPath->segs[3].y0 == xPath->segs[3].y1 && - xPath->segs[3].y0 == xPath->segs[0].y0 && - xPath->segs[3].y0 == xPath->segs[2].y1) || - (xPath->segs[0].y0 == xPath->segs[0].y1 && - xPath->segs[0].y0 == xPath->segs[1].y0 && - xPath->segs[0].y0 == xPath->segs[3].y1 && - xPath->segs[2].y0 == xPath->segs[2].y1 && - xPath->segs[2].y0 == xPath->segs[1].y1 && - xPath->segs[2].y0 == xPath->segs[3].y0 && - xPath->segs[1].x0 == xPath->segs[1].x1 && - xPath->segs[1].x0 == xPath->segs[0].x1 && - xPath->segs[1].x0 == xPath->segs[2].x0 && - xPath->segs[3].x0 == xPath->segs[3].x1 && - xPath->segs[3].x0 == xPath->segs[0].x0 && - xPath->segs[3].x0 == xPath->segs[2].x1))) { - clipToRect(xPath->segs[0].x0, xPath->segs[0].y0, - xPath->segs[2].x0, xPath->segs[2].y0); - delete xPath; - - } else { - grow(1); - if (antialias) { - xPath->aaScale(); - } - xPath->sort(); - paths[length] = xPath; - flags[length] = eo ? splashClipEO : 0; - if (antialias) { - yMinAA = yMinI * splashAASize; - yMaxAA = (yMaxI + 1) * splashAASize - 1; - } else { - yMinAA = yMinI; - yMaxAA = yMaxI; - } - scanners[length] = new SplashXPathScanner(xPath, eo, yMinAA, yMaxAA); - ++length; - } - - return splashOk; -} - -GBool SplashClip::test(int x, int y) { - int i; - - // check the rectangle - if (x < xMinI || x > xMaxI || y < yMinI || y > yMaxI) { - return gFalse; - } - - // check the paths - if (antialias) { - for (i = 0; i < length; ++i) { - if (!scanners[i]->test(x * splashAASize, y * splashAASize)) { - return gFalse; - } - } - } else { - for (i = 0; i < length; ++i) { - if (!scanners[i]->test(x, y)) { - return gFalse; - } - } - } - - return gTrue; -} - -SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin, - int rectXMax, int rectYMax) { - // This tests the rectangle: - // x = [rectXMin, rectXMax + 1) (note: rect coords are ints) - // y = [rectYMin, rectYMax + 1) - // against the clipping region: - // x = [xMin, xMax) (note: clipping coords are fp) - // y = [yMin, yMax) - if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin >= xMax || - (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin >= yMax) { - return splashClipAllOutside; - } - if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax && - (SplashCoord)rectYMin >= yMin && (SplashCoord)(rectYMax + 1) <= yMax && - length == 0) { - return splashClipAllInside; - } - return splashClipPartial; -} - -SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) { - int i; - - // This tests the rectangle: - // x = [spanXMin, spanXMax + 1) (note: span coords are ints) - // y = [spanY, spanY + 1) - // against the clipping region: - // x = [xMin, xMax) (note: clipping coords are fp) - // y = [yMin, yMax) - if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin >= xMax || - (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY >= yMax) { - return splashClipAllOutside; - } - if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax && - (SplashCoord)spanY >= yMin && (SplashCoord)(spanY + 1) <= yMax)) { - return splashClipPartial; - } - if (antialias) { - for (i = 0; i < length; ++i) { - if (!scanners[i]->testSpan(spanXMin * splashAASize, - spanXMax * splashAASize + (splashAASize - 1), - spanY * splashAASize)) { - return splashClipPartial; - } - } - } else { - for (i = 0; i < length; ++i) { - if (!scanners[i]->testSpan(spanXMin, spanXMax, spanY)) { - return splashClipPartial; - } - } - } - return splashClipAllInside; -} - -void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) { - int xx0, xx1, xx, yy, i; - SplashColorPtr p; - - // zero out pixels with x < xMin - xx0 = *x0 * splashAASize; - xx1 = splashFloor(xMin * splashAASize); - if (xx1 > aaBuf->getWidth()) { - xx1 = aaBuf->getWidth(); - } - if (xx0 < xx1) { - xx0 &= ~7; - for (yy = 0; yy < splashAASize; ++yy) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3); - for (xx = xx0; xx + 7 < xx1; xx += 8) { - *p++ = 0; - } - if (xx < xx1) { - *p &= 0xff >> (xx1 & 7); - } - } - *x0 = splashFloor(xMin); - } - - // zero out pixels with x > xMax - xx0 = splashFloor(xMax * splashAASize) + 1; - if (xx0 < 0) { - xx0 = 0; - } - xx1 = (*x1 + 1) * splashAASize; - if (xx0 < xx1) { - for (yy = 0; yy < splashAASize; ++yy) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3); - xx = xx0; - if (xx & 7) { - *p &= 0xff00 >> (xx & 7); - xx = (xx & ~7) + 8; - ++p; - } - for (; xx < xx1; xx += 8) { - *p++ = 0; - } - } - *x1 = splashFloor(xMax); - } - - // check the paths - for (i = 0; i < length; ++i) { - scanners[i]->clipAALine(aaBuf, x0, x1, y); - } -} diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.cc b/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.cc deleted file mode 100644 index 9a4533a0376..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.cc +++ /dev/null @@ -1,188 +0,0 @@ -//======================================================================== -// -// SplashFTFontEngine.cc -// -//======================================================================== - -#include <aconf.h> - -#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#ifndef WIN32 -# include <unistd.h> -#endif -#include "gmem.h" -#include "GString.h" -#include "gfile.h" -#include "FoFiTrueType.h" -#include "FoFiType1C.h" -#include "SplashFTFontFile.h" -#include "SplashFTFontEngine.h" - -#ifdef VMS -#if (__VMS_VER < 70000000) -extern "C" int unlink(char *filename); -#endif -#endif - -//------------------------------------------------------------------------ - -static void fileWrite(void *stream, const char *data, int len) { - fwrite(data, 1, len, (FILE *)stream); -} - -//------------------------------------------------------------------------ -// SplashFTFontEngine -//------------------------------------------------------------------------ - -SplashFTFontEngine::SplashFTFontEngine(GBool aaA, Guint flagsA, - FT_Library libA) { - FT_Int major, minor, patch; - - aa = aaA; - flags = flagsA; - lib = libA; - - // as of FT 2.1.8, CID fonts are indexed by CID instead of GID - FT_Library_Version(lib, &major, &minor, &patch); - useCIDs = major > 2 || - (major == 2 && (minor > 1 || (minor == 1 && patch > 7))); -} - -SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA, Guint flagsA) { - FT_Library libA; - - if (FT_Init_FreeType(&libA)) { - return NULL; - } - return new SplashFTFontEngine(aaA, flagsA, libA); -} - -SplashFTFontEngine::~SplashFTFontEngine() { - FT_Done_FreeType(lib); -} - -SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA, - char *fileName, - GBool deleteFile, - const char **enc) { - return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc); -} - -SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA, - char *fileName, - GBool deleteFile, - const char **enc) { - return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc); -} - -SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, - char *fileName, - GBool deleteFile, - const char **enc) { - return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc); -} - -SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA, - char *fileName, - GBool deleteFile) { - FoFiType1C *ff; - int *cidToGIDMap; - int nCIDs; - SplashFontFile *ret; - - // check for a CFF font - if (useCIDs) { - cidToGIDMap = NULL; - nCIDs = 0; - } else if ((ff = FoFiType1C::load(fileName))) { - cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); - delete ff; - } else { - cidToGIDMap = NULL; - nCIDs = 0; - } - ret = SplashFTFontFile::loadCIDFont(this, idA, fileName, deleteFile, - cidToGIDMap, nCIDs); - if (!ret) { - gfree(cidToGIDMap); - } - return ret; -} - -SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, - char *fileName, - GBool deleteFile, - int *codeToGID, - int codeToGIDLen) { - FoFiTrueType *ff; - GBool isCID; - int *cidToGIDMap; - int nCIDs; - SplashFontFile *ret; - - cidToGIDMap = NULL; - nCIDs = 0; - isCID = gFalse; - if (!codeToGID) { - if (!useCIDs) { - if ((ff = FoFiTrueType::load(fileName))) { - if (ff->isOpenTypeCFF()) { - cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); - } - delete ff; - } - } - } - ret = SplashFTFontFile::loadCIDFont(this, idA, fileName, deleteFile, - codeToGID ? codeToGID : cidToGIDMap, - codeToGID ? codeToGIDLen : nCIDs); - if (!ret) { - gfree(cidToGIDMap); - } - return ret; -} - -SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA, - char *fileName, - int fontNum, - GBool deleteFile, - int *codeToGID, - int codeToGIDLen) { - FoFiTrueType *ff; - GString *tmpFileName; - FILE *tmpFile; - SplashFontFile *ret; - - //~ this should use fontNum to load the correct font - if (!(ff = FoFiTrueType::load(fileName))) { - return NULL; - } - tmpFileName = NULL; - if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { - delete ff; - return NULL; - } - ff->writeTTF(&fileWrite, tmpFile); - delete ff; - fclose(tmpFile); - ret = SplashFTFontFile::loadTrueTypeFont(this, idA, - tmpFileName->getCString(), fontNum, - gTrue, codeToGID, codeToGIDLen); - if (ret) { - if (deleteFile) { - unlink(fileName); - } - } else { - unlink(tmpFileName->getCString()); - } - delete tmpFileName; - return ret; -} - -#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.cc b/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.cc deleted file mode 100644 index abe45938eb8..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.cc +++ /dev/null @@ -1,538 +0,0 @@ -//======================================================================== -// -// SplashXPathScanner.cc -// -//======================================================================== - -#include <aconf.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdlib.h> -#include <string.h> -#if HAVE_STD_SORT -#include <algorithm> -#endif -#include "gmem.h" -#include "SplashMath.h" -#include "SplashXPath.h" -#include "SplashBitmap.h" -#include "SplashXPathScanner.h" - -//------------------------------------------------------------------------ - -struct SplashIntersect { - int y; - int x0, x1; // intersection of segment with [y, y+1) - int count; // EO/NZWN counter increment -}; - -#if HAVE_STD_SORT - -struct cmpIntersectFunctor { - bool operator()(const SplashIntersect &i0, const SplashIntersect &i1) { - return (i0.y != i1.y) ? (i0.y < i1.y) : (i0.x0 < i1.x0); - } -}; - -#else // HAVE_STD_SORT - -static int cmpIntersect(const void *p0, const void *p1) { - SplashIntersect *i0 = (SplashIntersect *)p0; - SplashIntersect *i1 = (SplashIntersect *)p1; - int cmp; - - if ((cmp = i0->y - i1->y) == 0) { - cmp = i0->x0 - i1->x0; - } - return cmp; -} - -#endif // HAVE_STD_SORT - -//------------------------------------------------------------------------ -// SplashXPathScanner -//------------------------------------------------------------------------ - -SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA, - int clipYMin, int clipYMax) { - SplashXPathSeg *seg; - SplashCoord xMinFP, yMinFP, xMaxFP, yMaxFP; - int i; - - xPath = xPathA; - eo = eoA; - partialClip = gFalse; - - // compute the bbox - if (xPath->length == 0) { - xMin = yMin = 1; - xMax = yMax = 0; - } else { - seg = &xPath->segs[0]; - if (seg->x0 <= seg->x1) { - xMinFP = seg->x0; - xMaxFP = seg->x1; - } else { - xMinFP = seg->x1; - xMaxFP = seg->x0; - } - if (seg->flags & splashXPathFlip) { - yMinFP = seg->y1; - yMaxFP = seg->y0; - } else { - yMinFP = seg->y0; - yMaxFP = seg->y1; - } - for (i = 1; i < xPath->length; ++i) { - seg = &xPath->segs[i]; - if (seg->x0 < xMinFP) { - xMinFP = seg->x0; - } else if (seg->x0 > xMaxFP) { - xMaxFP = seg->x0; - } - if (seg->x1 < xMinFP) { - xMinFP = seg->x1; - } else if (seg->x1 > xMaxFP) { - xMaxFP = seg->x1; - } - if (seg->flags & splashXPathFlip) { - if (seg->y0 > yMaxFP) { - yMaxFP = seg->y0; - } - } else { - if (seg->y1 > yMaxFP) { - yMaxFP = seg->y1; - } - } - } - xMin = splashFloor(xMinFP); - xMax = splashFloor(xMaxFP); - yMin = splashFloor(yMinFP); - yMax = splashFloor(yMaxFP); - if (clipYMin > yMin) { - yMin = clipYMin; - partialClip = gTrue; - } - if (clipYMax < yMax) { - yMax = clipYMax; - partialClip = gTrue; - } - } - - allInter = NULL; - inter = NULL; - computeIntersections(); - interY = yMin - 1; -} - -SplashXPathScanner::~SplashXPathScanner() { - gfree(inter); - gfree(allInter); -} - -void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA, - int *xMaxA, int *yMaxA) { - *xMinA = xMin / splashAASize; - *yMinA = yMin / splashAASize; - *xMaxA = xMax / splashAASize; - *yMaxA = yMax / splashAASize; -} - -void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) { - int interBegin, interEnd, xx, i; - - if (y < yMin || y > yMax) { - interBegin = interEnd = 0; - } else { - interBegin = inter[y - yMin]; - interEnd = inter[y - yMin + 1]; - } - if (interBegin < interEnd) { - *spanXMin = allInter[interBegin].x0; - xx = allInter[interBegin].x1; - for (i = interBegin + 1; i < interEnd; ++i) { - if (allInter[i].x1 > xx) { - xx = allInter[i].x1; - } - } - *spanXMax = xx; - } else { - *spanXMin = xMax + 1; - *spanXMax = xMax; - } -} - -GBool SplashXPathScanner::test(int x, int y) { - int interBegin, interEnd, count, i; - - if (y < yMin || y > yMax) { - return gFalse; - } - interBegin = inter[y - yMin]; - interEnd = inter[y - yMin + 1]; - count = 0; - for (i = interBegin; i < interEnd && allInter[i].x0 <= x; ++i) { - if (x <= allInter[i].x1) { - return gTrue; - } - count += allInter[i].count; - } - return eo ? (count & 1) : (count != 0); -} - -GBool SplashXPathScanner::testSpan(int x0, int x1, int y) { - int interBegin, interEnd, count, xx1, i; - - if (y < yMin || y > yMax) { - return gFalse; - } - interBegin = inter[y - yMin]; - interEnd = inter[y - yMin + 1]; - count = 0; - for (i = interBegin; i < interEnd && allInter[i].x1 < x0; ++i) { - count += allInter[i].count; - } - - // invariant: the subspan [x0,xx1] is inside the path - xx1 = x0 - 1; - while (xx1 < x1) { - if (i >= interEnd) { - return gFalse; - } - if (allInter[i].x0 > xx1 + 1 && - !(eo ? (count & 1) : (count != 0))) { - return gFalse; - } - if (allInter[i].x1 > xx1) { - xx1 = allInter[i].x1; - } - count += allInter[i].count; - ++i; - } - - return gTrue; -} - -GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) { - int interEnd, xx0, xx1; - - if (y < yMin || y > yMax) { - return gFalse; - } - if (interY != y) { - interY = y; - interIdx = inter[y - yMin]; - interCount = 0; - } - interEnd = inter[y - yMin + 1]; - if (interIdx >= interEnd) { - return gFalse; - } - xx0 = allInter[interIdx].x0; - xx1 = allInter[interIdx].x1; - interCount += allInter[interIdx].count; - ++interIdx; - while (interIdx < interEnd && - (allInter[interIdx].x0 <= xx1 || - (eo ? (interCount & 1) : (interCount != 0)))) { - if (allInter[interIdx].x1 > xx1) { - xx1 = allInter[interIdx].x1; - } - interCount += allInter[interIdx].count; - ++interIdx; - } - *x0 = xx0; - *x1 = xx1; - return gTrue; -} - -void SplashXPathScanner::computeIntersections() { - SplashXPathSeg *seg; - SplashCoord segXMin, segXMax, segYMin, segYMax, xx0, xx1; - int x, y, y0, y1, i; - - if (yMin > yMax) { - return; - } - - // build the list of all intersections - allInterLen = 0; - allInterSize = 16; - allInter = (SplashIntersect *)gmallocn(allInterSize, - sizeof(SplashIntersect)); - for (i = 0; i < xPath->length; ++i) { - seg = &xPath->segs[i]; - if (seg->flags & splashXPathFlip) { - segYMin = seg->y1; - segYMax = seg->y0; - } else { - segYMin = seg->y0; - segYMax = seg->y1; - } - if (seg->flags & splashXPathHoriz) { - y = splashFloor(seg->y0); - if (y >= yMin && y <= yMax) { - addIntersection(segYMin, segYMax, seg->flags, - y, splashFloor(seg->x0), splashFloor(seg->x1)); - } - } else if (seg->flags & splashXPathVert) { - y0 = splashFloor(segYMin); - if (y0 < yMin) { - y0 = yMin; - } - y1 = splashFloor(segYMax); - if (y1 > yMax) { - y1 = yMax; - } - x = splashFloor(seg->x0); - for (y = y0; y <= y1; ++y) { - addIntersection(segYMin, segYMax, seg->flags, y, x, x); - } - } else { - if (seg->x0 < seg->x1) { - segXMin = seg->x0; - segXMax = seg->x1; - } else { - segXMin = seg->x1; - segXMax = seg->x0; - } - y0 = splashFloor(segYMin); - if (y0 < yMin) { - y0 = yMin; - } - y1 = splashFloor(segYMax); - if (y1 > yMax) { - y1 = yMax; - } - // this loop could just add seg->dxdy to xx1 on each iteration, - // but that introduces numerical accuracy problems - xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy; - for (y = y0; y <= y1; ++y) { - xx0 = xx1; - xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy; - // the segment may not actually extend to the top and/or bottom edges - if (xx0 < segXMin) { - xx0 = segXMin; - } else if (xx0 > segXMax) { - xx0 = segXMax; - } - if (xx1 < segXMin) { - xx1 = segXMin; - } else if (xx1 > segXMax) { - xx1 = segXMax; - } - addIntersection(segYMin, segYMax, seg->flags, y, - splashFloor(xx0), splashFloor(xx1)); - } - } - } -#if HAVE_STD_SORT - std::sort(allInter, allInter + allInterLen, cmpIntersectFunctor()); -#else - qsort(allInter, allInterLen, sizeof(SplashIntersect), cmpIntersect); -#endif - - // build the list of y pointers - inter = (int *)gmallocn(yMax - yMin + 2, sizeof(int)); - i = 0; - for (y = yMin; y <= yMax; ++y) { - inter[y - yMin] = i; - while (i < allInterLen && allInter[i].y <= y) { - ++i; - } - } - inter[yMax - yMin + 1] = i; -} - -void SplashXPathScanner::addIntersection(double segYMin, double segYMax, - Guint segFlags, - int y, int x0, int x1) { - if (allInterLen == allInterSize) { - allInterSize *= 2; - allInter = (SplashIntersect *)greallocn(allInter, allInterSize, - sizeof(SplashIntersect)); - } - allInter[allInterLen].y = y; - if (x0 < x1) { - allInter[allInterLen].x0 = x0; - allInter[allInterLen].x1 = x1; - } else { - allInter[allInterLen].x0 = x1; - allInter[allInterLen].x1 = x0; - } - if (segYMin <= y && - (SplashCoord)y < segYMax && - !(segFlags & splashXPathHoriz)) { - allInter[allInterLen].count = eo ? 1 - : (segFlags & splashXPathFlip) ? 1 : -1; - } else { - allInter[allInterLen].count = 0; - } - ++allInterLen; -} - -void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf, - int *x0, int *x1, int y) { - int xx0, xx1, xx, xxMin, xxMax, yy, interEnd; - Guchar mask; - SplashColorPtr p; - - memset(aaBuf->getDataPtr(), 0, aaBuf->getRowSize() * aaBuf->getHeight()); - xxMin = aaBuf->getWidth(); - xxMax = -1; - if (yMin <= yMax) { - if (splashAASize * y < yMin) { - interIdx = inter[0]; - } else if (splashAASize * y > yMax) { - interIdx = inter[yMax - yMin + 1]; - } else { - interIdx = inter[splashAASize * y - yMin]; - } - for (yy = 0; yy < splashAASize; ++yy) { - if (splashAASize * y + yy < yMin) { - interEnd = inter[0]; - } else if (splashAASize * y + yy > yMax) { - interEnd = inter[yMax - yMin + 1]; - } else { - interEnd = inter[splashAASize * y + yy - yMin + 1]; - } - interCount = 0; - while (interIdx < interEnd) { - xx0 = allInter[interIdx].x0; - xx1 = allInter[interIdx].x1; - interCount += allInter[interIdx].count; - ++interIdx; - while (interIdx < interEnd && - (allInter[interIdx].x0 <= xx1 || - (eo ? (interCount & 1) : (interCount != 0)))) { - if (allInter[interIdx].x1 > xx1) { - xx1 = allInter[interIdx].x1; - } - interCount += allInter[interIdx].count; - ++interIdx; - } - if (xx0 < 0) { - xx0 = 0; - } - ++xx1; - if (xx1 > aaBuf->getWidth()) { - xx1 = aaBuf->getWidth(); - } - // set [xx0, xx1) to 1 - if (xx0 < xx1) { - xx = xx0; - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3); - if (xx & 7) { - mask = 0xff >> (xx & 7); - if ((xx & ~7) == (xx1 & ~7)) { - mask &= (Guchar)(0xff00 >> (xx1 & 7)); - } - *p++ |= mask; - xx = (xx & ~7) + 8; - } - for (; xx + 7 < xx1; xx += 8) { - *p++ |= 0xff; - } - if (xx < xx1) { - *p |= (Guchar)(0xff00 >> (xx1 & 7)); - } - } - if (xx0 < xxMin) { - xxMin = xx0; - } - if (xx1 > xxMax) { - xxMax = xx1; - } - } - } - } - *x0 = xxMin / splashAASize; - *x1 = (xxMax - 1) / splashAASize; -} - -void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf, - int *x0, int *x1, int y) { - int xx0, xx1, xx, yy, interEnd; - Guchar mask; - SplashColorPtr p; - - for (yy = 0; yy < splashAASize; ++yy) { - xx = *x0 * splashAASize; - if (yMin <= yMax) { - if (splashAASize * y + yy < yMin) { - interIdx = interEnd = inter[0]; - } else if (splashAASize * y + yy > yMax) { - interIdx = interEnd = inter[yMax - yMin + 1]; - } else { - interIdx = inter[splashAASize * y + yy - yMin]; - if (splashAASize * y + yy > yMax) { - interEnd = inter[yMax - yMin + 1]; - } else { - interEnd = inter[splashAASize * y + yy - yMin + 1]; - } - } - interCount = 0; - while (interIdx < interEnd && xx < (*x1 + 1) * splashAASize) { - xx0 = allInter[interIdx].x0; - xx1 = allInter[interIdx].x1; - interCount += allInter[interIdx].count; - ++interIdx; - while (interIdx < interEnd && - (allInter[interIdx].x0 <= xx1 || - (eo ? (interCount & 1) : (interCount != 0)))) { - if (allInter[interIdx].x1 > xx1) { - xx1 = allInter[interIdx].x1; - } - interCount += allInter[interIdx].count; - ++interIdx; - } - if (xx0 > aaBuf->getWidth()) { - xx0 = aaBuf->getWidth(); - } - // set [xx, xx0) to 0 - if (xx < xx0) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3); - if (xx & 7) { - mask = (Guchar)(0xff00 >> (xx & 7)); - if ((xx & ~7) == (xx0 & ~7)) { - mask |= 0xff >> (xx0 & 7); - } - *p++ &= mask; - xx = (xx & ~7) + 8; - } - for (; xx + 7 < xx0; xx += 8) { - *p++ = 0x00; - } - if (xx < xx0) { - *p &= 0xff >> (xx0 & 7); - } - } - if (xx1 >= xx) { - xx = xx1 + 1; - } - } - } - xx0 = (*x1 + 1) * splashAASize; - // set [xx, xx0) to 0 - if (xx < xx0) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3); - if (xx & 7) { - mask = (Guchar)(0xff00 >> (xx & 7)); - if ((xx & ~7) == (xx0 & ~7)) { - mask &= 0xff >> (xx0 & 7); - } - *p++ &= mask; - xx = (xx & ~7) + 8; - } - for (; xx + 7 < xx0; xx += 8) { - *p++ = 0x00; - } - if (xx < xx0) { - *p &= 0xff >> (xx0 & 7); - } - } - } -} diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.h b/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.h deleted file mode 100644 index 5bb3aaf4ea4..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPathScanner.h +++ /dev/null @@ -1,95 +0,0 @@ -//======================================================================== -// -// SplashXPathScanner.h -// -//======================================================================== - -#ifndef SPLASHXPATHSCANNER_H -#define SPLASHXPATHSCANNER_H - -#include <aconf.h> - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "SplashTypes.h" - -class SplashXPath; -class SplashBitmap; -struct SplashIntersect; - -//------------------------------------------------------------------------ -// SplashXPathScanner -//------------------------------------------------------------------------ - -class SplashXPathScanner { -public: - - // Create a new SplashXPathScanner object. <xPathA> must be sorted. - SplashXPathScanner(SplashXPath *xPathA, GBool eoA, - int clipYMin, int clipYMax); - - ~SplashXPathScanner(); - - // Return the path's bounding box. - void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) - { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } - - // Return the path's bounding box. - void getBBoxAA(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA); - - // Returns true if at least part of the path was outside the - // clipYMin/clipYMax bounds passed to the constructor. - GBool hasPartialClip() { return partialClip; } - - // Return the min/max x values for the span at <y>. - void getSpanBounds(int y, int *spanXMin, int *spanXMax); - - // Returns true if (<x>,<y>) is inside the path. - GBool test(int x, int y); - - // Returns true if the entire span ([<x0>,<x1>], <y>) is inside the - // path. - GBool testSpan(int x0, int x1, int y); - - // Returns the next span inside the path at <y>. If <y> is - // different than the previous call to getNextSpan, this returns the - // first span at <y>; otherwise it returns the next span (relative - // to the previous call to getNextSpan). Returns false if there are - // no more spans at <y>. - GBool getNextSpan(int y, int *x0, int *x1); - - // Renders one anti-aliased line into <aaBuf>. Returns the min and - // max x coordinates with non-zero pixels in <x0> and <x1>. - void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y); - - // Clips an anti-aliased line by setting pixels to zero. On entry, - // all non-zero pixels are between <x0> and <x1>. This function - // will update <x0> and <x1>. - void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y); - -private: - - void computeIntersections(); - void addIntersection(double segYMin, double segYMax, - Guint segFlags, - int y, int x0, int x1); - - SplashXPath *xPath; - GBool eo; - int xMin, yMin, xMax, yMax; - GBool partialClip; - - SplashIntersect *allInter; // array of intersections - int allInterLen; // number of intersections in <allInter> - int allInterSize; // size of the <allInter> array - int *inter; // indexes into <allInter> for each y value - int interY; // current y value - used by getNextSpan - int interIdx; // current index into <inter> - used by - // getNextSpan - int interCount; // current EO/NZWN counter - used by - // getNextSpan -}; - -#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.in b/Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.in deleted file mode 100644 index 5b48eff0498..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.in +++ /dev/null @@ -1,269 +0,0 @@ -#======================================================================== -# -# Xpdf Makefile -# -# Copyright 1996-2003 Glyph & Cog, LLC -# -#======================================================================== - -SHELL = /bin/sh - -prefix = @prefix@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -GOOSRCDIR = $(srcdir)/../goo -GOOLIBDIR = ../goo -FOFISRCDIR = $(srcdir)/../fofi -FOFILIBDIR = ../fofi -SPLASHSRCDIR = $(srcdir)/../splash -SPLASHLIBDIR = ../splash - -CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(GOOSRCDIR) -I$(FOFISRCDIR) -I$(SPLASHSRCDIR) -I$(srcdir) @freetype2_CFLAGS@ @Sgm_CFLAGS@ @Xm_CFLAGS@ @Xt_CFLAGS@ @Xp_CFLAGS@ @Xext_CFLAGS@ @Xpm_CFLAGS@ @t1_CFLAGS@ @libpaper_CFLAGS@ @X_CFLAGS@ - -LDFLAGS = @LDFLAGS@ - -T1LIBS = @t1_LIBS@ -FTLIBS = @freetype2_LIBS@ - -XLIBS = @Sgm_LIBS@ @Xm_LIBS@ @Xt_LIBS@ @Xp_LIBS@ @Xext_LIBS@ @Xpm_LIBS@ @X_PRE_LIBS@ @X_LIBS@ -lX11 @X_EXTRA_LIBS@ - -SPLASHLIBS = -L$(SPLASHLIBDIR) -lsplash - -OTHERLIBS = @LIBS@ @libpaper_LIBS@ \ - -L$(FOFILIBDIR) -lfofi \ - -L$(GOOLIBDIR) -lGoo - -CXX = @CXX@ - -LIBPREFIX = @LIBPREFIX@ -EXE = @EXE@ - -#------------------------------------------------------------------------ - -.SUFFIXES: .cc - -.cc.o: - $(CXX) $(CXXFLAGS) -c $< - -#------------------------------------------------------------------------ - -CXX_SRC = \ - $(srcdir)/Annot.cc \ - $(srcdir)/Array.cc \ - $(srcdir)/BuiltinFont.cc \ - $(srcdir)/BuiltinFontTables.cc \ - $(srcdir)/CMap.cc \ - $(srcdir)/Catalog.cc \ - $(srcdir)/CharCodeToUnicode.cc \ - $(srcdir)/CoreOutputDev.cc \ - $(srcdir)/Decrypt.cc \ - $(srcdir)/Dict.cc \ - $(srcdir)/Error.cc \ - $(srcdir)/FontEncodingTables.cc \ - $(srcdir)/Function.cc \ - $(srcdir)/Gfx.cc \ - $(srcdir)/GfxFont.cc \ - $(srcdir)/GfxState.cc \ - $(srcdir)/GlobalParams.cc \ - $(srcdir)/ImageOutputDev.cc \ - $(srcdir)/JArithmeticDecoder.cc \ - $(srcdir)/JBIG2Stream.cc \ - $(srcdir)/JPXStream.cc \ - $(srcdir)/Lexer.cc \ - $(srcdir)/Link.cc \ - $(srcdir)/NameToCharCode.cc \ - $(srcdir)/Object.cc \ - $(srcdir)/OptionalContent.cc \ - $(srcdir)/Outline.cc \ - $(srcdir)/OutputDev.cc \ - $(srcdir)/PDFCore.cc \ - $(srcdir)/PDFDoc.cc \ - $(srcdir)/PDFDocEncoding.cc \ - $(srcdir)/PSOutputDev.cc \ - $(srcdir)/PSTokenizer.cc \ - $(srcdir)/Page.cc \ - $(srcdir)/Parser.cc \ - $(srcdir)/PreScanOutputDev.cc \ - $(srcdir)/SecurityHandler.cc \ - $(srcdir)/SplashOutputDev.cc \ - $(srcdir)/Stream.cc \ - $(srcdir)/TextOutputDev.cc \ - $(srcdir)/UnicodeMap.cc \ - $(srcdir)/UnicodeTypeTable.cc \ - $(srcdir)/XPDFApp.cc \ - $(srcdir)/XPDFCore.cc \ - $(srcdir)/XPDFTree.cc \ - $(srcdir)/XPDFViewer.cc \ - $(srcdir)/XpdfPluginAPI.cc \ - $(srcdir)/XRef.cc \ - $(srcdir)/pdftops.cc \ - $(srcdir)/pdftotext.cc \ - $(srcdir)/pdfinfo.cc \ - $(srcdir)/pdffonts.cc \ - $(srcdir)/pdfdetach.cc \ - $(srcdir)/pdftoppm.cc \ - $(srcdir)/pdfimages.cc \ - $(srcdir)/xpdf.cc - -#------------------------------------------------------------------------ - -all: xpdf$(EXE) pdftops$(EXE) pdftotext$(EXE) pdfinfo$(EXE) \ - pdffonts$(EXE) pdfdetach$(EXE) pdftoppm$(EXE) pdfimages$(EXE) - -all-no-x: pdftops$(EXE) pdftotext$(EXE) pdfinfo$(EXE) pdffonts$(EXE) \ - pdfdetach$(EXE) pdfimages$(EXE) - -#------------------------------------------------------------------------ - -XPDF_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o Catalog.o \ - CharCodeToUnicode.o CMap.o CoreOutputDev.o Decrypt.o Dict.o \ - Error.o FontEncodingTables.o Function.o Gfx.o GfxFont.o \ - GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \ - JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \ - OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFCore.o \ - PDFDoc.o PDFDocEncoding.o PreScanOutputDev.o PSOutputDev.o \ - PSTokenizer.o SecurityHandler.o SplashOutputDev.o Stream.o \ - TextOutputDev.o UnicodeMap.o UnicodeTypeTable.o XPDFApp.o \ - XPDFCore.o XPDFTree.o XPDFViewer.o XpdfPluginAPI.o XRef.o xpdf.o -XPDF_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(T1LIBS) $(FTLIBS) \ - $(XLIBS) $(OTHERLIBS) -lm - -xpdf$(EXE): $(XPDF_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o xpdf$(EXE) $(XPDF_OBJS) $(XPDF_LIBS) - -#------------------------------------------------------------------------ - -PDFTOPS_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o \ - GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \ - JPXStream.o Lexer.o Link.o NameToCharCode.o OptionalContent.o \ - Outline.o Object.o OutputDev.o Page.o Parser.o PDFDoc.o \ - PDFDocEncoding.o PreScanOutputDev.o PSOutputDev.o PSTokenizer.o \ - SecurityHandler.o SplashOutputDev.o Stream.o UnicodeMap.o \ - XpdfPluginAPI.o XRef.o pdftops.o -PDFTOPS_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(T1LIBS) $(FTLIBS) \ - $(OTHERLIBS) -lm - -pdftops$(EXE): $(PDFTOPS_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftops$(EXE) $(PDFTOPS_OBJS) \ - $(PDFTOPS_LIBS) - -#------------------------------------------------------------------------ - -PDFTOTEXT_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o \ - GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \ - JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \ - OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \ - PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \ - TextOutputDev.o UnicodeMap.o UnicodeTypeTable.o XpdfPluginAPI.o \ - XRef.o pdftotext.o -PDFTOTEXT_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm - -pdftotext$(EXE): $(PDFTOTEXT_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftotext$(EXE) $(PDFTOTEXT_OBJS) \ - $(PDFTOTEXT_LIBS) - -#------------------------------------------------------------------------ - -PDFINFO_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o \ - GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \ - JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \ - OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \ - PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \ - UnicodeMap.o XpdfPluginAPI.o XRef.o pdfinfo.o -PDFINFO_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm - -pdfinfo$(EXE): $(PDFINFO_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfinfo$(EXE) $(PDFINFO_OBJS) \ - $(PDFINFO_LIBS) - -#------------------------------------------------------------------------ - -PDFFONTS_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o \ - GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \ - JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \ - OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \ - PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \ - UnicodeMap.o XpdfPluginAPI.o XRef.o pdffonts.o -PDFFONTS_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm - -pdffonts$(EXE): $(PDFFONTS_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdffonts$(EXE) $(PDFFONTS_OBJS) \ - $(PDFFONTS_LIBS) - -#------------------------------------------------------------------------ - -PDFDETACH_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o \ - GfxState.o GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o \ - JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \ - OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \ - PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \ - UnicodeMap.o XpdfPluginAPI.o XRef.o pdfdetach.o -PDFDETACH_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm - -pdfdetach$(EXE): $(PDFDETACH_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfdetach$(EXE) $(PDFDETACH_OBJS) \ - $(PDFDETACH_LIBS) - -#------------------------------------------------------------------------ - -PDFTOPPM_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o GfxState.o \ - GlobalParams.o JArithmeticDecoder.o JBIG2Stream.o JPXStream.o \ - Lexer.o Link.o NameToCharCode.o Object.o OptionalContent.o \ - Outline.o OutputDev.o Page.o Parser.o PDFDoc.o PDFDocEncoding.o \ - PSTokenizer.o SecurityHandler.o SplashOutputDev.o Stream.o \ - TextOutputDev.o UnicodeMap.o UnicodeTypeTable.o XpdfPluginAPI.o \ - XRef.o pdftoppm.o -PDFTOPPM_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(T1LIBS) $(FTLIBS) \ - $(OTHERLIBS) -lm - -pdftoppm$(EXE): $(PDFTOPPM_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftoppm$(EXE) $(PDFTOPPM_OBJS) \ - $(PDFTOPPM_LIBS) - -#------------------------------------------------------------------------ - -PDFIMAGES_OBJS = Annot.o Array.o BuiltinFont.o BuiltinFontTables.o \ - Catalog.o CharCodeToUnicode.o CMap.o Decrypt.o Dict.o Error.o \ - FontEncodingTables.o Function.o Gfx.o GfxFont.o GfxState.o \ - GlobalParams.o ImageOutputDev.o JArithmeticDecoder.o \ - JBIG2Stream.o JPXStream.o Lexer.o Link.o NameToCharCode.o Object.o \ - OptionalContent.o Outline.o OutputDev.o Page.o Parser.o PDFDoc.o \ - PDFDocEncoding.o PSTokenizer.o SecurityHandler.o Stream.o \ - UnicodeMap.o XpdfPluginAPI.o XRef.o pdfimages.o -PDFIMAGES_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm - -pdfimages$(EXE): $(PDFIMAGES_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfimages$(EXE) $(PDFIMAGES_OBJS) \ - $(PDFIMAGES_LIBS) - -#------------------------------------------------------------------------ - -clean: - rm -f $(XPDF_OBJS) xpdf$(EXE) - rm -f $(PDFTOPS_OBJS) pdftops$(EXE) - rm -f $(PDFTOTEXT_OBJS) pdftotext$(EXE) - rm -f $(PDFINFO_OBJS) pdfinfo$(EXE) - rm -f $(PDFFONTS_OBJS) pdffonts$(EXE) - rm -f $(PDFDETACH_OBJS) pdfdetach$(EXE) - rm -f $(PDFTOPPM_OBJS) pdftoppm$(EXE) - rm -f $(PDFIMAGES_OBJS) pdfimages$(EXE) - -#------------------------------------------------------------------------ - -depend: - $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep - -include Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.cc deleted file mode 100644 index 971a3fe0941..00000000000 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.cc +++ /dev/null @@ -1,4330 +0,0 @@ -//======================================================================== -// -// TextOutputDev.cc -// -// Copyright 1997-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include <aconf.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <math.h> -#include <ctype.h> -#ifdef WIN32 -#include <fcntl.h> // for O_BINARY -#include <io.h> // for setmode -#endif -#include "gmem.h" -#include "GString.h" -#include "GList.h" -#include "config.h" -#include "Error.h" -#include "GlobalParams.h" -#include "UnicodeMap.h" -#include "UnicodeTypeTable.h" -#include "GfxState.h" -#include "Link.h" -#include "TextOutputDev.h" - -#ifdef MACOS -// needed for setting type/creator of MacOS files -#include "ICSupport.h" -#endif - -//------------------------------------------------------------------------ -// parameters -//------------------------------------------------------------------------ - -// Each bucket in a text pool includes baselines within a range of -// this many points. -#define textPoolStep 4 - -// Inter-character space width which will cause addChar to start a new -// word. -#define minWordBreakSpace 0.1 - -// Negative inter-character space width, i.e., overlap, which will -// cause addChar to start a new word. -#define minDupBreakOverlap 0.2 - -// Max distance between baselines of two lines within a block, as a -// fraction of the font size. -#define maxLineSpacingDelta 1.5 - -// Max difference in primary font sizes on two lines in the same -// block. Delta1 is used when examining new lines above and below the -// current block; delta2 is used when examining text that overlaps the -// current block; delta3 is used when examining text to the left and -// right of the current block. -#define maxBlockFontSizeDelta1 0.05 -#define maxBlockFontSizeDelta2 0.6 -#define maxBlockFontSizeDelta3 0.2 - -// Max difference in font sizes inside a word. -#define maxWordFontSizeDelta 0.05 - -// Maximum distance between baselines of two words on the same line, -// e.g., distance between subscript or superscript and the primary -// baseline, as a fraction of the font size. -#define maxIntraLineDelta 0.5 - -// Minimum inter-word spacing, as a fraction of the font size. (Only -// used for raw ordering.) -#define minWordSpacing 0.15 - -// Maximum inter-word spacing, as a fraction of the font size. -#define maxWordSpacing 1.5 - -// Maximum horizontal spacing which will allow a word to be pulled -// into a block. -#define minColSpacing1 0.3 - -// Minimum spacing between columns, as a fraction of the font size. -#define minColSpacing2 1.0 - -// Maximum vertical spacing between blocks within a flow, as a -// multiple of the font size. -#define maxBlockSpacing 2.5 - -// Minimum spacing between characters within a word, as a fraction of -// the font size. -#define minCharSpacing -0.2 - -// Maximum spacing between characters within a word, as a fraction of -// the font size, when there is no obvious extra-wide character -// spacing. -#define maxCharSpacing 0.03 - -// When extra-wide character spacing is detected, the inter-character -// space threshold is set to the minimum inter-character space -// multiplied by this constant. -#define maxWideCharSpacingMul 1.3 - -// Upper limit on spacing between characters in a word. -#define maxWideCharSpacing 0.4 - -// 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. -#define dupMaxPriDelta 0.1 -#define dupMaxSecDelta 0.2 - -// Max width of underlines (in points). -#define maxUnderlineWidth 3 - -// Min distance between baseline and underline (in points). -//~ this should be font-size-dependent -#define minUnderlineGap -2 - -// Max distance between baseline and underline (in points). -//~ this should be font-size-dependent -#define maxUnderlineGap 4 - -// Max horizontal distance between edge of word and start of underline -// (in points). -//~ this should be font-size-dependent -#define underlineSlack 1 - -// Max distance between edge of text and edge of link border -#define hyperlinkSlack 2 - -//------------------------------------------------------------------------ -// TextUnderline -//------------------------------------------------------------------------ - -class TextUnderline { -public: - - TextUnderline(double x0A, double y0A, double x1A, double y1A) - { x0 = x0A; y0 = y0A; x1 = x1A; y1 = y1A; horiz = y0 == y1; } - ~TextUnderline() {} - - double x0, y0, x1, y1; - GBool horiz; -}; - -//------------------------------------------------------------------------ -// TextLink -//------------------------------------------------------------------------ - -class TextLink { -public: - - TextLink(int xMinA, int yMinA, int xMaxA, int yMaxA, Link *linkA) - { xMin = xMinA; yMin = yMinA; xMax = xMaxA; yMax = yMaxA; link = linkA; } - ~TextLink() {} - - int xMin, yMin, xMax, yMax; - Link *link; -}; - -//------------------------------------------------------------------------ -// TextFontInfo -//------------------------------------------------------------------------ - -TextFontInfo::TextFontInfo(GfxState *state) { - gfxFont = state->getFont(); -#if TEXTOUT_WORD_LIST - fontName = (gfxFont && gfxFont->getName()) ? gfxFont->getName()->copy() - : (GString *)NULL; - flags = gfxFont ? gfxFont->getFlags() : 0; -#endif -} - -TextFontInfo::~TextFontInfo() { -#if TEXTOUT_WORD_LIST - if (fontName) { - delete fontName; - } -#endif -} - -GBool TextFontInfo::matches(GfxState *state) { - return state->getFont() == gfxFont; -} - -//------------------------------------------------------------------------ -// TextWord -//------------------------------------------------------------------------ - -TextWord::TextWord(GfxState *state, int rotA, double x0, double y0, - TextFontInfo *fontA, double fontSizeA) { - GfxFont *gfxFont; - double x, y, ascent, descent; - int wMode; - - rot = rotA; - font = fontA; - fontSize = fontSizeA; - state->transform(x0, y0, &x, &y); - if ((gfxFont = font->gfxFont)) { - ascent = gfxFont->getAscent() * fontSize; - descent = gfxFont->getDescent() * fontSize; - wMode = gfxFont->getWMode(); - } else { - // this means that the PDF file draws text without a current font, - // which should never happen - ascent = 0.95 * fontSize; - descent = -0.35 * fontSize; - wMode = 0; - } - if (wMode) { // vertical writing mode - // NB: the rotation value has been incremented by 1 (in - // TextPage::beginWord()) for vertical writing mode - switch (rot) { - case 0: - yMin = y - fontSize; - yMax = y; - base = y; - break; - case 1: - xMin = x; - xMax = x + fontSize; - base = x; - break; - case 2: - yMin = y; - yMax = y + fontSize; - base = y; - break; - case 3: - xMin = x - fontSize; - xMax = x; - base = x; - break; - } - } else { // horizontal writing mode - switch (rot) { - case 0: - yMin = y - ascent; - yMax = y - descent; - if (yMin == yMax) { - // this is a sanity check for a case that shouldn't happen -- but - // if it does happen, we want to avoid dividing by zero later - yMin = y; - yMax = y + 1; - } - base = y; - break; - case 1: - xMin = x + descent; - xMax = x + ascent; - if (xMin == xMax) { - // this is a sanity check for a case that shouldn't happen -- but - // if it does happen, we want to avoid dividing by zero later - xMin = x; - xMax = x + 1; - } - base = x; - break; - case 2: - yMin = y + descent; - yMax = y + ascent; - if (yMin == yMax) { - // this is a sanity check for a case that shouldn't happen -- but - // if it does happen, we want to avoid dividing by zero later - yMin = y; - yMax = y + 1; - } - base = y; - break; - case 3: - xMin = x - ascent; - xMax = x - descent; - if (xMin == xMax) { - // this is a sanity check for a case that shouldn't happen -- but - // if it does happen, we want to avoid dividing by zero later - xMin = x; - xMax = x + 1; - } - base = x; - break; - } - } - text = NULL; - edge = NULL; - charPos = NULL; - len = size = 0; - spaceAfter = gFalse; - next = NULL; - -#if TEXTOUT_WORD_LIST - GfxRGB rgb; - - if ((state->getRender() & 3) == 1) { - state->getStrokeRGB(&rgb); - } else { - state->getFillRGB(&rgb); - } - colorR = colToDbl(rgb.r); - colorG = colToDbl(rgb.g); - colorB = colToDbl(rgb.b); -#endif - - underlined = gFalse; - link = NULL; -} - -TextWord::~TextWord() { - gfree(text); - gfree(edge); - gfree(charPos); -} - -void TextWord::addChar(GfxState *state, double x, double y, - double dx, double dy, int charPosA, int charLen, - Unicode u) { - int wMode; - - if (len == size) { - size += 16; - text = (Unicode *)greallocn(text, size, sizeof(Unicode)); - edge = (double *)greallocn(edge, size + 1, sizeof(double)); - charPos = (int *)greallocn(charPos, size + 1, sizeof(int)); - } - text[len] = u; - charPos[len] = charPosA; - charPos[len + 1] = charPosA + charLen; - wMode = font->gfxFont ? font->gfxFont->getWMode() : 0; - if (wMode) { // vertical writing mode - // NB: the rotation value has been incremented by 1 (in - // TextPage::beginWord()) for vertical writing mode - switch (rot) { - case 0: - if (len == 0) { - xMin = x - fontSize; - } - edge[len] = x - fontSize; - xMax = edge[len+1] = x; - break; - case 1: - if (len == 0) { - yMin = y - fontSize; - } - edge[len] = y - fontSize; - yMax = edge[len+1] = y; - break; - case 2: - if (len == 0) { - xMax = x + fontSize; - } - edge[len] = x + fontSize; - xMin = edge[len+1] = x; - break; - case 3: - if (len == 0) { - yMax = y + fontSize; - } - edge[len] = y + fontSize; - yMin = edge[len+1] = y; - break; - } - } else { // horizontal writing mode - switch (rot) { - case 0: - if (len == 0) { - xMin = x; - } - edge[len] = x; - xMax = edge[len+1] = x + dx; - break; - case 1: - if (len == 0) { - yMin = y; - } - edge[len] = y; - yMax = edge[len+1] = y + dy; - break; - case 2: - if (len == 0) { - xMax = x; - } - edge[len] = x; - xMin = edge[len+1] = x + dx; - break; - case 3: - if (len == 0) { - yMax = y; - } - edge[len] = y; - yMin = edge[len+1] = y + dy; - break; - } - } - ++len; -} - -void TextWord::merge(TextWord *word) { - int i; - - if (word->xMin < xMin) { - xMin = word->xMin; - } - if (word->yMin < yMin) { - yMin = word->yMin; - } - if (word->xMax > xMax) { - xMax = word->xMax; - } - if (word->yMax > yMax) { - yMax = word->yMax; - } - if (len + word->len > size) { - size = len + word->len; - text = (Unicode *)greallocn(text, size, sizeof(Unicode)); - edge = (double *)greallocn(edge, size + 1, sizeof(double)); - charPos = (int *)greallocn(charPos, size + 1, sizeof(int)); - } - for (i = 0; i < word->len; ++i) { - text[len + i] = word->text[i]; - edge[len + i] = word->edge[i]; - charPos[len + i] = word->charPos[i]; - } - edge[len + word->len] = word->edge[word->len]; - charPos[len + word->len] = word->charPos[word->len]; - len += word->len; -} - -inline int TextWord::primaryCmp(TextWord *word) { - double cmp; - - cmp = 0; // make gcc happy - switch (rot) { - case 0: - cmp = xMin - word->xMin; - break; - case 1: - cmp = yMin - word->yMin; - break; - case 2: - cmp = word->xMax - xMax; - break; - case 3: - cmp = word->yMax - yMax; - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -double TextWord::primaryDelta(TextWord *word) { - double delta; - - delta = 0; // make gcc happy - switch (rot) { - case 0: - delta = word->xMin - xMax; - break; - case 1: - delta = word->yMin - yMax; - break; - case 2: - delta = xMin - word->xMax; - break; - case 3: - delta = yMin - word->yMax; - break; - } - return delta; -} - -int TextWord::cmpYX(const void *p1, const void *p2) { - TextWord *word1 = *(TextWord **)p1; - TextWord *word2 = *(TextWord **)p2; - double cmp; - - cmp = word1->yMin - word2->yMin; - if (cmp == 0) { - cmp = word1->xMin - word2->xMin; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -#if TEXTOUT_WORD_LIST - -GString *TextWord::getText() { - GString *s; - UnicodeMap *uMap; - char buf[8]; - int n, i; - - s = new GString(); - if (!(uMap = globalParams->getTextEncoding())) { - return s; - } - for (i = 0; i < len; ++i) { - n = uMap->mapUnicode(text[i], buf, sizeof(buf)); - s->append(buf, n); - } - uMap->decRefCnt(); - return s; -} - -void TextWord::getCharBBox(int charIdx, double *xMinA, double *yMinA, - double *xMaxA, double *yMaxA) { - if (charIdx < 0 || charIdx >= len) { - return; - } - switch (rot) { - case 0: - *xMinA = edge[charIdx]; - *xMaxA = edge[charIdx + 1]; - *yMinA = yMin; - *yMaxA = yMax; - break; - case 1: - *xMinA = xMin; - *xMaxA = xMax; - *yMinA = edge[charIdx]; - *yMaxA = edge[charIdx + 1]; - break; - case 2: - *xMinA = edge[charIdx + 1]; - *xMaxA = edge[charIdx]; - *yMinA = yMin; - *yMaxA = yMax; - break; - case 3: - *xMinA = xMin; - *xMaxA = xMax; - *yMinA = edge[charIdx + 1]; - *yMaxA = edge[charIdx]; - break; - } -} - -#endif // TEXTOUT_WORD_LIST - -//------------------------------------------------------------------------ -// TextPool -//------------------------------------------------------------------------ - -TextPool::TextPool() { - minBaseIdx = 0; - maxBaseIdx = -1; - pool = NULL; - cursor = NULL; - cursorBaseIdx = -1; -} - -TextPool::~TextPool() { - int baseIdx; - TextWord *word, *word2; - - for (baseIdx = minBaseIdx; baseIdx <= maxBaseIdx; ++baseIdx) { - for (word = pool[baseIdx - minBaseIdx]; word; word = word2) { - word2 = word->next; - delete word; - } - } - gfree(pool); -} - -int TextPool::getBaseIdx(double base) { - int baseIdx; - - baseIdx = (int)(base / textPoolStep); - if (baseIdx < minBaseIdx) { - return minBaseIdx; - } - if (baseIdx > maxBaseIdx) { - return maxBaseIdx; - } - return baseIdx; -} - -void TextPool::addWord(TextWord *word) { - TextWord **newPool; - int wordBaseIdx, newMinBaseIdx, newMaxBaseIdx, baseIdx; - TextWord *w0, *w1; - - // expand the array if needed - wordBaseIdx = (int)(word->base / textPoolStep); - if (minBaseIdx > maxBaseIdx) { - minBaseIdx = wordBaseIdx - 128; - maxBaseIdx = wordBaseIdx + 128; - pool = (TextWord **)gmallocn(maxBaseIdx - minBaseIdx + 1, - sizeof(TextWord *)); - for (baseIdx = minBaseIdx; baseIdx <= maxBaseIdx; ++baseIdx) { - pool[baseIdx - minBaseIdx] = NULL; - } - } else if (wordBaseIdx < minBaseIdx) { - newMinBaseIdx = wordBaseIdx - 128; - newPool = (TextWord **)gmallocn(maxBaseIdx - newMinBaseIdx + 1, - sizeof(TextWord *)); - for (baseIdx = newMinBaseIdx; baseIdx < minBaseIdx; ++baseIdx) { - newPool[baseIdx - newMinBaseIdx] = NULL; - } - memcpy(&newPool[minBaseIdx - newMinBaseIdx], pool, - (maxBaseIdx - minBaseIdx + 1) * sizeof(TextWord *)); - gfree(pool); - pool = newPool; - minBaseIdx = newMinBaseIdx; - } else if (wordBaseIdx > maxBaseIdx) { - newMaxBaseIdx = wordBaseIdx + 128; - pool = (TextWord **)greallocn(pool, newMaxBaseIdx - minBaseIdx + 1, - sizeof(TextWord *)); - for (baseIdx = maxBaseIdx + 1; baseIdx <= newMaxBaseIdx; ++baseIdx) { - pool[baseIdx - minBaseIdx] = NULL; - } - maxBaseIdx = newMaxBaseIdx; - } - - // insert the new word - if (cursor && wordBaseIdx == cursorBaseIdx && - word->primaryCmp(cursor) >= 0) { - w0 = cursor; - w1 = cursor->next; - } else { - w0 = NULL; - w1 = pool[wordBaseIdx - minBaseIdx]; - } - for (; w1 && word->primaryCmp(w1) > 0; w0 = w1, w1 = w1->next) ; - word->next = w1; - if (w0) { - w0->next = word; - } else { - pool[wordBaseIdx - minBaseIdx] = word; - } - cursor = word; - cursorBaseIdx = wordBaseIdx; -} - -//------------------------------------------------------------------------ -// TextLine -//------------------------------------------------------------------------ - -TextLine::TextLine(TextBlock *blkA, int rotA, double baseA) { - blk = blkA; - rot = rotA; - xMin = yMin = 0; - xMax = yMax = -1; - base = baseA; - words = lastWord = NULL; - text = NULL; - edge = NULL; - col = NULL; - len = 0; - convertedLen = 0; - hyphenated = gFalse; - next = NULL; -} - -TextLine::~TextLine() { - TextWord *word; - - while (words) { - word = words; - words = words->next; - delete word; - } - gfree(text); - gfree(edge); - gfree(col); -} - -void TextLine::addWord(TextWord *word) { - if (lastWord) { - lastWord->next = word; - } else { - words = word; - } - lastWord = word; - - if (xMin > xMax) { - xMin = word->xMin; - xMax = word->xMax; - yMin = word->yMin; - yMax = word->yMax; - } else { - if (word->xMin < xMin) { - xMin = word->xMin; - } - if (word->xMax > xMax) { - xMax = word->xMax; - } - if (word->yMin < yMin) { - yMin = word->yMin; - } - if (word->yMax > yMax) { - yMax = word->yMax; - } - } -} - -double TextLine::primaryDelta(TextLine *line) { - double delta; - - delta = 0; // make gcc happy - switch (rot) { - case 0: - delta = line->xMin - xMax; - break; - case 1: - delta = line->yMin - yMax; - break; - case 2: - delta = xMin - line->xMax; - break; - case 3: - delta = yMin - line->yMax; - break; - } - return delta; -} - -int TextLine::primaryCmp(TextLine *line) { - double cmp; - - cmp = 0; // make gcc happy - switch (rot) { - case 0: - cmp = xMin - line->xMin; - break; - case 1: - cmp = yMin - line->yMin; - break; - case 2: - cmp = line->xMax - xMax; - break; - case 3: - cmp = line->yMax - yMax; - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextLine::secondaryCmp(TextLine *line) { - double cmp; - - cmp = (rot == 0 || rot == 3) ? base - line->base : line->base - base; - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextLine::cmpYX(TextLine *line) { - int cmp; - - if ((cmp = secondaryCmp(line))) { - return cmp; - } - return primaryCmp(line); -} - -int TextLine::cmpXY(const void *p1, const void *p2) { - TextLine *line1 = *(TextLine **)p1; - TextLine *line2 = *(TextLine **)p2; - int cmp; - - if ((cmp = line1->primaryCmp(line2))) { - return cmp; - } - return line1->secondaryCmp(line2); -} - -void TextLine::coalesce(UnicodeMap *uMap) { - TextWord *word0, *word1; - double space, delta, minSpace; - GBool isUnicode; - char buf[8]; - int i, j; - - if (words->next) { - - // compute the inter-word space threshold - if (words->len > 1 || words->next->len > 1) { - minSpace = 0; - } else { - minSpace = words->primaryDelta(words->next); - for (word0 = words->next, word1 = word0->next; - word1 && minSpace > 0; - word0 = word1, word1 = word0->next) { - if (word1->len > 1) { - minSpace = 0; - } - delta = word0->primaryDelta(word1); - if (delta < minSpace) { - minSpace = delta; - } - } - } - if (minSpace <= 0) { - space = maxCharSpacing * words->fontSize; - } else { - space = maxWideCharSpacingMul * minSpace; - if (space > maxWideCharSpacing * words->fontSize) { - space = maxWideCharSpacing * words->fontSize; - } - } - - // merge words - word0 = words; - word1 = words->next; - while (word1) { - if (word0->primaryDelta(word1) >= space) { - word0->spaceAfter = gTrue; - word0 = word1; - word1 = word1->next; - } else if (word0->font == word1->font && - word0->underlined == word1->underlined && - fabs(word0->fontSize - word1->fontSize) < - maxWordFontSizeDelta * words->fontSize && - word1->charPos[0] == word0->charPos[word0->len]) { - word0->merge(word1); - word0->next = word1->next; - delete word1; - word1 = word0->next; - } else { - word0 = word1; - word1 = word1->next; - } - } - } - - // build the line text - isUnicode = uMap ? uMap->isUnicode() : gFalse; - len = 0; - for (word1 = words; word1; word1 = word1->next) { - len += word1->len; - if (word1->spaceAfter) { - ++len; - } - } - text = (Unicode *)gmallocn(len, sizeof(Unicode)); - edge = (double *)gmallocn(len + 1, sizeof(double)); - i = 0; - for (word1 = words; word1; word1 = word1->next) { - for (j = 0; j < word1->len; ++j) { - text[i] = word1->text[j]; - edge[i] = word1->edge[j]; - ++i; - } - edge[i] = word1->edge[word1->len]; - if (word1->spaceAfter) { - text[i] = (Unicode)0x0020; - ++i; - } - } - - // compute convertedLen and set up the col array - col = (int *)gmallocn(len + 1, sizeof(int)); - convertedLen = 0; - for (i = 0; i < len; ++i) { - col[i] = convertedLen; - if (isUnicode) { - ++convertedLen; - } else if (uMap) { - convertedLen += uMap->mapUnicode(text[i], buf, sizeof(buf)); - } - } - col[len] = convertedLen; - - // check for hyphen at end of line - //~ need to check for other chars used as hyphens - hyphenated = text[len - 1] == (Unicode)'-'; -} - -//------------------------------------------------------------------------ -// TextLineFrag -//------------------------------------------------------------------------ - -class TextLineFrag { -public: - - TextLine *line; // the line object - int start, len; // offset and length of this fragment - // (in Unicode chars) - double xMin, xMax; // bounding box coordinates - double yMin, yMax; - double base; // baseline virtual coordinate - int col; // first column - - void init(TextLine *lineA, int startA, int lenA); - void computeCoords(GBool oneRot); - - static int cmpYXPrimaryRot(const void *p1, const void *p2); - static int cmpYXLineRot(const void *p1, const void *p2); - static int cmpXYLineRot(const void *p1, const void *p2); - static int cmpXYColumnPrimaryRot(const void *p1, const void *p2); - static int cmpXYColumnLineRot(const void *p1, const void *p2); -}; - -void TextLineFrag::init(TextLine *lineA, int startA, int lenA) { - line = lineA; - start = startA; - len = lenA; - col = line->col[start]; -} - -void TextLineFrag::computeCoords(GBool oneRot) { - TextBlock *blk; - double d0, d1, d2, d3, d4; - - if (oneRot) { - - switch (line->rot) { - case 0: - xMin = line->edge[start]; - xMax = line->edge[start + len]; - yMin = line->yMin; - yMax = line->yMax; - break; - case 1: - xMin = line->xMin; - xMax = line->xMax; - yMin = line->edge[start]; - yMax = line->edge[start + len]; - break; - case 2: - xMin = line->edge[start + len]; - xMax = line->edge[start]; - yMin = line->yMin; - yMax = line->yMax; - break; - case 3: - xMin = line->xMin; - xMax = line->xMax; - yMin = line->edge[start + len]; - yMax = line->edge[start]; - break; - } - base = line->base; - - } else { - - if (line->rot == 0 && line->blk->page->primaryRot == 0) { - - xMin = line->edge[start]; - xMax = line->edge[start + len]; - yMin = line->yMin; - yMax = line->yMax; - base = line->base; - - } else { - - blk = line->blk; - d0 = line->edge[start]; - d1 = line->edge[start + len]; - d2 = d3 = d4 = 0; // make gcc happy - - switch (line->rot) { - case 0: - d2 = line->yMin; - d3 = line->yMax; - d4 = line->base; - d0 = (d0 - blk->xMin) / (blk->xMax - blk->xMin); - d1 = (d1 - blk->xMin) / (blk->xMax - blk->xMin); - d2 = (d2 - blk->yMin) / (blk->yMax - blk->yMin); - d3 = (d3 - blk->yMin) / (blk->yMax - blk->yMin); - d4 = (d4 - blk->yMin) / (blk->yMax - blk->yMin); - break; - case 1: - d2 = line->xMax; - d3 = line->xMin; - d4 = line->base; - d0 = (d0 - blk->yMin) / (blk->yMax - blk->yMin); - d1 = (d1 - blk->yMin) / (blk->yMax - blk->yMin); - d2 = (blk->xMax - d2) / (blk->xMax - blk->xMin); - d3 = (blk->xMax - d3) / (blk->xMax - blk->xMin); - d4 = (blk->xMax - d4) / (blk->xMax - blk->xMin); - break; - case 2: - d2 = line->yMax; - d3 = line->yMin; - d4 = line->base; - d0 = (blk->xMax - d0) / (blk->xMax - blk->xMin); - d1 = (blk->xMax - d1) / (blk->xMax - blk->xMin); - d2 = (blk->yMax - d2) / (blk->yMax - blk->yMin); - d3 = (blk->yMax - d3) / (blk->yMax - blk->yMin); - d4 = (blk->yMax - d4) / (blk->yMax - blk->yMin); - break; - case 3: - d2 = line->xMin; - d3 = line->xMax; - d4 = line->base; - d0 = (blk->yMax - d0) / (blk->yMax - blk->yMin); - d1 = (blk->yMax - d1) / (blk->yMax - blk->yMin); - d2 = (d2 - blk->xMin) / (blk->xMax - blk->xMin); - d3 = (d3 - blk->xMin) / (blk->xMax - blk->xMin); - d4 = (d4 - blk->xMin) / (blk->xMax - blk->xMin); - break; - } - - switch (line->blk->page->primaryRot) { - case 0: - xMin = blk->xMin + d0 * (blk->xMax - blk->xMin); - xMax = blk->xMin + d1 * (blk->xMax - blk->xMin); - yMin = blk->yMin + d2 * (blk->yMax - blk->yMin); - yMax = blk->yMin + d3 * (blk->yMax - blk->yMin); - base = blk->yMin + d4 * (blk->yMax - blk->yMin); - break; - case 1: - xMin = blk->xMax - d3 * (blk->xMax - blk->xMin); - xMax = blk->xMax - d2 * (blk->xMax - blk->xMin); - yMin = blk->yMin + d0 * (blk->yMax - blk->yMin); - yMax = blk->yMin + d1 * (blk->yMax - blk->yMin); - base = blk->xMax - d4 * (blk->xMax - blk->xMin); - break; - case 2: - xMin = blk->xMax - d1 * (blk->xMax - blk->xMin); - xMax = blk->xMax - d0 * (blk->xMax - blk->xMin); - yMin = blk->yMax - d3 * (blk->yMax - blk->yMin); - yMax = blk->yMax - d2 * (blk->yMax - blk->yMin); - base = blk->yMax - d4 * (blk->yMax - blk->yMin); - break; - case 3: - xMin = blk->xMin + d2 * (blk->xMax - blk->xMin); - xMax = blk->xMin + d3 * (blk->xMax - blk->xMin); - yMin = blk->yMax - d1 * (blk->yMax - blk->yMin); - yMax = blk->yMax - d0 * (blk->yMax - blk->yMin); - base = blk->xMin + d4 * (blk->xMax - blk->xMin); - break; - } - - } - } -} - -int TextLineFrag::cmpYXPrimaryRot(const void *p1, const void *p2) { - TextLineFrag *frag1 = (TextLineFrag *)p1; - TextLineFrag *frag2 = (TextLineFrag *)p2; - double cmp; - - cmp = 0; // make gcc happy - switch (frag1->line->blk->page->primaryRot) { - case 0: - if (fabs(cmp = frag1->yMin - frag2->yMin) < 0.01) { - cmp = frag1->xMin - frag2->xMin; - } - break; - case 1: - if (fabs(cmp = frag2->xMax - frag1->xMax) < 0.01) { - cmp = frag1->yMin - frag2->yMin; - } - break; - case 2: - if (fabs(cmp = frag2->yMin - frag1->yMin) < 0.01) { - cmp = frag2->xMax - frag1->xMax; - } - break; - case 3: - if (fabs(cmp = frag1->xMax - frag2->xMax) < 0.01) { - cmp = frag2->yMax - frag1->yMax; - } - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextLineFrag::cmpYXLineRot(const void *p1, const void *p2) { - TextLineFrag *frag1 = (TextLineFrag *)p1; - TextLineFrag *frag2 = (TextLineFrag *)p2; - double cmp; - - cmp = 0; // make gcc happy - switch (frag1->line->rot) { - case 0: - if ((cmp = frag1->yMin - frag2->yMin) == 0) { - cmp = frag1->xMin - frag2->xMin; - } - break; - case 1: - if ((cmp = frag2->xMax - frag1->xMax) == 0) { - cmp = frag1->yMin - frag2->yMin; - } - break; - case 2: - if ((cmp = frag2->yMin - frag1->yMin) == 0) { - cmp = frag2->xMax - frag1->xMax; - } - break; - case 3: - if ((cmp = frag1->xMax - frag2->xMax) == 0) { - cmp = frag2->yMax - frag1->yMax; - } - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextLineFrag::cmpXYLineRot(const void *p1, const void *p2) { - TextLineFrag *frag1 = (TextLineFrag *)p1; - TextLineFrag *frag2 = (TextLineFrag *)p2; - double cmp; - - cmp = 0; // make gcc happy - switch (frag1->line->rot) { - case 0: - if ((cmp = frag1->xMin - frag2->xMin) == 0) { - cmp = frag1->yMin - frag2->yMin; - } - break; - case 1: - if ((cmp = frag1->yMin - frag2->yMin) == 0) { - cmp = frag2->xMax - frag1->xMax; - } - break; - case 2: - if ((cmp = frag2->xMax - frag1->xMax) == 0) { - cmp = frag2->yMin - frag1->yMin; - } - break; - case 3: - if ((cmp = frag2->yMax - frag1->yMax) == 0) { - cmp = frag1->xMax - frag2->xMax; - } - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextLineFrag::cmpXYColumnPrimaryRot(const void *p1, const void *p2) { - TextLineFrag *frag1 = (TextLineFrag *)p1; - TextLineFrag *frag2 = (TextLineFrag *)p2; - double cmp; - - // if columns overlap, compare y values - if (frag1->col < frag2->col + (frag2->line->col[frag2->start + frag2->len] - - frag2->line->col[frag2->start]) && - frag2->col < frag1->col + (frag1->line->col[frag1->start + frag1->len] - - frag1->line->col[frag1->start])) { - cmp = 0; // make gcc happy - switch (frag1->line->blk->page->primaryRot) { - case 0: cmp = frag1->yMin - frag2->yMin; break; - case 1: cmp = frag2->xMax - frag1->xMax; break; - case 2: cmp = frag2->yMin - frag1->yMin; break; - case 3: cmp = frag1->xMax - frag2->xMax; break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; - } - - // otherwise, compare starting column - return frag1->col - frag2->col; -} - -int TextLineFrag::cmpXYColumnLineRot(const void *p1, const void *p2) { - TextLineFrag *frag1 = (TextLineFrag *)p1; - TextLineFrag *frag2 = (TextLineFrag *)p2; - double cmp; - - // if columns overlap, compare y values - if (frag1->col < frag2->col + (frag2->line->col[frag2->start + frag2->len] - - frag2->line->col[frag2->start]) && - frag2->col < frag1->col + (frag1->line->col[frag1->start + frag1->len] - - frag1->line->col[frag1->start])) { - cmp = 0; // make gcc happy - switch (frag1->line->rot) { - case 0: cmp = frag1->yMin - frag2->yMin; break; - case 1: cmp = frag2->xMax - frag1->xMax; break; - case 2: cmp = frag2->yMin - frag1->yMin; break; - case 3: cmp = frag1->xMax - frag2->xMax; break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; - } - - // otherwise, compare starting column - return frag1->col - frag2->col; -} - -//------------------------------------------------------------------------ -// TextBlock -//------------------------------------------------------------------------ - -TextBlock::TextBlock(TextPage *pageA, int rotA) { - page = pageA; - rot = rotA; - xMin = yMin = 0; - xMax = yMax = -1; - priMin = 0; - priMax = page->pageWidth; - pool = new TextPool(); - lines = NULL; - curLine = NULL; - next = NULL; - stackNext = NULL; -} - -TextBlock::~TextBlock() { - TextLine *line; - - delete pool; - while (lines) { - line = lines; - lines = lines->next; - delete line; - } -} - -void TextBlock::addWord(TextWord *word) { - pool->addWord(word); - if (xMin > xMax) { - xMin = word->xMin; - xMax = word->xMax; - yMin = word->yMin; - yMax = word->yMax; - } else { - if (word->xMin < xMin) { - xMin = word->xMin; - } - if (word->xMax > xMax) { - xMax = word->xMax; - } - if (word->yMin < yMin) { - yMin = word->yMin; - } - if (word->yMax > yMax) { - yMax = word->yMax; - } - } -} - -void TextBlock::coalesce(UnicodeMap *uMap, double fixedPitch) { - TextWord *word0, *word1, *word2, *bestWord0, *bestWord1, *lastWord; - TextLine *line, *line0, *line1; - int poolMinBaseIdx, startBaseIdx, minBaseIdx, maxBaseIdx; - int baseIdx, bestWordBaseIdx, idx0, idx1; - double minBase, maxBase; - double fontSize, wordSpacing, delta, priDelta, secDelta; - TextLine **lineArray; - GBool found, overlap; - int col1, col2; - int i, j, k; - - // discard duplicated text (fake boldface, drop shadows) - for (idx0 = pool->minBaseIdx; idx0 <= pool->maxBaseIdx; ++idx0) { - word0 = pool->getPool(idx0); - while (word0) { - priDelta = dupMaxPriDelta * word0->fontSize; - secDelta = dupMaxSecDelta * word0->fontSize; - maxBaseIdx = pool->getBaseIdx(word0->base + secDelta); - found = gFalse; - word1 = word2 = NULL; // make gcc happy - for (idx1 = idx0; idx1 <= maxBaseIdx; ++idx1) { - if (idx1 == idx0) { - word1 = word0; - word2 = word0->next; - } else { - word1 = NULL; - word2 = pool->getPool(idx1); - } - for (; word2; word1 = word2, word2 = word2->next) { - if (word2->len == word0->len && - !memcmp(word2->text, word0->text, - word0->len * sizeof(Unicode))) { - switch (rot) { - case 0: - case 2: - found = fabs(word0->xMin - word2->xMin) < priDelta && - fabs(word0->xMax - word2->xMax) < priDelta && - fabs(word0->yMin - word2->yMin) < secDelta && - fabs(word0->yMax - word2->yMax) < secDelta; - break; - case 1: - case 3: - found = fabs(word0->xMin - word2->xMin) < secDelta && - fabs(word0->xMax - word2->xMax) < secDelta && - fabs(word0->yMin - word2->yMin) < priDelta && - fabs(word0->yMax - word2->yMax) < priDelta; - break; - } - } - if (found) { - break; - } - } - if (found) { - break; - } - } - if (found) { - if (word1) { - word1->next = word2->next; - } else { - pool->setPool(idx1, word2->next); - } - delete word2; - } else { - word0 = word0->next; - } - } - } - - // build the lines - curLine = NULL; - poolMinBaseIdx = pool->minBaseIdx; - charCount = 0; - nLines = 0; - while (1) { - - // find the first non-empty line in the pool - for (; - poolMinBaseIdx <= pool->maxBaseIdx && !pool->getPool(poolMinBaseIdx); - ++poolMinBaseIdx) ; - if (poolMinBaseIdx > pool->maxBaseIdx) { - break; - } - - // look for the left-most word in the first four lines of the - // pool -- this avoids starting with a superscript word - startBaseIdx = poolMinBaseIdx; - for (baseIdx = poolMinBaseIdx + 1; - baseIdx < poolMinBaseIdx + 4 && baseIdx <= pool->maxBaseIdx; - ++baseIdx) { - if (!pool->getPool(baseIdx)) { - continue; - } - if (pool->getPool(baseIdx)->primaryCmp(pool->getPool(startBaseIdx)) - < 0) { - startBaseIdx = baseIdx; - } - } - - // create a new line - word0 = pool->getPool(startBaseIdx); - pool->setPool(startBaseIdx, word0->next); - word0->next = NULL; - line = new TextLine(this, word0->rot, word0->base); - line->addWord(word0); - lastWord = word0; - - // compute the search range - fontSize = word0->fontSize; - minBase = word0->base - maxIntraLineDelta * fontSize; - maxBase = word0->base + maxIntraLineDelta * fontSize; - minBaseIdx = pool->getBaseIdx(minBase); - maxBaseIdx = pool->getBaseIdx(maxBase); - wordSpacing = fixedPitch ? fixedPitch : maxWordSpacing * fontSize; - - // find the rest of the words in this line - while (1) { - - // find the left-most word whose baseline is in the range for - // this line - bestWordBaseIdx = 0; - bestWord0 = bestWord1 = NULL; - overlap = gFalse; - for (baseIdx = minBaseIdx; - !overlap && baseIdx <= maxBaseIdx; - ++baseIdx) { - for (word0 = NULL, word1 = pool->getPool(baseIdx); - word1; - word0 = word1, word1 = word1->next) { - if (word1->base >= minBase && - word1->base <= maxBase) { - delta = lastWord->primaryDelta(word1); - if (delta < minCharSpacing * fontSize) { - overlap = gTrue; - break; - } else { - if (delta < wordSpacing && - (!bestWord1 || word1->primaryCmp(bestWord1) < 0)) { - bestWordBaseIdx = baseIdx; - bestWord0 = word0; - bestWord1 = word1; - } - break; - } - } - } - } - if (overlap || !bestWord1) { - break; - } - - // remove it from the pool, and add it to the line - if (bestWord0) { - bestWord0->next = bestWord1->next; - } else { - pool->setPool(bestWordBaseIdx, bestWord1->next); - } - bestWord1->next = NULL; - line->addWord(bestWord1); - lastWord = bestWord1; - } - - // add the line - if (curLine && line->cmpYX(curLine) > 0) { - line0 = curLine; - line1 = curLine->next; - } else { - line0 = NULL; - line1 = lines; - } - for (; - line1 && line->cmpYX(line1) > 0; - line0 = line1, line1 = line1->next) ; - if (line0) { - line0->next = line; - } else { - lines = line; - } - line->next = line1; - curLine = line; - line->coalesce(uMap); - charCount += line->len; - ++nLines; - } - - // sort lines into xy order for column assignment - lineArray = (TextLine **)gmallocn(nLines, sizeof(TextLine *)); - for (line = lines, i = 0; line; line = line->next, ++i) { - lineArray[i] = line; - } - qsort(lineArray, nLines, sizeof(TextLine *), &TextLine::cmpXY); - - // column assignment - nColumns = 0; - if (fixedPitch) { - for (i = 0; i < nLines; ++i) { - line0 = lineArray[i]; - col1 = 0; // make gcc happy - switch (rot) { - case 0: - col1 = (int)((line0->xMin - xMin) / fixedPitch + 0.5); - break; - case 1: - col1 = (int)((line0->yMin - yMin) / fixedPitch + 0.5); - break; - case 2: - col1 = (int)((xMax - line0->xMax) / fixedPitch + 0.5); - break; - case 3: - col1 = (int)((yMax - line0->yMax) / fixedPitch + 0.5); - break; - } - for (k = 0; k <= line0->len; ++k) { - line0->col[k] += col1; - } - if (line0->col[line0->len] > nColumns) { - nColumns = line0->col[line0->len]; - } - } - } else { - for (i = 0; i < nLines; ++i) { - line0 = lineArray[i]; - col1 = 0; - for (j = 0; j < i; ++j) { - line1 = lineArray[j]; - if (line1->primaryDelta(line0) >= 0) { - col2 = line1->col[line1->len] + 1; - } else { - k = 0; // make gcc happy - switch (rot) { - case 0: - for (k = 0; - k < line1->len && - line0->xMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]); - ++k) ; - break; - case 1: - for (k = 0; - k < line1->len && - line0->yMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]); - ++k) ; - break; - case 2: - for (k = 0; - k < line1->len && - line0->xMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]); - ++k) ; - break; - case 3: - for (k = 0; - k < line1->len && - line0->yMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]); - ++k) ; - break; - } - col2 = line1->col[k]; - } - if (col2 > col1) { - col1 = col2; - } - } - for (k = 0; k <= line0->len; ++k) { - line0->col[k] += col1; - } - if (line0->col[line0->len] > nColumns) { - nColumns = line0->col[line0->len]; - } - } - } - gfree(lineArray); -} - -void TextBlock::updatePriMinMax(TextBlock *blk) { - double newPriMin, newPriMax; - GBool gotPriMin, gotPriMax; - - gotPriMin = gotPriMax = gFalse; - newPriMin = newPriMax = 0; // make gcc happy - switch (page->primaryRot) { - case 0: - case 2: - if (blk->yMin < yMax && blk->yMax > yMin) { - if (blk->xMin < xMin) { - newPriMin = blk->xMax; - gotPriMin = gTrue; - } - if (blk->xMax > xMax) { - newPriMax = blk->xMin; - gotPriMax = gTrue; - } - } - break; - case 1: - case 3: - if (blk->xMin < xMax && blk->xMax > xMin) { - if (blk->yMin < yMin) { - newPriMin = blk->yMax; - gotPriMin = gTrue; - } - if (blk->yMax > yMax) { - newPriMax = blk->yMin; - gotPriMax = gTrue; - } - } - break; - } - if (gotPriMin) { - if (newPriMin > xMin) { - newPriMin = xMin; - } - if (newPriMin > priMin) { - priMin = newPriMin; - } - } - if (gotPriMax) { - if (newPriMax < xMax) { - newPriMax = xMax; - } - if (newPriMax < priMax) { - priMax = newPriMax; - } - } -} - -int TextBlock::cmpXYPrimaryRot(const void *p1, const void *p2) { - TextBlock *blk1 = *(TextBlock **)p1; - TextBlock *blk2 = *(TextBlock **)p2; - double cmp; - - cmp = 0; // make gcc happy - switch (blk1->page->primaryRot) { - case 0: - if ((cmp = blk1->xMin - blk2->xMin) == 0) { - cmp = blk1->yMin - blk2->yMin; - } - break; - case 1: - if ((cmp = blk1->yMin - blk2->yMin) == 0) { - cmp = blk2->xMax - blk1->xMax; - } - break; - case 2: - if ((cmp = blk2->xMax - blk1->xMax) == 0) { - cmp = blk2->yMin - blk1->yMin; - } - break; - case 3: - if ((cmp = blk2->yMax - blk1->yMax) == 0) { - cmp = blk1->xMax - blk2->xMax; - } - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextBlock::cmpYXPrimaryRot(const void *p1, const void *p2) { - TextBlock *blk1 = *(TextBlock **)p1; - TextBlock *blk2 = *(TextBlock **)p2; - double cmp; - - cmp = 0; // make gcc happy - switch (blk1->page->primaryRot) { - case 0: - if ((cmp = blk1->yMin - blk2->yMin) == 0) { - cmp = blk1->xMin - blk2->xMin; - } - break; - case 1: - if ((cmp = blk2->xMax - blk1->xMax) == 0) { - cmp = blk1->yMin - blk2->yMin; - } - break; - case 2: - if ((cmp = blk2->yMin - blk1->yMin) == 0) { - cmp = blk2->xMax - blk1->xMax; - } - break; - case 3: - if ((cmp = blk1->xMax - blk2->xMax) == 0) { - cmp = blk2->yMax - blk1->yMax; - } - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -int TextBlock::primaryCmp(TextBlock *blk) { - double cmp; - - cmp = 0; // make gcc happy - switch (rot) { - case 0: - cmp = xMin - blk->xMin; - break; - case 1: - cmp = yMin - blk->yMin; - break; - case 2: - cmp = blk->xMax - xMax; - break; - case 3: - cmp = blk->yMax - yMax; - break; - } - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -double TextBlock::secondaryDelta(TextBlock *blk) { - double delta; - - delta = 0; // make gcc happy - switch (rot) { - case 0: - delta = blk->yMin - yMax; - break; - case 1: - delta = xMin - blk->xMax; - break; - case 2: - delta = yMin - blk->yMax; - break; - case 3: - delta = blk->xMin - xMax; - break; - } - return delta; -} - -GBool TextBlock::isBelow(TextBlock *blk) { - GBool below; - - below = gFalse; // make gcc happy - switch (page->primaryRot) { - case 0: - below = xMin >= blk->priMin && xMax <= blk->priMax && - yMin > blk->yMin; - break; - case 1: - below = yMin >= blk->priMin && yMax <= blk->priMax && - xMax < blk->xMax; - break; - case 2: - below = xMin >= blk->priMin && xMax <= blk->priMax && - yMax < blk->yMax; - break; - case 3: - below = yMin >= blk->priMin && yMax <= blk->priMax && - xMin > blk->xMin; - break; - } - - return below; -} - -//------------------------------------------------------------------------ -// TextFlow -//------------------------------------------------------------------------ - -TextFlow::TextFlow(TextPage *pageA, TextBlock *blk) { - page = pageA; - xMin = blk->xMin; - xMax = blk->xMax; - yMin = blk->yMin; - yMax = blk->yMax; - priMin = blk->priMin; - priMax = blk->priMax; - blocks = lastBlk = blk; - next = NULL; -} - -TextFlow::~TextFlow() { - TextBlock *blk; - - while (blocks) { - blk = blocks; - blocks = blocks->next; - delete blk; - } -} - -void TextFlow::addBlock(TextBlock *blk) { - if (lastBlk) { - lastBlk->next = blk; - } else { - blocks = blk; - } - lastBlk = blk; - if (blk->xMin < xMin) { - xMin = blk->xMin; - } - if (blk->xMax > xMax) { - xMax = blk->xMax; - } - if (blk->yMin < yMin) { - yMin = blk->yMin; - } - if (blk->yMax > yMax) { - yMax = blk->yMax; - } -} - -GBool TextFlow::blockFits(TextBlock *blk, TextBlock *prevBlk) { - GBool fits; - - // lower blocks must use smaller fonts - if (blk->lines->words->fontSize > lastBlk->lines->words->fontSize) { - return gFalse; - } - - fits = gFalse; // make gcc happy - switch (page->primaryRot) { - case 0: - fits = blk->xMin >= priMin && blk->xMax <= priMax; - break; - case 1: - fits = blk->yMin >= priMin && blk->yMax <= priMax; - break; - case 2: - fits = blk->xMin >= priMin && blk->xMax <= priMax; - break; - case 3: - fits = blk->yMin >= priMin && blk->yMax <= priMax; - break; - } - return fits; -} - -#if TEXTOUT_WORD_LIST - -//------------------------------------------------------------------------ -// TextWordList -//------------------------------------------------------------------------ - -TextWordList::TextWordList(TextPage *text, GBool physLayout) { - TextFlow *flow; - TextBlock *blk; - TextLine *line; - TextWord *word; - TextWord **wordArray; - int nWords, i; - - words = new GList(); - - if (text->rawOrder) { - for (word = text->rawWords; word; word = word->next) { - words->append(word); - } - - } else if (physLayout) { - // this is inefficient, but it's also the least useful of these - // three cases - nWords = 0; - for (flow = text->flows; flow; flow = flow->next) { - for (blk = flow->blocks; blk; blk = blk->next) { - for (line = blk->lines; line; line = line->next) { - for (word = line->words; word; word = word->next) { - ++nWords; - } - } - } - } - wordArray = (TextWord **)gmallocn(nWords, sizeof(TextWord *)); - i = 0; - for (flow = text->flows; flow; flow = flow->next) { - for (blk = flow->blocks; blk; blk = blk->next) { - for (line = blk->lines; line; line = line->next) { - for (word = line->words; word; word = word->next) { - wordArray[i++] = word; - } - } - } - } - qsort(wordArray, nWords, sizeof(TextWord *), &TextWord::cmpYX); - for (i = 0; i < nWords; ++i) { - words->append(wordArray[i]); - } - gfree(wordArray); - - } else { - for (flow = text->flows; flow; flow = flow->next) { - for (blk = flow->blocks; blk; blk = blk->next) { - for (line = blk->lines; line; line = line->next) { - for (word = line->words; word; word = word->next) { - words->append(word); - } - } - } - } - } -} - -TextWordList::~TextWordList() { - delete words; -} - -int TextWordList::getLength() { - return words->getLength(); -} - -TextWord *TextWordList::get(int idx) { - if (idx < 0 || idx >= words->getLength()) { - return NULL; - } - return (TextWord *)words->get(idx); -} - -#endif // TEXTOUT_WORD_LIST - -//------------------------------------------------------------------------ -// TextPage -//------------------------------------------------------------------------ - -TextPage::TextPage(GBool rawOrderA) { - int rot; - - rawOrder = rawOrderA; - curWord = NULL; - charPos = 0; - curFont = NULL; - curFontSize = 0; - nest = 0; - nTinyChars = 0; - lastCharOverlap = gFalse; - actualText = NULL; - actualTextLen = 0; - actualTextNBytes = 0; - if (!rawOrder) { - for (rot = 0; rot < 4; ++rot) { - pools[rot] = new TextPool(); - } - } - flows = NULL; - blocks = NULL; - rawWords = NULL; - rawLastWord = NULL; - fonts = new GList(); - lastFindXMin = lastFindYMin = 0; - haveLastFind = gFalse; - underlines = new GList(); - links = new GList(); -} - -TextPage::~TextPage() { - int rot; - - clear(); - if (!rawOrder) { - for (rot = 0; rot < 4; ++rot) { - delete pools[rot]; - } - } - delete fonts; - deleteGList(underlines, TextUnderline); - deleteGList(links, TextLink); -} - -void TextPage::startPage(GfxState *state) { - clear(); - if (state) { - pageWidth = state->getPageWidth(); - pageHeight = state->getPageHeight(); - } else { - pageWidth = pageHeight = 0; - } -} - -void TextPage::endPage() { - if (curWord) { - endWord(); - } -} - -void TextPage::clear() { - int rot; - TextFlow *flow; - TextWord *word; - - if (curWord) { - delete curWord; - curWord = NULL; - } - gfree(actualText); - if (rawOrder) { - while (rawWords) { - word = rawWords; - rawWords = rawWords->next; - delete word; - } - } else { - for (rot = 0; rot < 4; ++rot) { - delete pools[rot]; - } - while (flows) { - flow = flows; - flows = flows->next; - delete flow; - } - gfree(blocks); - } - deleteGList(fonts, TextFontInfo); - deleteGList(underlines, TextUnderline); - deleteGList(links, TextLink); - - curWord = NULL; - charPos = 0; - curFont = NULL; - curFontSize = 0; - nest = 0; - nTinyChars = 0; - actualText = NULL; - actualTextLen = 0; - actualTextNBytes = 0; - if (!rawOrder) { - for (rot = 0; rot < 4; ++rot) { - pools[rot] = new TextPool(); - } - } - flows = NULL; - blocks = NULL; - rawWords = NULL; - rawLastWord = NULL; - fonts = new GList(); - underlines = new GList(); - links = new GList(); -} - -void TextPage::updateFont(GfxState *state) { - GfxFont *gfxFont; - double *fm; - char *name; - int code, mCode, letterCode, anyCode; - double w; - int i; - - // get the font info object - curFont = NULL; - for (i = 0; i < fonts->getLength(); ++i) { - curFont = (TextFontInfo *)fonts->get(i); - if (curFont->matches(state)) { - break; - } - curFont = NULL; - } - if (!curFont) { - curFont = new TextFontInfo(state); - fonts->append(curFont); - } - - // adjust the font size - gfxFont = state->getFont(); - curFontSize = state->getTransformedFontSize(); - if (gfxFont && gfxFont->getType() == fontType3) { - // This is a hack which makes it possible to deal with some Type 3 - // fonts. The problem is that it's impossible to know what the - // base coordinate system used in the font is without actually - // rendering the font. This code tries to guess by looking at the - // width of the character 'm' (which breaks if the font is a - // subset that doesn't contain 'm'). - mCode = letterCode = anyCode = -1; - for (code = 0; code < 256; ++code) { - name = ((Gfx8BitFont *)gfxFont)->getCharName(code); - if (name && name[0] == 'm' && name[1] == '\0') { - mCode = code; - } - if (letterCode < 0 && name && name[1] == '\0' && - ((name[0] >= 'A' && name[0] <= 'Z') || - (name[0] >= 'a' && name[0] <= 'z'))) { - letterCode = code; - } - if (anyCode < 0 && name && - ((Gfx8BitFont *)gfxFont)->getWidth(code) > 0) { - anyCode = code; - } - } - if (mCode >= 0 && - (w = ((Gfx8BitFont *)gfxFont)->getWidth(mCode)) > 0) { - // 0.6 is a generic average 'm' width -- yes, this is a hack - curFontSize *= w / 0.6; - } else if (letterCode >= 0 && - (w = ((Gfx8BitFont *)gfxFont)->getWidth(letterCode)) > 0) { - // even more of a hack: 0.5 is a generic letter width - curFontSize *= w / 0.5; - } else if (anyCode >= 0 && - (w = ((Gfx8BitFont *)gfxFont)->getWidth(anyCode)) > 0) { - // better than nothing: 0.5 is a generic character width - curFontSize *= w / 0.5; - } - fm = gfxFont->getFontMatrix(); - if (fm[0] != 0) { - curFontSize *= fabs(fm[3] / fm[0]); - } - } -} - -void TextPage::beginWord(GfxState *state, double x0, double y0) { - double *fontm; - double m[4], m2[4]; - int rot; - - // This check is needed because Type 3 characters can contain - // text-drawing operations (when TextPage is being used via - // {X,Win}SplashOutputDev rather than TextOutputDev). - if (curWord) { - ++nest; - return; - } - - // compute the rotation - state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]); - if (state->getFont()->getType() == fontType3) { - fontm = state->getFont()->getFontMatrix(); - m2[0] = fontm[0] * m[0] + fontm[1] * m[2]; - m2[1] = fontm[0] * m[1] + fontm[1] * m[3]; - m2[2] = fontm[2] * m[0] + fontm[3] * m[2]; - m2[3] = fontm[2] * m[1] + fontm[3] * m[3]; - m[0] = m2[0]; - m[1] = m2[1]; - m[2] = m2[2]; - m[3] = m2[3]; - } - if (fabs(m[0] * m[3]) > fabs(m[1] * m[2])) { - rot = (m[0] > 0 || m[3] < 0) ? 0 : 2; - } else { - rot = (m[2] > 0) ? 1 : 3; - } - - // for vertical writing mode, the lines are effectively rotated 90 - // degrees - if (state->getFont()->getWMode()) { - rot = (rot + 1) & 3; - } - - curWord = new TextWord(state, rot, x0, y0, curFont, curFontSize); -} - -void TextPage::addChar(GfxState *state, double x, double y, - double dx, double dy, - CharCode c, int nBytes, Unicode *u, int uLen) { - double x1, y1, w1, h1, dx2, dy2, base, sp, delta; - GBool overlap; - int i; - - // if we're in an ActualText span, save the position info (the - // ActualText chars will be added by TextPage::endActualText()). - if (actualText) { - if (!actualTextNBytes) { - actualTextX0 = x; - actualTextY0 = y; - } - actualTextX1 = x + dx; - actualTextY1 = y + dy; - actualTextNBytes += nBytes; - return; - } - - // subtract char and word spacing from the dx,dy values - sp = state->getCharSpace(); - if (c == (CharCode)0x20) { - sp += state->getWordSpace(); - } - state->textTransformDelta(sp * state->getHorizScaling(), 0, &dx2, &dy2); - dx -= dx2; - dy -= dy2; - state->transformDelta(dx, dy, &w1, &h1); - - // throw away chars that aren't inside the page bounds - // (and also do a sanity check on the character size) - state->transform(x, y, &x1, &y1); - if (x1 + w1 < 0 || x1 > pageWidth || - y1 + h1 < 0 || y1 > pageHeight || - w1 > pageWidth || h1 > pageHeight) { - charPos += nBytes; - return; - } - - // check the tiny chars limit - if (!globalParams->getTextKeepTinyChars() && - fabs(w1) < 3 && fabs(h1) < 3) { - if (++nTinyChars > 50000) { - charPos += nBytes; - return; - } - } - - // break words at space character - if (uLen == 1 && u[0] == (Unicode)0x20) { - charPos += nBytes; - endWord(); - return; - } - - // start a new word if: - // (1) this character doesn't fall in the right place relative to - // the end of the previous word (this places upper and lower - // constraints on the position deltas along both the primary - // and secondary axes), or - // (2) this character overlaps the previous one (duplicated text), or - // (3) the previous character was an overlap (we want each duplicated - // character to be in a word by itself at this stage), - // (4) the font or font size has changed - if (curWord && curWord->len > 0) { - base = sp = delta = 0; // make gcc happy - switch (curWord->rot) { - case 0: - base = y1; - sp = x1 - curWord->xMax; - delta = x1 - curWord->edge[curWord->len - 1]; - break; - case 1: - base = x1; - sp = y1 - curWord->yMax; - delta = y1 - curWord->edge[curWord->len - 1]; - break; - case 2: - base = y1; - sp = curWord->xMin - x1; - delta = curWord->edge[curWord->len - 1] - x1; - break; - case 3: - base = x1; - sp = curWord->yMin - y1; - delta = curWord->edge[curWord->len - 1] - y1; - break; - } - overlap = fabs(delta) < dupMaxPriDelta * curWord->fontSize && - fabs(base - curWord->base) < dupMaxSecDelta * curWord->fontSize; - if (overlap || lastCharOverlap || - sp < -minDupBreakOverlap * curWord->fontSize || - sp > minWordBreakSpace * curWord->fontSize || - fabs(base - curWord->base) > 0.5 || - curFont != curWord->font || - curFontSize != curWord->fontSize) { - endWord(); - } - lastCharOverlap = overlap; - } else { - lastCharOverlap = gFalse; - } - - if (uLen != 0) { - // start a new word if needed - if (!curWord) { - beginWord(state, x, y); - } - - // page rotation and/or transform matrices can cause text to be - // drawn in reverse order -- in this case, swap the begin/end - // coordinates and break text into individual chars - if ((curWord->rot == 0 && w1 < 0) || - (curWord->rot == 1 && h1 < 0) || - (curWord->rot == 2 && w1 > 0) || - (curWord->rot == 3 && h1 > 0)) { - endWord(); - beginWord(state, x + dx, y + dy); - x1 += w1; - y1 += h1; - w1 = -w1; - h1 = -h1; - } - - // add the characters to the current word - w1 /= uLen; - h1 /= uLen; - for (i = 0; i < uLen; ++i) { - curWord->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, - charPos, nBytes, u[i]); - } - } - charPos += nBytes; -} - -void TextPage::incCharCount(int nChars) { - charPos += nChars; -} - -void TextPage::beginActualText(GfxState *state, Unicode *u, int uLen) { - if (actualText) { - gfree(actualText); - } - actualText = (Unicode *)gmallocn(uLen, sizeof(Unicode)); - memcpy(actualText, u, uLen * sizeof(Unicode)); - actualTextLen = uLen; - actualTextNBytes = 0; -} - -void TextPage::endActualText(GfxState *state) { - Unicode *u; - - u = actualText; - actualText = NULL; // so we can call TextPage::addChar() - if (actualTextNBytes) { - // now that we have the position info for all of the text inside - // the marked content span, we feed the "ActualText" back through - // addChar() - addChar(state, actualTextX0, actualTextY0, - actualTextX1 - actualTextX0, actualTextY1 - actualTextY0, - 0, actualTextNBytes, u, actualTextLen); - } - gfree(u); - actualText = NULL; - actualTextLen = 0; - actualTextNBytes = gFalse; -} - -void TextPage::endWord() { - // This check is needed because Type 3 characters can contain - // text-drawing operations (when TextPage is being used via - // {X,Win}SplashOutputDev rather than TextOutputDev). - if (nest > 0) { - --nest; - return; - } - - if (curWord) { - addWord(curWord); - curWord = NULL; - } -} - -void TextPage::addWord(TextWord *word) { - // throw away zero-length words -- they don't have valid xMin/xMax - // values, and they're useless anyway - if (word->len == 0) { - delete word; - return; - } - - if (rawOrder) { - if (rawLastWord) { - rawLastWord->next = word; - } else { - rawWords = word; - } - rawLastWord = word; - } else { - pools[word->rot]->addWord(word); - } -} - -void TextPage::addUnderline(double x0, double y0, double x1, double y1) { - underlines->append(new TextUnderline(x0, y0, x1, y1)); -} - -void TextPage::addLink(int xMin, int yMin, int xMax, int yMax, Link *link) { - links->append(new TextLink(xMin, yMin, xMax, yMax, link)); -} - -void TextPage::coalesce(GBool physLayout, double fixedPitch, GBool doHTML) { - UnicodeMap *uMap; - TextPool *pool; - TextWord *word0, *word1, *word2; - TextLine *line; - TextBlock *blkList, *blkStack, *blk, *lastBlk, *blk0, *blk1; - TextBlock **blkArray; - TextFlow *flow, *lastFlow; - TextUnderline *underline; - TextLink *link; - int rot, poolMinBaseIdx, baseIdx, startBaseIdx, endBaseIdx; - double minBase, maxBase, newMinBase, newMaxBase; - double fontSize, colSpace1, colSpace2, lineSpace, intraLineSpace, blkSpace; - GBool found; - int count[4]; - int lrCount; - int firstBlkIdx, nBlocksLeft; - int col1, col2; - int i, j, n; - - if (rawOrder) { - primaryRot = 0; - primaryLR = gTrue; - return; - } - - uMap = globalParams->getTextEncoding(); - blkList = NULL; - lastBlk = NULL; - nBlocks = 0; - primaryRot = 0; - -#if 0 // for debugging - printf("*** initial words ***\n"); - for (rot = 0; rot < 4; ++rot) { - pool = pools[rot]; - for (baseIdx = pool->minBaseIdx; baseIdx <= pool->maxBaseIdx; ++baseIdx) { - for (word0 = pool->getPool(baseIdx); word0; word0 = word0->next) { - printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f rot=%d link=%p '", - word0->xMin, word0->xMax, word0->yMin, word0->yMax, - word0->base, word0->fontSize, rot*90, word0->link); - for (i = 0; i < word0->len; ++i) { - fputc(word0->text[i] & 0xff, stdout); - } - printf("'\n"); - } - } - } - printf("\n"); -#endif - -#if 0 //~ for debugging - for (i = 0; i < underlines->getLength(); ++i) { - underline = (TextUnderline *)underlines->get(i); - printf("underline: x=%g..%g y=%g..%g horiz=%d\n", - underline->x0, underline->x1, underline->y0, underline->y1, - underline->horiz); - } -#endif - - if (doHTML) { - - //----- handle underlining - for (i = 0; i < underlines->getLength(); ++i) { - underline = (TextUnderline *)underlines->get(i); - if (underline->horiz) { - // rot = 0 - if (pools[0]->minBaseIdx <= pools[0]->maxBaseIdx) { - startBaseIdx = pools[0]->getBaseIdx(underline->y0 + minUnderlineGap); - endBaseIdx = pools[0]->getBaseIdx(underline->y0 + maxUnderlineGap); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[0]->getPool(j); word0; word0 = word0->next) { - //~ need to check the y value against the word baseline - if (underline->x0 < word0->xMin + underlineSlack && - word0->xMax - underlineSlack < underline->x1) { - word0->underlined = gTrue; - } - } - } - } - - // rot = 2 - if (pools[2]->minBaseIdx <= pools[2]->maxBaseIdx) { - startBaseIdx = pools[2]->getBaseIdx(underline->y0 - maxUnderlineGap); - endBaseIdx = pools[2]->getBaseIdx(underline->y0 - minUnderlineGap); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[2]->getPool(j); word0; word0 = word0->next) { - if (underline->x0 < word0->xMin + underlineSlack && - word0->xMax - underlineSlack < underline->x1) { - word0->underlined = gTrue; - } - } - } - } - } else { - // rot = 1 - if (pools[1]->minBaseIdx <= pools[1]->maxBaseIdx) { - startBaseIdx = pools[1]->getBaseIdx(underline->x0 - maxUnderlineGap); - endBaseIdx = pools[1]->getBaseIdx(underline->x0 - minUnderlineGap); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[1]->getPool(j); word0; word0 = word0->next) { - if (underline->y0 < word0->yMin + underlineSlack && - word0->yMax - underlineSlack < underline->y1) { - word0->underlined = gTrue; - } - } - } - } - - // rot = 3 - if (pools[3]->minBaseIdx <= pools[3]->maxBaseIdx) { - startBaseIdx = pools[3]->getBaseIdx(underline->x0 + minUnderlineGap); - endBaseIdx = pools[3]->getBaseIdx(underline->x0 + maxUnderlineGap); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[3]->getPool(j); word0; word0 = word0->next) { - if (underline->y0 < word0->yMin + underlineSlack && - word0->yMax - underlineSlack < underline->y1) { - word0->underlined = gTrue; - } - } - } - } - } - } - - //----- handle links - for (i = 0; i < links->getLength(); ++i) { - link = (TextLink *)links->get(i); - - // rot = 0 - if (pools[0]->minBaseIdx <= pools[0]->maxBaseIdx) { - startBaseIdx = pools[0]->getBaseIdx(link->yMin); - endBaseIdx = pools[0]->getBaseIdx(link->yMax); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[0]->getPool(j); word0; word0 = word0->next) { - if (link->xMin < word0->xMin + hyperlinkSlack && - word0->xMax - hyperlinkSlack < link->xMax && - link->yMin < word0->yMin + hyperlinkSlack && - word0->yMax - hyperlinkSlack < link->yMax) { - word0->link = link->link; - } - } - } - } - - // rot = 2 - if (pools[2]->minBaseIdx <= pools[2]->maxBaseIdx) { - startBaseIdx = pools[2]->getBaseIdx(link->yMin); - endBaseIdx = pools[2]->getBaseIdx(link->yMax); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[2]->getPool(j); word0; word0 = word0->next) { - if (link->xMin < word0->xMin + hyperlinkSlack && - word0->xMax - hyperlinkSlack < link->xMax && - link->yMin < word0->yMin + hyperlinkSlack && - word0->yMax - hyperlinkSlack < link->yMax) { - word0->link = link->link; - } - } - } - } - - // rot = 1 - if (pools[1]->minBaseIdx <= pools[1]->maxBaseIdx) { - startBaseIdx = pools[1]->getBaseIdx(link->xMin); - endBaseIdx = pools[1]->getBaseIdx(link->xMax); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[1]->getPool(j); word0; word0 = word0->next) { - if (link->yMin < word0->yMin + hyperlinkSlack && - word0->yMax - hyperlinkSlack < link->yMax && - link->xMin < word0->xMin + hyperlinkSlack && - word0->xMax - hyperlinkSlack < link->xMax) { - word0->link = link->link; - } - } - } - } - - // rot = 3 - if (pools[3]->minBaseIdx <= pools[3]->maxBaseIdx) { - startBaseIdx = pools[3]->getBaseIdx(link->xMin); - endBaseIdx = pools[3]->getBaseIdx(link->xMax); - for (j = startBaseIdx; j <= endBaseIdx; ++j) { - for (word0 = pools[3]->getPool(j); word0; word0 = word0->next) { - if (link->yMin < word0->yMin + hyperlinkSlack && - word0->yMax - hyperlinkSlack < link->yMax && - link->xMin < word0->xMin + hyperlinkSlack && - word0->xMax - hyperlinkSlack < link->xMax) { - word0->link = link->link; - } - } - } - } - } - } - - //----- assemble the blocks - - //~ add an outer loop for writing mode (vertical text) - - // build blocks for each rotation value - for (rot = 0; rot < 4; ++rot) { - pool = pools[rot]; - poolMinBaseIdx = pool->minBaseIdx; - count[rot] = 0; - - // add blocks until no more words are left - while (1) { - - // find the first non-empty line in the pool - for (; - poolMinBaseIdx <= pool->maxBaseIdx && - !pool->getPool(poolMinBaseIdx); - ++poolMinBaseIdx) ; - if (poolMinBaseIdx > pool->maxBaseIdx) { - break; - } - - // look for the left-most word in the first four lines of the - // pool -- this avoids starting with a superscript word - startBaseIdx = poolMinBaseIdx; - for (baseIdx = poolMinBaseIdx + 1; - baseIdx < poolMinBaseIdx + 4 && baseIdx <= pool->maxBaseIdx; - ++baseIdx) { - if (!pool->getPool(baseIdx)) { - continue; - } - if (pool->getPool(baseIdx)->primaryCmp(pool->getPool(startBaseIdx)) - < 0) { - startBaseIdx = baseIdx; - } - } - - // create a new block - word0 = pool->getPool(startBaseIdx); - pool->setPool(startBaseIdx, word0->next); - word0->next = NULL; - blk = new TextBlock(this, rot); - blk->addWord(word0); - - fontSize = word0->fontSize; - minBase = maxBase = word0->base; - colSpace1 = minColSpacing1 * fontSize; - colSpace2 = minColSpacing2 * fontSize; - lineSpace = maxLineSpacingDelta * fontSize; - intraLineSpace = maxIntraLineDelta * fontSize; - - // add words to the block - do { - found = gFalse; - - // look for words on the line above the current top edge of - // the block - newMinBase = minBase; - for (baseIdx = pool->getBaseIdx(minBase); - baseIdx >= pool->getBaseIdx(minBase - lineSpace); - --baseIdx) { - word0 = NULL; - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base < minBase && - word1->base >= minBase - lineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin) - : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta1 * fontSize) { - word2 = word1; - if (word0) { - word0->next = word1->next; - } else { - pool->setPool(baseIdx, word1->next); - } - word1 = word1->next; - word2->next = NULL; - blk->addWord(word2); - found = gTrue; - newMinBase = word2->base; - } else { - word0 = word1; - word1 = word1->next; - } - } - } - minBase = newMinBase; - - // look for words on the line below the current bottom edge of - // the block - newMaxBase = maxBase; - for (baseIdx = pool->getBaseIdx(maxBase); - baseIdx <= pool->getBaseIdx(maxBase + lineSpace); - ++baseIdx) { - word0 = NULL; - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base > maxBase && - word1->base <= maxBase + lineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin) - : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta1 * fontSize) { - word2 = word1; - if (word0) { - word0->next = word1->next; - } else { - pool->setPool(baseIdx, word1->next); - } - word1 = word1->next; - word2->next = NULL; - blk->addWord(word2); - found = gTrue; - newMaxBase = word2->base; - } else { - word0 = word1; - word1 = word1->next; - } - } - } - maxBase = newMaxBase; - - // look for words that are on lines already in the block, and - // that overlap the block horizontally - for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); - baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); - ++baseIdx) { - word0 = NULL; - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base >= minBase - intraLineSpace && - word1->base <= maxBase + intraLineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMin < blk->xMax + colSpace1 && - word1->xMax > blk->xMin - colSpace1) - : (word1->yMin < blk->yMax + colSpace1 && - word1->yMax > blk->yMin - colSpace1)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta2 * fontSize) { - word2 = word1; - if (word0) { - word0->next = word1->next; - } else { - pool->setPool(baseIdx, word1->next); - } - word1 = word1->next; - word2->next = NULL; - blk->addWord(word2); - found = gTrue; - } else { - word0 = word1; - word1 = word1->next; - } - } - } - - // only check for outlying words (the next two chunks of code) - // if we didn't find anything else - if (found) { - continue; - } - - // scan down the left side of the block, looking for words - // that are near (but not overlapping) the block; if there are - // three or fewer, add them to the block - n = 0; - for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); - baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); - ++baseIdx) { - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base >= minBase - intraLineSpace && - word1->base <= maxBase + intraLineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMax <= blk->xMin && - word1->xMax > blk->xMin - colSpace2) - : (word1->yMax <= blk->yMin && - word1->yMax > blk->yMin - colSpace2)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta3 * fontSize) { - ++n; - break; - } - word1 = word1->next; - } - } - if (n > 0 && n <= 3) { - for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); - baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); - ++baseIdx) { - word0 = NULL; - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base >= minBase - intraLineSpace && - word1->base <= maxBase + intraLineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMax <= blk->xMin && - word1->xMax > blk->xMin - colSpace2) - : (word1->yMax <= blk->yMin && - word1->yMax > blk->yMin - colSpace2)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta3 * fontSize) { - word2 = word1; - if (word0) { - word0->next = word1->next; - } else { - pool->setPool(baseIdx, word1->next); - } - word1 = word1->next; - word2->next = NULL; - blk->addWord(word2); - if (word2->base < minBase) { - minBase = word2->base; - } else if (word2->base > maxBase) { - maxBase = word2->base; - } - found = gTrue; - break; - } else { - word0 = word1; - word1 = word1->next; - } - } - } - } - - // scan down the right side of the block, looking for words - // that are near (but not overlapping) the block; if there are - // three or fewer, add them to the block - n = 0; - for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); - baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); - ++baseIdx) { - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base >= minBase - intraLineSpace && - word1->base <= maxBase + intraLineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMin >= blk->xMax && - word1->xMin < blk->xMax + colSpace2) - : (word1->yMin >= blk->yMax && - word1->yMin < blk->yMax + colSpace2)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta3 * fontSize) { - ++n; - break; - } - word1 = word1->next; - } - } - if (n > 0 && n <= 3) { - for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); - baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); - ++baseIdx) { - word0 = NULL; - word1 = pool->getPool(baseIdx); - while (word1) { - if (word1->base >= minBase - intraLineSpace && - word1->base <= maxBase + intraLineSpace && - ((rot == 0 || rot == 2) - ? (word1->xMin >= blk->xMax && - word1->xMin < blk->xMax + colSpace2) - : (word1->yMin >= blk->yMax && - word1->yMin < blk->yMax + colSpace2)) && - fabs(word1->fontSize - fontSize) < - maxBlockFontSizeDelta3 * fontSize) { - word2 = word1; - if (word0) { - word0->next = word1->next; - } else { - pool->setPool(baseIdx, word1->next); - } - word1 = word1->next; - word2->next = NULL; - blk->addWord(word2); - if (word2->base < minBase) { - minBase = word2->base; - } else if (word2->base > maxBase) { - maxBase = word2->base; - } - found = gTrue; - break; - } else { - word0 = word1; - word1 = word1->next; - } - } - } - } - - } while (found); - - //~ need to compute the primary writing mode (horiz/vert) in - //~ addition to primary rotation - - // coalesce the block, and add it to the list - blk->coalesce(uMap, fixedPitch); - if (lastBlk) { - lastBlk->next = blk; - } else { - blkList = blk; - } - lastBlk = blk; - count[rot] += blk->charCount; - ++nBlocks; - } - - if (count[rot] > count[primaryRot]) { - primaryRot = rot; - } - } - -#if 0 // for debugging - printf("*** rotation ***\n"); - for (rot = 0; rot < 4; ++rot) { - printf(" %d: %6d\n", rot, count[rot]); - } - printf(" primary rot = %d\n", primaryRot); - printf("\n"); -#endif - -#if 0 // for debugging - printf("*** blocks ***\n"); - for (blk = blkList; blk; blk = blk->next) { - printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f\n", - blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax); - for (line = blk->lines; line; line = line->next) { - printf(" line: x=%.2f..%.2f y=%.2f..%.2f base=%.2f\n", - line->xMin, line->xMax, line->yMin, line->yMax, line->base); - for (word0 = line->words; word0; word0 = word0->next) { - printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", - word0->xMin, word0->xMax, word0->yMin, word0->yMax, - word0->base, word0->fontSize, word0->spaceAfter); - for (i = 0; i < word0->len; ++i) { - fputc(word0->text[i] & 0xff, stdout); - } - printf("'\n"); - } - } - } - printf("\n"); -#endif - - // determine the primary direction - lrCount = 0; - for (blk = blkList; blk; blk = blk->next) { - for (line = blk->lines; line; line = line->next) { - for (word0 = line->words; word0; word0 = word0->next) { - for (i = 0; i < word0->len; ++i) { - if (unicodeTypeL(word0->text[i])) { - ++lrCount; - } else if (unicodeTypeR(word0->text[i])) { - --lrCount; - } - } - } - } - } - primaryLR = lrCount >= 0; - -#if 0 // for debugging - printf("*** direction ***\n"); - printf("lrCount = %d\n", lrCount); - printf("primaryLR = %d\n", primaryLR); -#endif - - //----- column assignment - - if (physLayout && fixedPitch) { - - blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); - for (blk = blkList, i = 0; blk; blk = blk->next, ++i) { - blocks[i] = blk; - col1 = 0; // make gcc happy - switch (primaryRot) { - case 0: - col1 = (int)(blk->xMin / fixedPitch + 0.5); - break; - case 1: - col1 = (int)(blk->yMin / fixedPitch + 0.5); - break; - case 2: - col1 = (int)((pageWidth - blk->xMax) / fixedPitch + 0.5); - break; - case 3: - col1 = (int)((pageHeight - blk->yMax) / fixedPitch + 0.5); - break; - } - blk->col = col1; - for (line = blk->lines; line; line = line->next) { - for (j = 0; j <= line->len; ++j) { - line->col[j] += col1; - } - } - } - - } else { - - // sort blocks into xy order for column assignment - blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); - for (blk = blkList, i = 0; blk; blk = blk->next, ++i) { - blocks[i] = blk; - } - qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpXYPrimaryRot); - - // column assignment - for (i = 0; i < nBlocks; ++i) { - blk0 = blocks[i]; - col1 = 0; - for (j = 0; j < i; ++j) { - blk1 = blocks[j]; - col2 = 0; // make gcc happy - switch (primaryRot) { - case 0: - if (blk0->xMin > blk1->xMax) { - col2 = blk1->col + blk1->nColumns + 3; - } else if (blk1->xMax == blk1->xMin) { - col2 = blk1->col; - } else { - col2 = blk1->col + (int)(((blk0->xMin - blk1->xMin) / - (blk1->xMax - blk1->xMin)) * - blk1->nColumns); - } - break; - case 1: - if (blk0->yMin > blk1->yMax) { - col2 = blk1->col + blk1->nColumns + 3; - } else if (blk1->yMax == blk1->yMin) { - col2 = blk1->col; - } else { - col2 = blk1->col + (int)(((blk0->yMin - blk1->yMin) / - (blk1->yMax - blk1->yMin)) * - blk1->nColumns); - } - break; - case 2: - if (blk0->xMax < blk1->xMin) { - col2 = blk1->col + blk1->nColumns + 3; - } else if (blk1->xMin == blk1->xMax) { - col2 = blk1->col; - } else { - col2 = blk1->col + (int)(((blk0->xMax - blk1->xMax) / - (blk1->xMin - blk1->xMax)) * - blk1->nColumns); - } - break; - case 3: - if (blk0->yMax < blk1->yMin) { - col2 = blk1->col + blk1->nColumns + 3; - } else if (blk1->yMin == blk1->yMax) { - col2 = blk1->col; - } else { - col2 = blk1->col + (int)(((blk0->yMax - blk1->yMax) / - (blk1->yMin - blk1->yMax)) * - blk1->nColumns); - } - break; - } - if (col2 > col1) { - col1 = col2; - } - } - blk0->col = col1; - for (line = blk0->lines; line; line = line->next) { - for (j = 0; j <= line->len; ++j) { - line->col[j] += col1; - } - } - } - - } - -#if 0 // for debugging - printf("*** blocks, after column assignment ***\n"); - for (blk = blkList; blk; blk = blk->next) { - printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f col=%d nCols=%d\n", - blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->col, - blk->nColumns); - for (line = blk->lines; line; line = line->next) { - printf(" line: col[0]=%d\n", line->col[0]); - for (word0 = line->words; word0; word0 = word0->next) { - printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", - word0->xMin, word0->xMax, word0->yMin, word0->yMax, - word0->base, word0->fontSize, word0->spaceAfter); - for (i = 0; i < word0->len; ++i) { - fputc(word0->text[i] & 0xff, stdout); - } - printf("'\n"); - } - } - } - printf("\n"); -#endif - - //----- reading order sort - - // sort blocks into yx order (in preparation for reading order sort) - qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpYXPrimaryRot); - - // compute space on left and right sides of each block - for (i = 0; i < nBlocks; ++i) { - blk0 = blocks[i]; - for (j = 0; j < nBlocks; ++j) { - blk1 = blocks[j]; - if (blk1 != blk0) { - blk0->updatePriMinMax(blk1); - } - } - } - -#if 0 // for debugging - printf("*** blocks, after yx sort ***\n"); - for (i = 0; i < nBlocks; ++i) { - blk = blocks[i]; - printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f space=%.2f..%.2f\n", - blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, - blk->priMin, blk->priMax); - for (line = blk->lines; line; line = line->next) { - printf(" line:\n"); - for (word0 = line->words; word0; word0 = word0->next) { - printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", - word0->xMin, word0->xMax, word0->yMin, word0->yMax, - word0->base, word0->fontSize, word0->spaceAfter); - for (j = 0; j < word0->len; ++j) { - fputc(word0->text[j] & 0xff, stdout); - } - printf("'\n"); - } - } - } - printf("\n"); -#endif - - // build the flows - //~ this needs to be adjusted for writing mode (vertical text) - //~ this also needs to account for right-to-left column ordering - blkArray = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); - memcpy(blkArray, blocks, nBlocks * sizeof(TextBlock *)); - flows = lastFlow = NULL; - firstBlkIdx = 0; - nBlocksLeft = nBlocks; - while (nBlocksLeft > 0) { - - // find the upper-left-most block - for (; !blkArray[firstBlkIdx]; ++firstBlkIdx) ; - i = firstBlkIdx; - blk = blkArray[i]; - for (j = firstBlkIdx + 1; j < nBlocks; ++j) { - blk1 = blkArray[j]; - if (blk1) { - if (blk && blk->secondaryDelta(blk1) > 0) { - break; - } - if (blk1->primaryCmp(blk) < 0) { - i = j; - blk = blk1; - } - } - } - blkArray[i] = NULL; - --nBlocksLeft; - blk->next = NULL; - - // create a new flow, starting with the upper-left-most block - flow = new TextFlow(this, blk); - if (lastFlow) { - lastFlow->next = flow; - } else { - flows = flow; - } - lastFlow = flow; - fontSize = blk->lines->words->fontSize; - - // push the upper-left-most block on the stack - blk->stackNext = NULL; - blkStack = blk; - - // find the other blocks in this flow - while (blkStack) { - - // find the upper-left-most block under (but within - // maxBlockSpacing of) the top block on the stack - blkSpace = maxBlockSpacing * blkStack->lines->words->fontSize; - blk = NULL; - i = -1; - for (j = firstBlkIdx; j < nBlocks; ++j) { - blk1 = blkArray[j]; - if (blk1) { - if (blkStack->secondaryDelta(blk1) > blkSpace) { - break; - } - if (blk && blk->secondaryDelta(blk1) > 0) { - break; - } - if (blk1->isBelow(blkStack) && - (!blk || blk1->primaryCmp(blk) < 0)) { - i = j; - blk = blk1; - } - } - } - - // if a suitable block was found, add it to the flow and push it - // onto the stack - if (blk && flow->blockFits(blk, blkStack)) { - blkArray[i] = NULL; - --nBlocksLeft; - blk->next = NULL; - flow->addBlock(blk); - fontSize = blk->lines->words->fontSize; - blk->stackNext = blkStack; - blkStack = blk; - - // otherwise (if there is no block under the top block or the - // block is not suitable), pop the stack - } else { - blkStack = blkStack->stackNext; - } - } - } - gfree(blkArray); - -#if 0 // for debugging - printf("*** flows ***\n"); - for (flow = flows; flow; flow = flow->next) { - printf("flow: x=%.2f..%.2f y=%.2f..%.2f pri:%.2f..%.2f\n", - flow->xMin, flow->xMax, flow->yMin, flow->yMax, - flow->priMin, flow->priMax); - for (blk = flow->blocks; blk; blk = blk->next) { - printf(" block: rot=%d x=%.2f..%.2f y=%.2f..%.2f pri=%.2f..%.2f\n", - blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, - blk->priMin, blk->priMax); - for (line = blk->lines; line; line = line->next) { - printf(" line:\n"); - for (word0 = line->words; word0; word0 = word0->next) { - printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", - word0->xMin, word0->xMax, word0->yMin, word0->yMax, - word0->base, word0->fontSize, word0->spaceAfter); - for (i = 0; i < word0->len; ++i) { - fputc(word0->text[i] & 0xff, stdout); - } - printf("'\n"); - } - } - } - } - printf("\n"); -#endif - - if (uMap) { - uMap->decRefCnt(); - } -} - -GBool TextPage::findText(Unicode *s, int len, - GBool startAtTop, GBool stopAtBottom, - GBool startAtLast, GBool stopAtLast, - GBool caseSensitive, GBool backward, - GBool wholeWord, - double *xMin, double *yMin, - double *xMax, double *yMax) { - TextBlock *blk; - TextLine *line; - Unicode *s2, *txt; - Unicode *p; - int txtSize, m, i, j, k; - double xStart, yStart, xStop, yStop; - double xMin0, yMin0, xMax0, yMax0; - double xMin1, yMin1, xMax1, yMax1; - GBool found; - - //~ needs to handle right-to-left text - - if (rawOrder) { - return gFalse; - } - - // convert the search string to uppercase - if (!caseSensitive) { - s2 = (Unicode *)gmallocn(len, sizeof(Unicode)); - for (i = 0; i < len; ++i) { - s2[i] = unicodeToUpper(s[i]); - } - } else { - s2 = s; - } - - txt = NULL; - txtSize = 0; - - xStart = yStart = xStop = yStop = 0; - if (startAtLast && haveLastFind) { - xStart = lastFindXMin; - yStart = lastFindYMin; - } else if (!startAtTop) { - xStart = *xMin; - yStart = *yMin; - } - if (stopAtLast && haveLastFind) { - xStop = lastFindXMin; - yStop = lastFindYMin; - } else if (!stopAtBottom) { - xStop = *xMax; - yStop = *yMax; - } - - found = gFalse; - xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy - xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy - - for (i = backward ? nBlocks - 1 : 0; - backward ? i >= 0 : i < nBlocks; - i += backward ? -1 : 1) { - blk = blocks[i]; - - // check: is the block above the top limit? - // (this only works if the page's primary rotation is zero -- - // otherwise the blocks won't be sorted in the useful order) - if (!startAtTop && primaryRot == 0 && - (backward ? blk->yMin > yStart : blk->yMax < yStart)) { - continue; - } - - // check: is the block below the bottom limit? - // (this only works if the page's primary rotation is zero -- - // otherwise the blocks won't be sorted in the useful order) - if (!stopAtBottom && primaryRot == 0 && - (backward ? blk->yMax < yStop : blk->yMin > yStop)) { - break; - } - - for (line = blk->lines; line; line = line->next) { - - // check: is the line above the top limit? - // (this only works if the page's primary rotation is zero -- - // otherwise the lines won't be sorted in the useful order) - if (!startAtTop && primaryRot == 0 && - (backward ? line->yMin > yStart : line->yMin < yStart)) { - continue; - } - - // check: is the line below the bottom limit? - // (this only works if the page's primary rotation is zero -- - // otherwise the lines won't be sorted in the useful order) - if (!stopAtBottom && primaryRot == 0 && - (backward ? line->yMin < yStop : line->yMin > yStop)) { - continue; - } - - // convert the line to uppercase - m = line->len; - if (!caseSensitive) { - if (m > txtSize) { - txt = (Unicode *)greallocn(txt, m, sizeof(Unicode)); - txtSize = m; - } - for (k = 0; k < m; ++k) { - txt[k] = unicodeToUpper(line->text[k]); - } - } else { - txt = line->text; - } - - // search each position in this line - j = backward ? m - len : 0; - p = txt + j; - while (backward ? j >= 0 : j <= m - len) { - if (!wholeWord || - ((j == 0 || !unicodeTypeAlphaNum(txt[j - 1])) && - (j + len == m || !unicodeTypeAlphaNum(txt[j + len])))) { - - // compare the strings - for (k = 0; k < len; ++k) { - if (p[k] != s2[k]) { - break; - } - } - - // found it - if (k == len) { - switch (line->rot) { - case 0: - xMin1 = line->edge[j]; - xMax1 = line->edge[j + len]; - yMin1 = line->yMin; - yMax1 = line->yMax; - break; - case 1: - xMin1 = line->xMin; - xMax1 = line->xMax; - yMin1 = line->edge[j]; - yMax1 = line->edge[j + len]; - break; - case 2: - xMin1 = line->edge[j + len]; - xMax1 = line->edge[j]; - yMin1 = line->yMin; - yMax1 = line->yMax; - break; - case 3: - xMin1 = line->xMin; - xMax1 = line->xMax; - yMin1 = line->edge[j + len]; - yMax1 = line->edge[j]; - break; - } - if (backward) { - if ((startAtTop || - yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) && - (stopAtBottom || - yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) { - if (!found || - yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) { - xMin0 = xMin1; - xMax0 = xMax1; - yMin0 = yMin1; - yMax0 = yMax1; - found = gTrue; - } - } - } else { - if ((startAtTop || - yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) && - (stopAtBottom || - yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) { - if (!found || - yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) { - xMin0 = xMin1; - xMax0 = xMax1; - yMin0 = yMin1; - yMax0 = yMax1; - found = gTrue; - } - } - } - } - } - if (backward) { - --j; - --p; - } else { - ++j; - ++p; - } - } - } - } - - if (!caseSensitive) { - gfree(s2); - gfree(txt); - } - - if (found) { - *xMin = xMin0; - *xMax = xMax0; - *yMin = yMin0; - *yMax = yMax0; - lastFindXMin = xMin0; - lastFindYMin = yMin0; - haveLastFind = gTrue; - return gTrue; - } - - return gFalse; -} - -GString *TextPage::getText(double xMin, double yMin, - double xMax, double yMax) { - GString *s; - UnicodeMap *uMap; - GBool isUnicode; - TextBlock *blk; - TextLine *line; - TextLineFrag *frags; - int nFrags, fragsSize; - TextLineFrag *frag; - char space[8], eol[16]; - int spaceLen, eolLen; - int lastRot; - double x, y, delta; - int col, idx0, idx1, i, j; - GBool multiLine, oneRot; - - s = new GString(); - - if (rawOrder) { - return s; - } - - // get the output encoding - if (!(uMap = globalParams->getTextEncoding())) { - return s; - } - isUnicode = uMap->isUnicode(); - spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); - eolLen = 0; // make gcc happy - switch (globalParams->getTextEOL()) { - case eolUnix: - eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); - break; - case eolDOS: - eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); - eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen); - break; - case eolMac: - eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); - break; - } - - //~ writing mode (horiz/vert) - - // collect the line fragments that are in the rectangle - fragsSize = 256; - frags = (TextLineFrag *)gmallocn(fragsSize, sizeof(TextLineFrag)); - nFrags = 0; - lastRot = -1; - oneRot = gTrue; - for (i = 0; i < nBlocks; ++i) { - blk = blocks[i]; - if (xMin < blk->xMax && blk->xMin < xMax && - yMin < blk->yMax && blk->yMin < yMax) { - for (line = blk->lines; line; line = line->next) { - if (xMin < line->xMax && line->xMin < xMax && - yMin < line->yMax && line->yMin < yMax) { - idx0 = idx1 = -1; - switch (line->rot) { - case 0: - y = 0.5 * (line->yMin + line->yMax); - if (yMin < y && y < yMax) { - j = 0; - while (j < line->len) { - if (0.5 * (line->edge[j] + line->edge[j+1]) > xMin) { - idx0 = j; - break; - } - ++j; - } - j = line->len - 1; - while (j >= 0) { - if (0.5 * (line->edge[j] + line->edge[j+1]) < xMax) { - idx1 = j; - break; - } - --j; - } - } - break; - case 1: - x = 0.5 * (line->xMin + line->xMax); - if (xMin < x && x < xMax) { - j = 0; - while (j < line->len) { - if (0.5 * (line->edge[j] + line->edge[j+1]) > yMin) { - idx0 = j; - break; - } - ++j; - } - j = line->len - 1; - while (j >= 0) { - if (0.5 * (line->edge[j] + line->edge[j+1]) < yMax) { - idx1 = j; - break; - } - --j; - } - } - break; - case 2: - y = 0.5 * (line->yMin + line->yMax); - if (yMin < y && y < yMax) { - j = 0; - while (j < line->len) { - if (0.5 * (line->edge[j] + line->edge[j+1]) < xMax) { - idx0 = j; - break; - } - ++j; - } - j = line->len - 1; - while (j >= 0) { - if (0.5 * (line->edge[j] + line->edge[j+1]) > xMin) { - idx1 = j; - break; - } - --j; - } - } - break; - case 3: - x = 0.5 * (line->xMin + line->xMax); - if (xMin < x && x < xMax) { - j = 0; - while (j < line->len) { - if (0.5 * (line->edge[j] + line->edge[j+1]) < yMax) { - idx0 = j; - break; - } - ++j; - } - j = line->len - 1; - while (j >= 0) { - if (0.5 * (line->edge[j] + line->edge[j+1]) > yMin) { - idx1 = j; - break; - } - --j; - } - } - break; - } - if (idx0 >= 0 && idx1 >= 0) { - if (nFrags == fragsSize) { - fragsSize *= 2; - frags = (TextLineFrag *) - greallocn(frags, fragsSize, sizeof(TextLineFrag)); - } - frags[nFrags].init(line, idx0, idx1 - idx0 + 1); - ++nFrags; - if (lastRot >= 0 && line->rot != lastRot) { - oneRot = gFalse; - } - lastRot = line->rot; - } - } - } - } - } - - // sort the fragments and generate the string - if (nFrags > 0) { - - for (i = 0; i < nFrags; ++i) { - frags[i].computeCoords(oneRot); - } - assignColumns(frags, nFrags, oneRot); - - // if all lines in the region have the same rotation, use it; - // otherwise, use the page's primary rotation - if (oneRot) { - qsort(frags, nFrags, sizeof(TextLineFrag), - &TextLineFrag::cmpYXLineRot); - } else { - qsort(frags, nFrags, sizeof(TextLineFrag), - &TextLineFrag::cmpYXPrimaryRot); - } - i = 0; - while (i < nFrags) { - delta = maxIntraLineDelta * frags[i].line->words->fontSize; - for (j = i+1; - j < nFrags && fabs(frags[j].base - frags[i].base) < delta; - ++j) ; - qsort(frags + i, j - i, sizeof(TextLineFrag), - oneRot ? &TextLineFrag::cmpXYColumnLineRot - : &TextLineFrag::cmpXYColumnPrimaryRot); - i = j; - } - - col = 0; - multiLine = gFalse; - for (i = 0; i < nFrags; ++i) { - frag = &frags[i]; - - // insert a return - if (frag->col < col || - (i > 0 && fabs(frag->base - frags[i-1].base) > - maxIntraLineDelta * frags[i-1].line->words->fontSize)) { - s->append(eol, eolLen); - col = 0; - multiLine = gTrue; - } - - // column alignment - for (; col < frag->col; ++col) { - s->append(space, spaceLen); - } - - // get the fragment text - col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s); - } - - if (multiLine) { - s->append(eol, eolLen); - } - } - - gfree(frags); - uMap->decRefCnt(); - - return s; -} - -GBool TextPage::findCharRange(int pos, int length, - double *xMin, double *yMin, - double *xMax, double *yMax) { - TextBlock *blk; - TextLine *line; - TextWord *word; - double xMin0, xMax0, yMin0, yMax0; - double xMin1, xMax1, yMin1, yMax1; - GBool first; - int i, j0, j1; - - if (rawOrder) { - return gFalse; - } - - //~ this doesn't correctly handle ranges split across multiple lines - //~ (the highlighted region is the bounding box of all the parts of - //~ the range) - first = gTrue; - xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy - xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy - for (i = 0; i < nBlocks; ++i) { - blk = blocks[i]; - for (line = blk->lines; line; line = line->next) { - for (word = line->words; word; word = word->next) { - if (pos < word->charPos[word->len] && - pos + length > word->charPos[0]) { - for (j0 = 0; - j0 < word->len && pos >= word->charPos[j0 + 1]; - ++j0) ; - for (j1 = word->len - 1; - j1 > j0 && pos + length <= word->charPos[j1]; - --j1) ; - switch (line->rot) { - case 0: - xMin1 = word->edge[j0]; - xMax1 = word->edge[j1 + 1]; - yMin1 = word->yMin; - yMax1 = word->yMax; - break; - case 1: - xMin1 = word->xMin; - xMax1 = word->xMax; - yMin1 = word->edge[j0]; - yMax1 = word->edge[j1 + 1]; - break; - case 2: - xMin1 = word->edge[j1 + 1]; - xMax1 = word->edge[j0]; - yMin1 = word->yMin; - yMax1 = word->yMax; - break; - case 3: - xMin1 = word->xMin; - xMax1 = word->xMax; - yMin1 = word->edge[j1 + 1]; - yMax1 = word->edge[j0]; - break; - } - if (first || xMin1 < xMin0) { - xMin0 = xMin1; - } - if (first || xMax1 > xMax0) { - xMax0 = xMax1; - } - if (first || yMin1 < yMin0) { - yMin0 = yMin1; - } - if (first || yMax1 > yMax0) { - yMax0 = yMax1; - } - first = gFalse; - } - } - } - } - if (!first) { - *xMin = xMin0; - *xMax = xMax0; - *yMin = yMin0; - *yMax = yMax0; - return gTrue; - } - return gFalse; -} - -void TextPage::dump(void *outputStream, TextOutputFunc outputFunc, - GBool physLayout) { - UnicodeMap *uMap; - TextFlow *flow; - TextBlock *blk; - TextLine *line; - TextLineFrag *frags; - TextWord *word; - int nFrags, fragsSize; - TextLineFrag *frag; - char space[8], eol[16], eop[8]; - int spaceLen, eolLen, eopLen; - GBool pageBreaks; - GString *s; - double delta; - int col, i, j, d, n; - - // get the output encoding - if (!(uMap = globalParams->getTextEncoding())) { - return; - } - spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); - eolLen = 0; // make gcc happy - switch (globalParams->getTextEOL()) { - case eolUnix: - eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); - break; - case eolDOS: - eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); - eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen); - break; - case eolMac: - eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); - break; - } - eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop)); - pageBreaks = globalParams->getTextPageBreaks(); - - //~ writing mode (horiz/vert) - - // output the page in raw (content stream) order - if (rawOrder) { - - for (word = rawWords; word; word = word->next) { - s = new GString(); - dumpFragment(word->text, word->len, uMap, s); - (*outputFunc)(outputStream, s->getCString(), s->getLength()); - delete s; - if (word->next && - fabs(word->next->base - word->base) < - maxIntraLineDelta * word->fontSize && - word->next->xMin > - word->xMax - minDupBreakOverlap * word->fontSize) { - if (word->next->xMin > word->xMax + minWordSpacing * word->fontSize) { - (*outputFunc)(outputStream, space, spaceLen); - } - } else { - (*outputFunc)(outputStream, eol, eolLen); - } - } - - // output the page, maintaining the original physical layout - } else if (physLayout) { - - // collect the line fragments for the page and sort them - fragsSize = 256; - frags = (TextLineFrag *)gmallocn(fragsSize, sizeof(TextLineFrag)); - nFrags = 0; - for (i = 0; i < nBlocks; ++i) { - blk = blocks[i]; - for (line = blk->lines; line; line = line->next) { - if (nFrags == fragsSize) { - fragsSize *= 2; - frags = (TextLineFrag *)greallocn(frags, - fragsSize, sizeof(TextLineFrag)); - } - frags[nFrags].init(line, 0, line->len); - frags[nFrags].computeCoords(gTrue); - ++nFrags; - } - } - qsort(frags, nFrags, sizeof(TextLineFrag), &TextLineFrag::cmpYXPrimaryRot); - i = 0; - while (i < nFrags) { - delta = maxIntraLineDelta * frags[i].line->words->fontSize; - for (j = i+1; - j < nFrags && fabs(frags[j].base - frags[i].base) < delta; - ++j) ; - qsort(frags + i, j - i, sizeof(TextLineFrag), - &TextLineFrag::cmpXYColumnPrimaryRot); - i = j; - } - -#if 0 // for debugging - printf("*** line fragments ***\n"); - for (i = 0; i < nFrags; ++i) { - frag = &frags[i]; - printf("frag: x=%.2f..%.2f y=%.2f..%.2f base=%.2f '", - frag->xMin, frag->xMax, frag->yMin, frag->yMax, frag->base); - for (n = 0; n < frag->len; ++n) { - fputc(frag->line->text[frag->start + n] & 0xff, stdout); - } - printf("'\n"); - } - printf("\n"); -#endif - - // generate output - col = 0; - for (i = 0; i < nFrags; ++i) { - frag = &frags[i]; - - // column alignment - for (; col < frag->col; ++col) { - (*outputFunc)(outputStream, space, spaceLen); - } - - // print the line - s = new GString(); - col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s); - (*outputFunc)(outputStream, s->getCString(), s->getLength()); - delete s; - - // print one or more returns if necessary - if (i == nFrags - 1 || - frags[i+1].col < col || - fabs(frags[i+1].base - frag->base) > - maxIntraLineDelta * frag->line->words->fontSize) { - if (i < nFrags - 1) { - d = (int)((frags[i+1].base - frag->base) / - frag->line->words->fontSize); - if (d < 1) { - d = 1; - } else if (d > 5) { - d = 5; - } - } else { - d = 1; - } - for (; d > 0; --d) { - (*outputFunc)(outputStream, eol, eolLen); - } - col = 0; - } - } - - gfree(frags); - - // output the page, "undoing" the layout - } else { - for (flow = flows; flow; flow = flow->next) { - for (blk = flow->blocks; blk; blk = blk->next) { - for (line = blk->lines; line; line = line->next) { - n = line->len; - if (line->hyphenated && (line->next || blk->next)) { - --n; - } - s = new GString(); - dumpFragment(line->text, n, uMap, s); - (*outputFunc)(outputStream, s->getCString(), s->getLength()); - delete s; - if (!line->hyphenated) { - if (line->next) { - (*outputFunc)(outputStream, space, spaceLen); - } else if (blk->next) { - //~ this is a bit of a kludge - we should really do a more - //~ intelligent determination of paragraphs - if (blk->next->lines->words->fontSize == - blk->lines->words->fontSize) { - (*outputFunc)(outputStream, space, spaceLen); - } else { - (*outputFunc)(outputStream, eol, eolLen); - } - } - } - } - } - (*outputFunc)(outputStream, eol, eolLen); - (*outputFunc)(outputStream, eol, eolLen); - } - } - - // end of page - if (pageBreaks) { - (*outputFunc)(outputStream, eop, eopLen); - } - - uMap->decRefCnt(); -} - -void TextPage::assignColumns(TextLineFrag *frags, int nFrags, GBool oneRot) { - TextLineFrag *frag0, *frag1; - int rot, col1, col2, i, j, k; - - // all text in the region has the same rotation -- recompute the - // column numbers based only on the text in the region - if (oneRot) { - qsort(frags, nFrags, sizeof(TextLineFrag), &TextLineFrag::cmpXYLineRot); - rot = frags[0].line->rot; - for (i = 0; i < nFrags; ++i) { - frag0 = &frags[i]; - col1 = 0; - for (j = 0; j < i; ++j) { - frag1 = &frags[j]; - col2 = 0; // make gcc happy - switch (rot) { - case 0: - if (frag0->xMin >= frag1->xMax) { - col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - - frag1->line->col[frag1->start]) + 1; - } else { - for (k = frag1->start; - k < frag1->start + frag1->len && - frag0->xMin >= 0.5 * (frag1->line->edge[k] + - frag1->line->edge[k+1]); - ++k) ; - col2 = frag1->col + - frag1->line->col[k] - frag1->line->col[frag1->start]; - } - break; - case 1: - if (frag0->yMin >= frag1->yMax) { - col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - - frag1->line->col[frag1->start]) + 1; - } else { - for (k = frag1->start; - k < frag1->start + frag1->len && - frag0->yMin >= 0.5 * (frag1->line->edge[k] + - frag1->line->edge[k+1]); - ++k) ; - col2 = frag1->col + - frag1->line->col[k] - frag1->line->col[frag1->start]; - } - break; - case 2: - if (frag0->xMax <= frag1->xMin) { - col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - - frag1->line->col[frag1->start]) + 1; - } else { - for (k = frag1->start; - k < frag1->start + frag1->len && - frag0->xMax <= 0.5 * (frag1->line->edge[k] + - frag1->line->edge[k+1]); - ++k) ; - col2 = frag1->col + - frag1->line->col[k] - frag1->line->col[frag1->start]; - } - break; - case 3: - if (frag0->yMax <= frag1->yMin) { - col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - - frag1->line->col[frag1->start]) + 1; - } else { - for (k = frag1->start; - k < frag1->start + frag1->len && - frag0->yMax <= 0.5 * (frag1->line->edge[k] + - frag1->line->edge[k+1]); - ++k) ; - col2 = frag1->col + - frag1->line->col[k] - frag1->line->col[frag1->start]; - } - break; - } - if (col2 > col1) { - col1 = col2; - } - } - frag0->col = col1; - } - - // the region includes text at different rotations -- use the - // globally assigned column numbers, offset by the minimum column - // number (i.e., shift everything over to column 0) - } else { - col1 = frags[0].col; - for (i = 1; i < nFrags; ++i) { - if (frags[i].col < col1) { - col1 = frags[i].col; - } - } - for (i = 0; i < nFrags; ++i) { - frags[i].col -= col1; - } - } -} - -int TextPage::dumpFragment(Unicode *text, int len, UnicodeMap *uMap, - GString *s) { - char lre[8], rle[8], popdf[8], buf[8]; - int lreLen, rleLen, popdfLen, n; - int nCols, i, j, k; - - nCols = 0; - - if (uMap->isUnicode()) { - - lreLen = uMap->mapUnicode(0x202a, lre, sizeof(lre)); - rleLen = uMap->mapUnicode(0x202b, rle, sizeof(rle)); - popdfLen = uMap->mapUnicode(0x202c, popdf, sizeof(popdf)); - - if (primaryLR) { - - i = 0; - while (i < len) { - // output a left-to-right section - for (j = i; j < len && !unicodeTypeR(text[j]); ++j) ; - for (k = i; k < j; ++k) { - n = uMap->mapUnicode(text[k], buf, sizeof(buf)); - s->append(buf, n); - ++nCols; - } - i = j; - // output a right-to-left section - for (j = i; - j < len && !(unicodeTypeL(text[j]) || unicodeTypeNum(text[j])); - ++j) ; - if (j > i) { - s->append(rle, rleLen); - for (k = j - 1; k >= i; --k) { - n = uMap->mapUnicode(text[k], buf, sizeof(buf)); - s->append(buf, n); - ++nCols; - } - s->append(popdf, popdfLen); - i = j; - } - } - - } else { - - // 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) ; - for (k = i; k > j; --k) { - n = uMap->mapUnicode(text[k], buf, sizeof(buf)); - s->append(buf, n); - ++nCols; - } - i = j; - // output a left-to-right section - for (j = i; j >= 0 && !unicodeTypeR(text[j]); --j) ; - if (j < i) { - s->append(lre, lreLen); - for (k = j + 1; k <= i; ++k) { - n = uMap->mapUnicode(text[k], buf, sizeof(buf)); - s->append(buf, n); - ++nCols; - } - s->append(popdf, popdfLen); - i = j; - } - } - s->append(popdf, popdfLen); - - } - - } else { - for (i = 0; i < len; ++i) { - n = uMap->mapUnicode(text[i], buf, sizeof(buf)); - s->append(buf, n); - nCols += n; - } - } - - return nCols; -} - -#if TEXTOUT_WORD_LIST -TextWordList *TextPage::makeWordList(GBool physLayout) { - return new TextWordList(this, physLayout); -} -#endif - -//------------------------------------------------------------------------ -// TextOutputDev -//------------------------------------------------------------------------ - -static void outputToFile(void *stream, const char *text, int len) { - fwrite(text, 1, len, (FILE *)stream); -} - -TextOutputDev::TextOutputDev(char *fileName, GBool physLayoutA, - double fixedPitchA, GBool rawOrderA, - GBool append) { - text = NULL; - physLayout = physLayoutA; - fixedPitch = physLayout ? fixedPitchA : 0; - rawOrder = rawOrderA; - doHTML = gFalse; - ok = gTrue; - - // open file - needClose = gFalse; - if (fileName) { - if (!strcmp(fileName, "-")) { - outputStream = stdout; -#ifdef WIN32 - // keep DOS from munging the end-of-line characters - setmode(fileno(stdout), O_BINARY); -#endif - } else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) { - needClose = gTrue; - } else { - error(errIO, -1, "Couldn't open text file '{0:s}'", fileName); - ok = gFalse; - return; - } - outputFunc = &outputToFile; - } else { - outputStream = NULL; - } - - // set up text object - text = new TextPage(rawOrderA); -} - -TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, - GBool physLayoutA, double fixedPitchA, - GBool rawOrderA) { - outputFunc = func; - outputStream = stream; - needClose = gFalse; - physLayout = physLayoutA; - fixedPitch = physLayout ? fixedPitchA : 0; - rawOrder = rawOrderA; - doHTML = gFalse; - text = new TextPage(rawOrderA); - ok = gTrue; -} - -TextOutputDev::~TextOutputDev() { - if (needClose) { -#ifdef MACOS - ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); -#endif - fclose((FILE *)outputStream); - } - if (text) { - delete text; - } -} - -void TextOutputDev::startPage(int pageNum, GfxState *state) { - text->startPage(state); -} - -void TextOutputDev::endPage() { - text->endPage(); - text->coalesce(physLayout, fixedPitch, doHTML); - if (outputStream) { - text->dump(outputStream, outputFunc, physLayout); - } -} - -void TextOutputDev::restoreState(GfxState *state) { - text->updateFont(state); -} - -void TextOutputDev::updateFont(GfxState *state) { - text->updateFont(state); -} - -void TextOutputDev::beginString(GfxState *state, GString *s) { -} - -void TextOutputDev::endString(GfxState *state) { -} - -void TextOutputDev::drawChar(GfxState *state, double x, double y, - double dx, double dy, - double originX, double originY, - CharCode c, int nBytes, Unicode *u, int uLen) { - text->addChar(state, x - originX, y - originY, dx, dy, c, nBytes, u, uLen); -} - -void TextOutputDev::incCharCount(int nChars) { - text->incCharCount(nChars); -} - -void TextOutputDev::beginActualText(GfxState *state, Unicode *u, int uLen) { - text->beginActualText(state, u, uLen); -} - -void TextOutputDev::endActualText(GfxState *state) { - text->endActualText(state); -} - -void TextOutputDev::stroke(GfxState *state) { - GfxPath *path; - GfxSubpath *subpath; - double x[2], y[2]; - - if (!doHTML) { - return; - } - path = state->getPath(); - if (path->getNumSubpaths() != 1) { - return; - } - subpath = path->getSubpath(0); - if (subpath->getNumPoints() != 2) { - return; - } - state->transform(subpath->getX(0), subpath->getY(0), &x[0], &y[0]); - state->transform(subpath->getX(1), subpath->getY(1), &x[1], &y[1]); - - // look for a vertical or horizontal line - if (x[0] == x[1] || y[0] == y[1]) { - text->addUnderline(x[0], y[0], x[1], y[1]); - } -} - -void TextOutputDev::fill(GfxState *state) { - GfxPath *path; - GfxSubpath *subpath; - double x[5], y[5]; - double rx0, ry0, rx1, ry1, t; - int i; - - if (!doHTML) { - return; - } - path = state->getPath(); - if (path->getNumSubpaths() != 1) { - return; - } - subpath = path->getSubpath(0); - if (subpath->getNumPoints() != 5) { - return; - } - for (i = 0; i < 5; ++i) { - if (subpath->getCurve(i)) { - return; - } - state->transform(subpath->getX(i), subpath->getY(i), &x[i], &y[i]); - } - - // look for a rectangle - if (x[0] == x[1] && y[1] == y[2] && x[2] == x[3] && y[3] == y[4] && - x[0] == x[4] && y[0] == y[4]) { - rx0 = x[0]; - ry0 = y[0]; - rx1 = x[2]; - ry1 = y[1]; - } else if (y[0] == y[1] && x[1] == x[2] && y[2] == y[3] && x[3] == x[4] && - x[0] == x[4] && y[0] == y[4]) { - rx0 = x[0]; - ry0 = y[0]; - rx1 = x[1]; - ry1 = y[2]; - } else { - return; - } - if (rx1 < rx0) { - t = rx0; - rx0 = rx1; - rx1 = t; - } - if (ry1 < ry0) { - t = ry0; - ry0 = ry1; - ry1 = t; - } - - // skinny horizontal rectangle - if (ry1 - ry0 < rx1 - rx0) { - if (ry1 - ry0 < maxUnderlineWidth) { - ry0 = 0.5 * (ry0 + ry1); - text->addUnderline(rx0, ry0, rx1, ry0); - } - - // skinny vertical rectangle - } else { - if (rx1 - rx0 < maxUnderlineWidth) { - rx0 = 0.5 * (rx0 + rx1); - text->addUnderline(rx0, ry0, rx0, ry1); - } - } -} - -void TextOutputDev::eoFill(GfxState *state) { - if (!doHTML) { - return; - } - fill(state); -} - -void TextOutputDev::processLink(Link *link) { - double x1, y1, x2, y2; - int xMin, yMin, xMax, yMax, x, y; - - if (!doHTML) { - return; - } - link->getRect(&x1, &y1, &x2, &y2); - cvtUserToDev(x1, y1, &x, &y); - xMin = xMax = x; - yMin = yMax = y; - cvtUserToDev(x1, y2, &x, &y); - if (x < xMin) { - xMin = x; - } else if (x > xMax) { - xMax = x; - } - if (y < yMin) { - yMin = y; - } else if (y > yMax) { - yMax = y; - } - cvtUserToDev(x2, y1, &x, &y); - if (x < xMin) { - xMin = x; - } else if (x > xMax) { - xMax = x; - } - if (y < yMin) { - yMin = y; - } else if (y > yMax) { - yMax = y; - } - cvtUserToDev(x2, y2, &x, &y); - if (x < xMin) { - xMin = x; - } else if (x > xMax) { - xMax = x; - } - if (y < yMin) { - yMin = y; - } else if (y > yMax) { - yMax = y; - } - text->addLink(xMin, yMin, xMax, yMax, link); -} - -GBool TextOutputDev::findText(Unicode *s, int len, - GBool startAtTop, GBool stopAtBottom, - GBool startAtLast, GBool stopAtLast, - GBool caseSensitive, GBool backward, - GBool wholeWord, - double *xMin, double *yMin, - double *xMax, double *yMax) { - return text->findText(s, len, startAtTop, stopAtBottom, - startAtLast, stopAtLast, - caseSensitive, backward, wholeWord, - xMin, yMin, xMax, yMax); -} - -GString *TextOutputDev::getText(double xMin, double yMin, - double xMax, double yMax) { - return text->getText(xMin, yMin, xMax, yMax); -} - -GBool TextOutputDev::findCharRange(int pos, int length, - double *xMin, double *yMin, - double *xMax, double *yMax) { - return text->findCharRange(pos, length, xMin, yMin, xMax, yMax); -} - -#if TEXTOUT_WORD_LIST -TextWordList *TextOutputDev::makeWordList() { - return text->makeWordList(physLayout); -} -#endif - -TextPage *TextOutputDev::takeText() { - TextPage *ret; - - ret = text; - text = new TextPage(rawOrder); - return ret; -} diff --git a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/ChangeLog b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/ChangeLog index 0f84b1ceb57..409f65cad84 100644 --- a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/ChangeLog +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/ChangeLog @@ -1,3 +1,13 @@ +2014-05-30 Peter Breitenlohner <peb@mppmu.mpg.de> + + Imported xpdf-3.04 source tree: + ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.04.tar.gz + + * patch-10-exclude-body-of-Page_getDefaultCTM, + patch-20-skip-reading-config-file, + patch-22-exclude-openTempFile, patch-30-include-strings_h, + patch-40-W32TeX: Adapted. + 2012-10-19 Peter Breitenlohner <peb@mppmu.mpg.de> * patch-12-mingw32 (removed): The library now needs '-lgdi32'. diff --git a/Build/source/libs/xpdf/xpdf-3.04-PATCHES/TL-Changes b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/TL-Changes new file mode 100644 index 00000000000..16c6b27b495 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/TL-Changes @@ -0,0 +1,6 @@ +Changes applied to the xpdf-3.04/ tree as obtained from: + ftp://ftp.foolabs.com/pub/xpdf/ + +Removed: + install-sh + diff --git a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-10-exclude-body-of-Page_getDefaultCTM b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-10-exclude-body-of-Page_getDefaultCTM index b2e73f78704..da4d8519c31 100644 --- a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-10-exclude-body-of-Page_getDefaultCTM +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-10-exclude-body-of-Page_getDefaultCTM @@ -1,22 +1,23 @@ Enable compilation with -DPDF_PARSER_ONLY - from: - Derek B. Noonburg <derek@foolabs.com> - -diff -ur -N xpdf-3.03.orig/xpdf/Page.cc xpdf-3.03/xpdf/Page.cc ---- xpdf-3.03.orig/xpdf/Page.cc 2011-08-15 23:08:53.000000000 +0200 -+++ xpdf-3.03/xpdf/Page.cc 2011-08-22 13:52:37.000000000 +0200 -@@ -461,6 +461,7 @@ +diff -ur -N xpdf-3.04.orig/xpdf/Page.cc xpdf-3.04/xpdf/Page.cc +--- xpdf-3.04.orig/xpdf/Page.cc 2014-05-28 20:50:50.000000000 +0200 ++++ xpdf-3.04/xpdf/Page.cc 2014-05-30 19:57:46.000000000 +0200 +@@ -468,9 +468,9 @@ + delete links; + } +-#ifndef PDF_PARSER_ONLY void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI, int rotate, GBool useMediaBox, GBool upsideDown) { +#ifndef PDF_PARSER_ONLY GfxState *state; int i; -@@ -477,4 +478,5 @@ +@@ -487,5 +487,5 @@ ctm[i] = state->getCTM()[i]; } delete state; -+#endif - } +-} + #endif ++} diff --git a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-20-skip-reading-config-file b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-20-skip-reading-config-file index 24d43695ef1..5c20dccdd72 100644 --- a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-20-skip-reading-config-file +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-20-skip-reading-config-file @@ -7,9 +7,9 @@ Han The Thanh <thanh@pdftex.org> Peter Breitenlohner <tex-live@tug.org> -diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc ---- xpdf-3.03.orig/xpdf/GlobalParams.cc 2011-08-15 23:08:53.000000000 +0200 -+++ xpdf-3.03/xpdf/GlobalParams.cc 2012-10-19 10:01:03.000000000 +0200 +diff -ur -N xpdf-3.04.orig/xpdf/GlobalParams.cc xpdf-3.04/xpdf/GlobalParams.cc +--- xpdf-3.04.orig/xpdf/GlobalParams.cc 2014-05-28 20:50:50.000000000 +0200 ++++ xpdf-3.04/xpdf/GlobalParams.cc 2014-05-30 19:29:23.000000000 +0200 @@ -5,6 +5,9 @@ // Copyright 2001-2003 Glyph & Cog, LLC // @@ -20,7 +20,7 @@ diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc #include <aconf.h> -@@ -779,6 +782,7 @@ +@@ -812,6 +815,7 @@ f = NULL; fileName = NULL; if (cfgFileName && cfgFileName[0]) { @@ -28,7 +28,7 @@ diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc fileName = new GString(cfgFileName); if (!(f = fopen(fileName->getCString(), "r"))) { delete fileName; -@@ -811,6 +815,7 @@ +@@ -844,6 +848,7 @@ parseFile(fileName, f); delete fileName; fclose(f); @@ -36,9 +36,9 @@ diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc } } -diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h ---- xpdf-3.03.orig/xpdf/GlobalParams.h 2011-08-15 23:08:53.000000000 +0200 -+++ xpdf-3.03/xpdf/GlobalParams.h 2012-10-19 09:58:39.000000000 +0200 +diff -ur -N xpdf-3.04.orig/xpdf/GlobalParams.h xpdf-3.04/xpdf/GlobalParams.h +--- xpdf-3.04.orig/xpdf/GlobalParams.h 2014-05-28 20:50:50.000000000 +0200 ++++ xpdf-3.04/xpdf/GlobalParams.h 2014-05-30 19:29:23.000000000 +0200 @@ -5,6 +5,9 @@ // Copyright 2001-2003 Glyph & Cog, LLC // @@ -53,8 +53,8 @@ diff -ur -N xpdf-3.03.orig/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h // Initialize the global parameters by attempting to read a config // file. -- GlobalParams(char *cfgFileName); -+ GlobalParams(char *cfgFileName = NULL); +- GlobalParams(const char *cfgFileName); ++ GlobalParams(const char *cfgFileName = NULL); ~GlobalParams(); diff --git a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-22-exclude-openTempFile b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-22-exclude-openTempFile index bf476881371..be04bd4042d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03-PATCHES/patch-22-exclude-openTempFile +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-22-exclude-openTempFile @@ -3,9 +3,9 @@ from: Han The Thanh <thanh@pdftex.org> -diff -ur -N xpdf-3.03.orig/goo/gfile.cc xpdf-3.03/goo/gfile.cc ---- xpdf-3.03.orig/goo/gfile.cc 2011-08-15 23:08:53.000000000 +0200 -+++ xpdf-3.03/goo/gfile.cc 2011-08-22 14:17:58.000000000 +0200 +diff -ur -N xpdf-3.04.orig/goo/gfile.cc xpdf-3.04/goo/gfile.cc +--- xpdf-3.04.orig/goo/gfile.cc 2014-05-28 20:50:50.000000000 +0200 ++++ xpdf-3.04/goo/gfile.cc 2014-05-30 19:42:41.000000000 +0200 @@ -7,6 +7,9 @@ // Copyright 1996-2003 Glyph & Cog, LLC // @@ -16,19 +16,19 @@ diff -ur -N xpdf-3.03.orig/goo/gfile.cc xpdf-3.03/goo/gfile.cc #include <aconf.h> -@@ -440,6 +443,7 @@ +@@ -441,6 +444,7 @@ #endif } +#ifndef PDF_PARSER_ONLY - GBool openTempFile(GString **name, FILE **f, const char *mode, char *ext) { - #if defined(WIN32) - //---------- Win32 ---------- -@@ -549,6 +553,7 @@ + GBool openTempFile(GString **name, FILE **f, + const char *mode, const char *ext) { + #if defined(_WIN32) +@@ -551,6 +555,7 @@ return gTrue; #endif } +#endif - GBool executeCommand(char *cmd) { - #ifdef VMS + GBool createDir(char *path, int mode) { + #ifdef _WIN32 diff --git a/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-30-include-strings_h b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-30-include-strings_h new file mode 100644 index 00000000000..f9b694650b1 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-30-include-strings_h @@ -0,0 +1,15 @@ + The Posix manpage says strcasecmp() is declared in <strings.h> + and this indeed required for AIX 4.3 and xlc. + +diff -ur -N xpdf-3.04.orig/xpdf/GlobalParams.cc xpdf-3.04/xpdf/GlobalParams.cc +--- xpdf-3.04.orig/xpdf/GlobalParams.cc 2014-05-30 19:29:23.000000000 +0200 ++++ xpdf-3.04/xpdf/GlobalParams.cc 2014-05-30 19:47:44.000000000 +0200 +@@ -54,6 +54,8 @@ + #ifdef _WIN32 + # define strcasecmp stricmp + # define strncasecmp strnicmp ++#else ++# include <strings.h> + #endif + + #if MULTITHREADED diff --git a/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-40-W32TeX b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-40-W32TeX new file mode 100644 index 00000000000..53a431f334a --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04-PATCHES/patch-40-W32TeX @@ -0,0 +1,29 @@ + WIN32TeX uses MSVC 5.0 with the kpathsea headers and library. + +diff -ur -N xpdf-3.04.orig/xpdf/GlobalParams.cc xpdf-3.04/xpdf/GlobalParams.cc +--- xpdf-3.04.orig/xpdf/GlobalParams.cc 2014-05-30 19:47:44.000000000 +0200 ++++ xpdf-3.04/xpdf/GlobalParams.cc 2014-05-30 19:52:04.000000000 +0200 +@@ -52,6 +52,8 @@ + #include "GlobalParams.h" + + #ifdef _WIN32 ++# undef strcasecmp ++# undef strncasecmp + # define strcasecmp stricmp + # define strncasecmp strnicmp + #else +diff -ur -N xpdf-3.04.orig/xpdf/config.h xpdf-3.04/xpdf/config.h +--- xpdf-3.04.orig/xpdf/config.h 2014-05-28 20:50:50.000000000 +0200 ++++ xpdf-3.04/xpdf/config.h 2014-05-30 19:52:04.000000000 +0200 +@@ -78,11 +78,6 @@ + // popen + //------------------------------------------------------------------------ + +-#if defined(_MSC_VER) || defined(__BORLANDC__) +-#define popen _popen +-#define pclose _pclose +-#endif +- + #if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(_WIN32) || defined(__DJGPP__) || defined(MACOS) + #define POPEN_READ_MODE "rb" + #else diff --git a/Build/source/libs/xpdf/xpdf-3.03-foolabs/README b/Build/source/libs/xpdf/xpdf-3.04-foolabs/README index 95dd725375a..95dd725375a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03-foolabs/README +++ b/Build/source/libs/xpdf/xpdf-3.04-foolabs/README diff --git a/Build/source/libs/xpdf/xpdf-3.04/ANNOUNCE b/Build/source/libs/xpdf/xpdf-3.04/ANNOUNCE new file mode 100644 index 00000000000..d21dd9c1934 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/ANNOUNCE @@ -0,0 +1,33 @@ +Subject: ANNOUNCE: Xpdf 3.04 - a PDF viewer for X + + +Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the +open source Portable Document Format (PDF) viewer for X. The Xpdf +project also includes a PDF text extractor, PDF-to-PostScript +converter, and various other utilities. + +Xpdf runs under the X Window System on Unix, and OS/2. The non-X +components (pdftops, pdftotext, etc.) also run on Win32 systems and +should run on pretty much any system with a decent C++ compiler. + +Major changes: +* New text extractor. +* Added the pdftohtml tool. +* Added the pdftopng tool. +* New trapezoid-based rasterizer core (for performance). + +See the `CHANGES' file for a complete list of changes. + +Source (C++ and C) is available, and it should be fairly easy to +compile for UNIX, OS/2, and Win32. + +More information, source code, and precompiled binaries are on the +xpdf web page and ftp site: + + http://www.foolabs.com/xpdf/ + ftp://ftp.foolabs.com/pub/xpdf/ + +For information on commercial licensing and consulting, please see the +Glyph & Cog web site: + + http://www.glyphandcog.com/ diff --git a/Build/source/libs/xpdf/xpdf-3.03/CHANGES b/Build/source/libs/xpdf/xpdf-3.04/CHANGES index cde9756bbb3..d2228d233b3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/CHANGES +++ b/Build/source/libs/xpdf/xpdf-3.04/CHANGES @@ -2147,3 +2147,177 @@ Implement embedding of external 16-bit fonts (without subsetting) in PostScript output. Added the minLineWidth xpdfrc command. Added warning messages for font substitutions. + +3.04 (2014-may-28) +------------------ +New text extractor. +Added the pdftohtml tool. +Added the pdftopng tool. +New trapezoid-based rasterizer core (for performance). +Generate appearance streams for Line, PolyLine, and Polygon + annotations. +Added the closeWindowOrQuit command, and changed the default binding + for ctrl-W from closeWindow to closeWindowOrQuit. +Implemented the new AES-256 mode (R=6, Acrobat X). +Add an object cache. +Added a small cache for object streams. +Modify PSOutputDev to use LZW compression instead of RLE, with a + fallback to RLE if the "psLZW no" setting is given. +Pdfinfo now prints page rotation info. +Modified ImageOutputDev, used by pdfimages, to output the masks and + soft masks used when drawing images. +Remove non-printable characters from error output, just in case they + might cause problems for the terminal program. +Added initial support for Code3of9 bar codes in XFA forms. +Added the mapExtTrueTypeFontsViaUnicode xpdfrc command. +Apply stroke adjustment to rectangular images and clipping regions (in + addition to strokes and fills). +Decode JPEG 2000 images at less than full resolution if the full res + image isn't needed (i.e., if the raw image is higher resolution than + the output). +Implemented knockout groups. +Removed t1lib support. +Added support for images with 16-bit components. +Rewrote the Dict class to use a hash table; as a side effect, this + handles dictionaries with multiple definitions for a key, which are + in violation of the spec, but Acrobat appears to handle. +The transformed line width computation -- used to implement the + minLineWidth setting, and the hairline threshold in monochrome mode -- + was incorrect. +Pdftops was not correctly handling the case where it couldn't find + a 16-bit font -- this led to crashes and/or invalid PostScript. +A bug in FlateStream::getBlock() was causing problems with narrow + images. +Use the correct _WIN32 define instead of WIN32. +Use copy-on-write for the clip path in SplashState (when doing gsave), + for performance. +Added a Solaris-specific entry to the ghostscript font search path. +SplashState was initializing line width to 0 instead of 1. +Abort processing on a content stream after getting 500 errors + (undefined operator, wrong number of args) -- this avoids very long + processing time for malicious PDF files using bogus RLE encoded + content streams. +Added the psUseCropBoxAsPage xpdfrc option; "pdftops -pagecrop" now + sets psUseCropBoxAsPage; "pdftops -pagecrop -paper match" now uses + the CropBox as the page size. +Re-architected the AcroForm support code into a separate AcroForm + module. +Fixed the handling of overprinting/transparency interaction, using + the CompatibleOverprint blend mode. +The TIFF predictor code for the 1-bit-per-pixel case was broken. +For triangle and patch mesh shadings (types 4-7) with color functions, + interpolate the function parameter not the color. +Check the fontFile/fontDir commands before (instead of after) doing + Base-14 substitution in PS output. +Correctly handle non-embedded TrueType fonts that have an Identity + ToUnicode mapping (display and PS output were failing). +Added support for XFA form rendering, including an "enableXFA" xpdfrc + setting. +Handle PFB Type 1 fonts when generating PostScript output. +Unwind any extraneous saved graphics state at the end of the page + (before drawing annotations). +Added some integer overflow checks in the GString class. +Handle 16-bit components in JPEG 2000 images. +ActualText spans can end without a valid font, in which case + TextPage::beginWord was crashing. +The Domain entry in function shadings wasn't being parsed correctly. +Fixed a bug in the JPEG decoder - successive approximation + (progressive mode) coefficients weren't being handled correctly. +Added a better infinite loop test to the xref parser. +When generating PostScript, merge reused TrueType fonts (if their + code-to-GID mappings are the same). +Tweak the Gouraud triangle shaded fill code to end the recursive + splitting if the triangles get sufficiently small. +Do bilinear interpolation when upsampling images. +When skipping extraneous image data from an inline image, look for + EI<whitespace> instead of just EI. +When writing to stdout on Windows, pdftoppm now sets the file mode to + binary. [Thanks to Robert Frunzke.] +Accept strings as well as names for the BaseFont entry in font + objects. +Removed the TEXTOUT_WORD_LIST config option (with the new text + extractor, this is always enabled). +Fixed a bug in the JBIG2 decoder (the TPGD context for template #3 in + readGenericBitmap was incorrect). +Rewrote the PostScriptFunction code for performance. +Handle 8-bit OpenType CFF fonts that are missing required tables in + the OpenType wrapper. +Handle tiling patterns with reversed coordinates in their bounding + boxes. +Added support for 64-bit file offsets, i.e., PDF files larger than + 2GB. +Optimize the code that rasterizes pattern-filled image masks. +Added support for Mac OS X system fonts (Base-14 only). +The backdrop color in luminosity-type soft mask groups was not being + handled correctly. +Modified behavior of "pdftops -paper match -duplex ..." - it will now + duplex consecutive same-sized pages. +Tweak the handling of degenerate fills ('moveto lineto fill') to + match Adobe. +Don't honor the OPM=1 setting with ICCBased CMYK color spaces. +Whole-word searches were treating certain punctuation (Unicode number + separators and terminators) as part of the word, e.g., searching for + "foo" would not match "foo,". +Use the TextString class everywhere it makes sense. +Removed the unnecessary segment sort in Splash (performance + optimization). +Handle hyperlinks that use Widget-type annotations. +Fix up the integer overflow checks to avoid issues with clever + compilers. [Thanks to Nickolai Zeldovich.] +Correctly handle streams with missing Length entries in damaged PDF + files. +Added a compile-time option (LOAD_FONTS_FROM_MEM) to load fonts from + memory rather than temporary files on disk. +Added the psRasterSliceSize xpdfrc option. +Fixed a case in the JPEG 2000 arithmetic decoder where extra data is + present in packet i, and needs to be saved for use in packet i+1. +Fixed a bug in the JPEG 2000 decoder related to images with fewer than + 8 bits per component. +Handle the case in PSOutputDev where slice size overflows a 32-bit + integer. +Add (partial) support for TrueType cmap format 2. +Always pass FT_LOAD_NO_BITMAP to FreeType -- bitmaps apparently fail + with rotated characters. +Support fonts specified in ExtGState dictionaries. +Annotations with empty Border arrays should not draw a border. +Fix the CMap parser to handle large CID ranges. +Check for Type 3 CharProcs that call q or Q before the d0/d1 operator, + and treat them as uncacheable. +Invert the selection color when starting in reverse video mode. +Device{Gray,RGB,CMYK} cannot be mapped via a resource dict. +Changed the PS output for masked images (explicit and color key + masking): use a plain old clip path instead of rectclip to avoid + array overflows. +Check the StemSnapH/V arrays when converting Type 1C fonts to Type 1 - + if there are any duplicate or out-of-order values, skip that + StemSnapH/V array. +Added the psMinLineWidth xpdfrc setting. +Fix an obscure issue in converting TrueType fonts to Type 42, related + to empty glyph descriptions (12 zero bytes). +Pdftops now reports an error if there were any I/O errors writing to + the PS output file. +Fix vertical text (CJK fonts) in PS output -- offset the character + origin correctly. +Increased the number of digits used by pdfimages for the image number + from three to four. +Handle right-to-left (e.g., Arabic) ligatures correctly in the text + extractor. +Added the -loc and -locPS options to pdffonts. +Extend the object parser recursion limit to cover Stream::addFilters() + / Stream::makeFilters() - to avoid another possibility of stack + overflow. +Disable FreeType autohinting, because it can fail badly with font + subsets that use invalid glyph names -- except in the case of Type 1 + fonts, which look much better with light autohinting. +Modified the rasterizer pipeline functions to process a scan line at a + time (for performance). +Removed VMS build support (it hasn't been updated in ages). +Removed pdftotext's '-htmlmeta' option (use pdftohtml instead). +PSOutputDev's font/form setup code, and pdffonts, were not scanning + soft mask groups in ExtGState dictionaries. +Invalid DCT input (e.g., from a damaged PDF file) could overflow the + dctClip array. +When upsampling an image mask or image with a large resulting image + size, do it in stream mode instead of prescaling the whole image + (to avoid running out of memory). +Added infinite loop detection to pdffonts. diff --git a/Build/source/libs/xpdf/xpdf-3.03/COPYING b/Build/source/libs/xpdf/xpdf-3.04/COPYING index a43ea2126fb..a43ea2126fb 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/COPYING +++ b/Build/source/libs/xpdf/xpdf-3.04/COPYING diff --git a/Build/source/libs/xpdf/xpdf-3.03/COPYING3 b/Build/source/libs/xpdf/xpdf-3.04/COPYING3 index 94a9ed024d3..94a9ed024d3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/COPYING3 +++ b/Build/source/libs/xpdf/xpdf-3.04/COPYING3 diff --git a/Build/source/libs/xpdf/xpdf-3.03/INSTALL b/Build/source/libs/xpdf/xpdf-3.04/INSTALL index 366a46d4910..fce20fdbfa8 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/INSTALL +++ b/Build/source/libs/xpdf/xpdf-3.04/INSTALL @@ -1,11 +1,11 @@ Xpdf ==== -version 3.03 -2011-aug-15 +version 3.04 +2014-may-28 The Xpdf software and documentation are -copyright 1996-2011 Glyph & Cog, LLC. +copyright 1996-2014 Glyph & Cog, LLC. Email: derekn@foolabs.com WWW: http://www.foolabs.com/xpdf/ @@ -36,12 +36,6 @@ different systems. --with-freetype2-library=PATH --with-freetype2-includes=PATH - (The include path is the directory which contains the freetype2 - directory, i.e., do NOT include "freetype2" in the - --with-freetype2-includes path. For example, with the default - installation, the library path is /usr/local/lib and the include - path is /usr/local/include/freetype2.) - * If you have Motif (or Lesstif) installed in a non-standard place, you can use the following options to tell configure where to find it: @@ -112,35 +106,6 @@ If you want to run a quick test, there is a tiny PDF file included with xpdf, as misc/hello.pdf . -************* -*** VMS *** -************* - -* The 'stddef.h' include file which comes with older versions of gcc - may be missing a definition for wchar_t. In this case, add the - following lines: - ----- - File GNU_CC:[INCLUDE]STDDEF.H;2 - 44 /* Wide characters, not yet supported by VAXCRTL [match VAXC's <stddef. - 45 #if !defined(_WCHAR_T) && !defined(_WCHAR_T_) - 46 typedef unsigned int wchar_t; - 47 #endif - 48 #define _WCHAR_T - 49 #define _WCHAR_T_ - 50 - ----- - -* Read the instructions at the top of vms_make.com. - -* Type '@vms_make' in the top-level directory. You'll probably want - to use some of the options described in the file. - -* The executables will be left in '[.xpdf]'. - -If you want to run a quick test, there is a tiny PDF file included -with xpdf, as misc/hello.pdf . - - ************** *** OS/2 *** ************** @@ -176,8 +141,7 @@ port (thanks to Michael A. Richmond for these instructions): * to build xpdf: - cd xpdf-x.yy - - ./configure --with-t1-library=/usr/local/lib - --with-t1-includes=/usr/local/include + - ./configure --with-freetype2-library=/usr/lib --with-freetype2-includes=/usr/include/freetype2 --with-Xm-library=/usr/lib diff --git a/Build/source/libs/xpdf/xpdf-3.03/Makefile.in b/Build/source/libs/xpdf/xpdf-3.04/Makefile.in index e4391e6b43d..40f74491d66 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/Makefile.in +++ b/Build/source/libs/xpdf/xpdf-3.04/Makefile.in @@ -119,7 +119,7 @@ clean: distclean: clean rm -f config.log config.status config.cache rm -f aconf.h - rm -f Makefile goo/Makefile xpdf/Makefile + rm -f Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile rm -f goo/Makefile.dep fofi/Makefile.dep splash/Makefile.dep xpdf/Makefile.dep rm -f goo/Makefile.in.bak fofi/Makefile.in.bak splash/Makefile.in.bak xpdf/Makefile.in.bak touch goo/Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/README b/Build/source/libs/xpdf/xpdf-3.04/README index e97791ce5b2..93a1bc54766 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/README +++ b/Build/source/libs/xpdf/xpdf-3.04/README @@ -1,11 +1,11 @@ Xpdf ==== -version 3.03 -2011-aug-15 +version 3.04 +2014-may-28 The Xpdf software and documentation are -copyright 1996-2011 Glyph & Cog, LLC. +copyright 1996-2014 Glyph & Cog, LLC. Email: derekn@foolabs.com WWW: http://www.foolabs.com/xpdf/ @@ -23,7 +23,7 @@ the name of Adobe's PDF software.) The Xpdf project also includes a PDF text extractor, PDF-to-PostScript converter, and various other utilities. -Xpdf runs under the X Window System on UNIX, VMS, and OS/2. The non-X +Xpdf runs under the X Window System on UNIX and OS/2. The non-X components (pdftops, pdftotext, etc.) also run on Windows and Mac OSX systems and should run on pretty much any system with a decent C++ compiler. Xpdf will run on 32-bit and 64-bit machines. @@ -68,9 +68,9 @@ Xpdf is developed and tested on Linux. In addition, it has been compiled by others on Solaris, AIX, HP-UX, Digital Unix, Irix, and numerous other Unix implementations, as well -as VMS and OS/2. It should work on pretty much any system which runs -X11 and has Unix-like libraries. You'll need ANSI C++ and C compilers -to compile it. +as OS/2. It should work on pretty much any system which runs X11 and +has Unix-like libraries. You'll need ANSI C++ and C compilers to +compile it. The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdffonts, pdfdetach, pdftoppm, and pdfimages) can also be compiled on Windows @@ -137,7 +137,7 @@ their man pages): pdfimages -- extracts the images from a PDF file Command line options and many other details are described in the man -pages (xpdf(1), etc.) and the VMS help files (xpdf.hlp, etc.). +pages: xpdf(1), etc. All of these utilities read an optional configuration file: see the xpdfrc(5) man page. @@ -182,6 +182,15 @@ bug listed here, please send me email, with a pointer (URL, ftp site, etc.) to the PDF file. +Third-Party Libraries +--------------------- + +Xpdf uses the following libraries: +* FreeType [http://www.freetype.org/] +* libpng [http://www.libpng.com/pub/png/libpng.html] (used by pdftohtml) +* zlib [http://zlib.net/] (used by pdftohtml) + + Acknowledgments --------------- diff --git a/Build/source/libs/xpdf/xpdf-3.03/aclocal.m4 b/Build/source/libs/xpdf/xpdf-3.04/aclocal.m4 index b3aeea2fda6..b3aeea2fda6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/aclocal.m4 +++ b/Build/source/libs/xpdf/xpdf-3.04/aclocal.m4 diff --git a/Build/source/libs/xpdf/xpdf-3.03/aconf-dj.h b/Build/source/libs/xpdf/xpdf-3.04/aconf-dj.h index 24492dfe2a1..4c4beff68d1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/aconf-dj.h +++ b/Build/source/libs/xpdf/xpdf-3.04/aconf-dj.h @@ -55,11 +55,6 @@ #undef HAVE_X11_XPM_H /* - * This is defined if using t1lib. - */ -#undef HAVE_T1LIB_H - -/* * One of these is defined if using FreeType (version 1 or 2). */ #undef HAVE_FREETYPE_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/aconf-win32.h b/Build/source/libs/xpdf/xpdf-3.04/aconf-win32.h index 240d04600a1..67bbb443874 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/aconf-win32.h +++ b/Build/source/libs/xpdf/xpdf-3.04/aconf-win32.h @@ -35,11 +35,6 @@ #define USE_EXCEPTIONS 1 /* - * Enable word list support. - */ -#undef TEXTOUT_WORD_LIST - -/* * Use fixed point (instead of floating point) arithmetic. */ #undef USE_FIXEDPOINT @@ -72,6 +67,7 @@ #define HAVE_STD_SORT 1 #undef HAVE_FSEEKO #undef HAVE_FSEEK64 +#define HAVE_FSEEKI64 1 #undef _FILE_OFFSET_BITS #undef _LARGE_FILES #undef _LARGEFILE_SOURCE @@ -83,11 +79,6 @@ #undef HAVE_X11_XPM_H /* - * This is defined if using t1lib. - */ -#undef HAVE_T1LIB_H - -/* * One of these is defined if using FreeType (version 1 or 2). */ #undef HAVE_FREETYPE_H @@ -111,11 +102,11 @@ /* * Defined if the Splash library is avaiable. */ -#undef HAVE_SPLASH +#define HAVE_SPLASH 1 /* * Enable support for CMYK output. */ -#undef SPLASH_CMYK +#define SPLASH_CMYK 1 #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/aconf.h.in b/Build/source/libs/xpdf/xpdf-3.04/aconf.h.in index 42c04d8ad1a..91a9ce48d62 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/aconf.h.in +++ b/Build/source/libs/xpdf/xpdf-3.04/aconf.h.in @@ -35,11 +35,6 @@ #undef USE_EXCEPTIONS /* - * Enable word list support. - */ -#undef TEXTOUT_WORD_LIST - -/* * Use fixed point (instead of floating point) arithmetic. */ #undef USE_FIXEDPOINT @@ -72,6 +67,7 @@ #undef HAVE_STD_SORT #undef HAVE_FSEEKO #undef HAVE_FSEEK64 +#undef HAVE_FSEEKI64 #undef _FILE_OFFSET_BITS #undef _LARGE_FILES #undef _LARGEFILE_SOURCE @@ -83,11 +79,6 @@ #undef HAVE_X11_XPM_H /* - * This is defined if using t1lib. - */ -#undef HAVE_T1LIB_H - -/* * One of these is defined if using FreeType 2. */ #undef HAVE_FREETYPE_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/aconf2.h b/Build/source/libs/xpdf/xpdf-3.04/aconf2.h index b51de1e9cb6..59a1740ab93 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/aconf2.h +++ b/Build/source/libs/xpdf/xpdf-3.04/aconf2.h @@ -28,11 +28,4 @@ # endif #endif -/* - * Make sure WIN32 is defined if appropriate. - */ -#if defined(_WIN32) && !defined(WIN32) -# define WIN32 -#endif - #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/configure b/Build/source/libs/xpdf/xpdf-3.04/configure index 03cd2de7b0a..b6cd8bdaec4 100755 --- a/Build/source/libs/xpdf/xpdf-3.03/configure +++ b/Build/source/libs/xpdf/xpdf-3.04/configure @@ -1,11 +1,9 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65. +# Generated by GNU Autoconf 2.69. # # -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation @@ -89,6 +87,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -133,6 +132,31 @@ export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh @@ -166,7 +190,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi -test x\$exitcode = x0 || exit 1" +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && @@ -211,14 +236,25 @@ IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 fi if test x$as_have_required = xno; then : @@ -316,10 +352,18 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take @@ -356,19 +400,19 @@ else fi # as_fn_arith -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. +# script with STATUS, using 1 if that was 0. as_fn_error () { - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $1" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -441,6 +485,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). @@ -475,16 +523,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -496,28 +544,8 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -530,7 +558,7 @@ test -n "$DJDIR" || exec 7<&0 </dev/null exec 6>&1 # Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -593,14 +621,16 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +EXTRA_CFLAGS +EXTRA_LIBS XPDF_TARGET X libpaper_CFLAGS libpaper_LIBS +libpng_CFLAGS +libpng_LIBS freetype2_CFLAGS freetype2_LIBS -t1_CFLAGS -t1_LIBS Sgm_CFLAGS Sgm_LIBS Xm_CFLAGS @@ -685,7 +715,6 @@ enable_no_text_select enable_opi enable_multithreaded enable_exceptions -enable_wordlist enable_fixedpoint enable_cmyk with_appdef_dir @@ -705,6 +734,8 @@ with_Sgm_library with_Sgm_includes with_freetype2_library with_freetype2_includes +with_libpng_library +with_libpng_includes with_libpaper_library with_libpaper_includes ' @@ -783,8 +814,9 @@ do fi case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -829,7 +861,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -855,7 +887,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1059,7 +1091,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1075,7 +1107,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1105,8 +1137,8 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information." + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" ;; *=*) @@ -1114,7 +1146,7 @@ Try \`$0 --help' for more information." # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error "invalid variable name: \`$ac_envvar'" ;; + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1124,7 +1156,7 @@ Try \`$0 --help' for more information." $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1132,13 +1164,13 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error "missing argument to $ac_option" + as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1161,7 +1193,7 @@ do [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1175,8 +1207,6 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1191,9 +1221,9 @@ test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error "working directory cannot be determined" + as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error "pwd does not report name of working directory" + as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1232,11 +1262,11 @@ else fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1276,7 +1306,7 @@ Configuration: --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages + -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1333,14 +1363,14 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-a4-paper use A4 paper size instead of Letter for - PostScript output + --enable-a4-paper use A4 paper size instead of Letter for PostScript + output --enable-no-text-select do not allow text selection --enable-opi include support for OPI comments --enable-multithreaded include support for multithreading --enable-exceptions use C++ exceptions - --enable-wordlist include support for building word lists - --enable-fixedpoint use fixed point (instead of floating point) arithmetic + --enable-fixedpoint use fixed point (instead of floating point) + arithmetic --enable-cmyk include support for CMYK rasterization --disable-largefile omit support for large files @@ -1377,6 +1407,10 @@ Optional Packages: use freetype2 library (FreeType2 font rasterizer - version 2.0.5+) --with-freetype2-includes=DIR set directory for freetype2 headers + --with-libpng-library=PATH + use libpng library (PNG library) + --with-libpng-includes=DIR + set directory for libpng headers --with-libpaper-library=PATH use libpaper library (Debian libpaper) --with-libpaper-includes=DIR @@ -1462,9 +1496,9 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.65 +generated by GNU Autoconf 2.69 -Copyright (C) 2009 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1508,7 +1542,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1540,7 +1574,7 @@ $as_echo "$ac_try_echo"; } >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext + test -x conftest$ac_exeext }; then : ac_retval=0 else @@ -1554,7 +1588,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link @@ -1592,7 +1626,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile @@ -1618,7 +1652,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { + test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : @@ -1629,7 +1663,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp @@ -1642,7 +1676,7 @@ ac_fn_c_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1697,7 +1731,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func @@ -1728,7 +1762,7 @@ $as_echo "$ac_try_echo"; } >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext + test -x conftest$ac_exeext }; then : ac_retval=0 else @@ -1742,7 +1776,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link @@ -1755,7 +1789,7 @@ ac_fn_cxx_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1810,7 +1844,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_func @@ -1822,10 +1856,10 @@ $as_echo "$ac_res" >&6; } ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -1861,7 +1895,7 @@ if ac_fn_c_try_cpp "$LINENO"; then : else ac_header_preproc=no fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } @@ -1888,7 +1922,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -1897,7 +1931,7 @@ eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel @@ -1938,7 +1972,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run @@ -1952,7 +1986,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1970,7 +2004,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile cat >config.log <<_ACEOF @@ -1978,7 +2012,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.65. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2088,11 +2122,9 @@ trap 'exit_status=$? { echo - cat <<\_ASBOX -## ---------------- ## + $as_echo "## ---------------- ## ## Cache variables. ## -## ---------------- ## -_ASBOX +## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( @@ -2126,11 +2158,9 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ) echo - cat <<\_ASBOX -## ----------------- ## + $as_echo "## ----------------- ## ## Output variables. ## -## ----------------- ## -_ASBOX +## ----------------- ##" echo for ac_var in $ac_subst_vars do @@ -2143,11 +2173,9 @@ _ASBOX echo if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## + $as_echo "## ------------------- ## ## File substitutions. ## -## ------------------- ## -_ASBOX +## ------------------- ##" echo for ac_var in $ac_subst_files do @@ -2161,11 +2189,9 @@ _ASBOX fi if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## + $as_echo "## ----------- ## ## confdefs.h. ## -## ----------- ## -_ASBOX +## ----------- ##" echo cat confdefs.h echo @@ -2220,7 +2246,12 @@ _ACEOF ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - ac_site_file1=$CONFIG_SITE + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -2235,7 +2266,11 @@ do { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -2311,7 +2346,7 @@ if $ac_cache_corrupted; then $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -2327,64 +2362,90 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers aconf.h" + # Check whether --enable-a4-paper was given. if test "${enable_a4_paper+set}" = set; then : - enableval=$enable_a4_paper; $as_echo "#define A4_PAPER 1" >>confdefs.h + enableval=$enable_a4_paper; +fi + +if test "x$enable_a4_paper" = "xyes"; then : + $as_echo "#define A4_PAPER 1" >>confdefs.h fi # Check whether --enable-no-text-select was given. if test "${enable_no_text_select+set}" = set; then : - enableval=$enable_no_text_select; $as_echo "#define NO_TEXT_SELECT 1" >>confdefs.h + enableval=$enable_no_text_select; +fi + +if test "x$enable_no_text_select" = "xyes"; then : + $as_echo "#define NO_TEXT_SELECT 1" >>confdefs.h fi # Check whether --enable-opi was given. if test "${enable_opi+set}" = set; then : - enableval=$enable_opi; $as_echo "#define OPI_SUPPORT 1" >>confdefs.h + enableval=$enable_opi; +fi + +if test "x$enable_opi" = "xyes"; then : + $as_echo "#define OPI_SUPPORT 1" >>confdefs.h fi # Check whether --enable-multithreaded was given. if test "${enable_multithreaded+set}" = set; then : - enableval=$enable_multithreaded; $as_echo "#define MULTITHREADED 1" >>confdefs.h + enableval=$enable_multithreaded; +fi + +if test "x$enable_multithreaded" = "xyes"; then : + $as_echo "#define MULTITHREADED 1" >>confdefs.h fi # Check whether --enable-exceptions was given. if test "${enable_exceptions+set}" = set; then : - enableval=$enable_exceptions; $as_echo "#define USE_EXCEPTIONS 1" >>confdefs.h - + enableval=$enable_exceptions; fi -# Check whether --enable-wordlist was given. -if test "${enable_wordlist+set}" = set; then : - enableval=$enable_wordlist; $as_echo "#define TEXTOUT_WORD_LIST 1" >>confdefs.h +if test "x$enable_exceptions" = "xyes"; then : + $as_echo "#define USE_EXCEPTIONS 1" >>confdefs.h fi # Check whether --enable-fixedpoint was given. if test "${enable_fixedpoint+set}" = set; then : - enableval=$enable_fixedpoint; $as_echo "#define USE_FIXEDPOINT 1" >>confdefs.h + enableval=$enable_fixedpoint; +fi + +if test "x$enable_fixedpoint" = "xyes"; then : + $as_echo "#define USE_FIXEDPOINT 1" >>confdefs.h fi # Check whether --enable-cmyk was given. if test "${enable_cmyk+set}" = set; then : - enableval=$enable_cmyk; $as_echo "#define SPLASH_CMYK 1" >>confdefs.h + enableval=$enable_cmyk; +fi + +if test "x$enable_cmyk" = "xyes"; then : + $as_echo "#define SPLASH_CMYK 1" >>confdefs.h fi # Check whether --with-appdef-dir was given. if test "${with_appdef_dir+set}" = set; then : - withval=$with_appdef_dir; cat >>confdefs.h <<_ACEOF + withval=$with_appdef_dir; +fi + +if test "x$with_appdef_dir" != "xno"; then : + cat >>confdefs.h <<_ACEOF #define APPDEFDIR "$with_appdef_dir" _ACEOF fi - if test "$sysconfdir" = '${prefix}/etc'; then if test "x$prefix" = xNONE; then system_xpdfrc="$ac_default_prefix/etc/xpdfrc" @@ -2409,7 +2470,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2421,7 +2482,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2449,7 +2510,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2461,7 +2522,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2502,7 +2563,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2514,7 +2575,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2542,7 +2603,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2555,7 +2616,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue @@ -2601,7 +2662,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2613,7 +2674,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2645,7 +2706,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2657,7 +2718,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2699,8 +2760,8 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "no acceptable C compiler found in \$PATH -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -2814,9 +2875,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "C compiler cannot create executables -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -2858,8 +2918,8 @@ done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -2916,9 +2976,9 @@ $as_echo "$ac_try_echo"; } >&5 else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run C compiled programs. +as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details." "$LINENO" 5; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -2929,7 +2989,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2969,8 +3029,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of object files: cannot compile -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -2980,7 +3040,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3017,7 +3077,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -3095,7 +3155,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -3104,8 +3164,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -3193,7 +3252,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 $as_echo_n "checking for library containing strerror... " >&6; } -if test "${ac_cv_search_strerror+set}" = set; then : +if ${ac_cv_search_strerror+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -3227,11 +3286,11 @@ for ac_lib in '' cposix; do fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test "${ac_cv_search_strerror+set}" = set; then : + if ${ac_cv_search_strerror+:} false; then : break fi done -if test "${ac_cv_search_strerror+set}" = set; then : +if ${ac_cv_search_strerror+:} false; then : else ac_cv_search_strerror=no @@ -3253,7 +3312,7 @@ fi *) : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } -if test "${ac_cv_prog_cc_c99+set}" = set; then : +if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no @@ -3397,7 +3456,7 @@ main () return 0; } _ACEOF -for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -xc99=all -qlanglvl=extc99 +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : @@ -3428,7 +3487,7 @@ if test "x$ac_cv_prog_cc_c99" != xno; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -3437,8 +3496,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -3524,7 +3582,7 @@ fi esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 $as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } - if test "${ac_cv_prog_cc_stdc+set}" = set; then : + if ${ac_cv_prog_cc_stdc+:} false; then : $as_echo_n "(cached) " >&6 fi @@ -3559,7 +3617,7 @@ if test -z "$CXX"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CXX+set}" = set; then : +if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then @@ -3571,7 +3629,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3603,7 +3661,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : +if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then @@ -3615,7 +3673,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3681,7 +3739,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : +if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3718,7 +3776,7 @@ ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } -if test "${ac_cv_prog_cxx_g+set}" = set; then : +if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag @@ -3802,16 +3860,22 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - for ac_t in install-sh install.sh shtool; do - if test -f "$ac_dir/$ac_t"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/$ac_t -c" - break 2 - fi - done + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi done if test -z "$ac_aux_dir"; then - as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -3840,7 +3904,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : +if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -3860,7 +3924,7 @@ case $as_dir/ in #(( # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -3921,7 +3985,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then : +if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then @@ -3933,7 +3997,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3961,7 +4025,7 @@ if test -z "$ac_cv_prog_RANLIB"; then set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then @@ -3973,7 +4037,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -4016,7 +4080,7 @@ UP_DIR="" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OS/2 (with EMX)" >&5 $as_echo_n "checking for OS/2 (with EMX)... " >&6; } -if test "${xpdf_cv_sys_os2+set}" = set; then : +if ${xpdf_cv_sys_os2+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -4047,7 +4111,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DOS (with DJGPP)" >&5 $as_echo_n "checking for DOS (with DJGPP)... " >&6; } -if test "${xpdf_cv_sys_dos+set}" = set; then : +if ${xpdf_cv_sys_dos+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -4094,7 +4158,7 @@ if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded @@ -4124,7 +4188,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4140,11 +4204,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -4183,7 +4247,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4199,18 +4263,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -4235,8 +4299,8 @@ if test "x$with_x" = xno; then have_x=disabled else case $x_includes,$x_libraries in #( - *\'*) as_fn_error "cannot use X directory names containing '" "$LINENO" 5;; #( - *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then : + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : $as_echo_n "(cached) " >&6 else # One or both of the vars are not set, and there is no cached value. @@ -4253,7 +4317,7 @@ libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then - # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done @@ -4339,7 +4403,7 @@ else fi done fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then @@ -4513,7 +4577,7 @@ if ac_fn_c_try_link "$LINENO"; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } -if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then : +if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4547,14 +4611,14 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } -if test "x$ac_cv_lib_dnet_dnet_ntoa" = x""yes; then : +if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } -if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then : +if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4588,7 +4652,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } -if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = x""yes; then : +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi @@ -4607,14 +4671,14 @@ rm -f core conftest.err conftest.$ac_objext \ # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" -if test "x$ac_cv_func_gethostbyname" = x""yes; then : +if test "x$ac_cv_func_gethostbyname" = xyes; then : fi if test $ac_cv_func_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } -if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then : +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4648,14 +4712,14 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } -if test "x$ac_cv_lib_nsl_gethostbyname" = x""yes; then : +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; } -if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then : +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4689,7 +4753,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } -if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then : +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi @@ -4704,14 +4768,14 @@ fi # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" -if test "x$ac_cv_func_connect" = x""yes; then : +if test "x$ac_cv_func_connect" = xyes; then : fi if test $ac_cv_func_connect = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 $as_echo_n "checking for connect in -lsocket... " >&6; } -if test "${ac_cv_lib_socket_connect+set}" = set; then : +if ${ac_cv_lib_socket_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4745,7 +4809,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 $as_echo "$ac_cv_lib_socket_connect" >&6; } -if test "x$ac_cv_lib_socket_connect" = x""yes; then : +if test "x$ac_cv_lib_socket_connect" = xyes; then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi @@ -4753,14 +4817,14 @@ fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" -if test "x$ac_cv_func_remove" = x""yes; then : +if test "x$ac_cv_func_remove" = xyes; then : fi if test $ac_cv_func_remove = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 $as_echo_n "checking for remove in -lposix... " >&6; } -if test "${ac_cv_lib_posix_remove+set}" = set; then : +if ${ac_cv_lib_posix_remove+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4794,7 +4858,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 $as_echo "$ac_cv_lib_posix_remove" >&6; } -if test "x$ac_cv_lib_posix_remove" = x""yes; then : +if test "x$ac_cv_lib_posix_remove" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi @@ -4802,14 +4866,14 @@ fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" -if test "x$ac_cv_func_shmat" = x""yes; then : +if test "x$ac_cv_func_shmat" = xyes; then : fi if test $ac_cv_func_shmat = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 $as_echo_n "checking for shmat in -lipc... " >&6; } -if test "${ac_cv_lib_ipc_shmat+set}" = set; then : +if ${ac_cv_lib_ipc_shmat+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4843,7 +4907,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 $as_echo "$ac_cv_lib_ipc_shmat" >&6; } -if test "x$ac_cv_lib_ipc_shmat" = x""yes; then : +if test "x$ac_cv_lib_ipc_shmat" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi @@ -4861,7 +4925,7 @@ fi # John Interrante, Karl Berry { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 $as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } -if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then : +if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -4895,7 +4959,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 $as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } -if test "x$ac_cv_lib_ICE_IceConnectionNumber" = x""yes; then : +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi @@ -4908,7 +4972,7 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -4935,8 +4999,7 @@ fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF @@ -4949,7 +5012,7 @@ done if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } -if test "${ac_cv_search_opendir+set}" = set; then : +if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -4983,11 +5046,11 @@ for ac_lib in '' dir; do fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test "${ac_cv_search_opendir+set}" = set; then : + if ${ac_cv_search_opendir+:} false; then : break fi done -if test "${ac_cv_search_opendir+set}" = set; then : +if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no @@ -5006,7 +5069,7 @@ fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } -if test "${ac_cv_search_opendir+set}" = set; then : +if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -5040,11 +5103,11 @@ for ac_lib in '' x; do fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test "${ac_cv_search_opendir+set}" = set; then : + if ${ac_cv_search_opendir+:} false; then : break fi done -if test "${ac_cv_search_opendir+set}" = set; then : +if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no @@ -5072,14 +5135,14 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_fn_cxx_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" -if test "x$ac_cv_func_gethostbyname" = x""yes; then : +if test "x$ac_cv_func_gethostbyname" = xyes; then : fi if test $ac_cv_func_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; } -if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then : +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -5113,7 +5176,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } -if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then : +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi @@ -5300,7 +5363,7 @@ fi for ac_func in rewinddir do : ac_fn_cxx_check_func "$LINENO" "rewinddir" "ac_cv_func_rewinddir" -if test "x$ac_cv_func_rewinddir" = x""yes; then : +if test "x$ac_cv_func_rewinddir" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_REWINDDIR 1 _ACEOF @@ -5311,7 +5374,7 @@ done if test $ac_cv_func_rewinddir = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rewinddir in -lcposix" >&5 $as_echo_n "checking for rewinddir in -lcposix... " >&6; } -if test "${ac_cv_lib_cposix_rewinddir+set}" = set; then : +if ${ac_cv_lib_cposix_rewinddir+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -5345,7 +5408,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cposix_rewinddir" >&5 $as_echo "$ac_cv_lib_cposix_rewinddir" >&6; } -if test "x$ac_cv_lib_cposix_rewinddir" = x""yes; then : +if test "x$ac_cv_lib_cposix_rewinddir" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCPOSIX 1 _ACEOF @@ -5359,7 +5422,7 @@ fi for ac_func in popen do : ac_fn_cxx_check_func "$LINENO" "popen" "ac_cv_func_popen" -if test "x$ac_cv_func_popen" = x""yes; then : +if test "x$ac_cv_func_popen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POPEN 1 _ACEOF @@ -5369,7 +5432,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mkstemp" >&5 $as_echo_n "checking for mkstemp... " >&6; } -if test "${xpdf_cv_func_mkstemp+set}" = set; then : +if ${xpdf_cv_func_mkstemp+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5400,7 +5463,7 @@ if test "$xpdf_cv_func_mkstemp" = yes; then fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mkstemps" >&5 $as_echo_n "checking for mkstemps... " >&6; } -if test "${xpdf_cv_func_mkstemps+set}" = set; then : +if ${xpdf_cv_func_mkstemps+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5432,7 +5495,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether select takes fd_set arguments" >&5 $as_echo_n "checking whether select takes fd_set arguments... " >&6; } -if test "${xpdf_cv_func_select_arg+set}" = set; then : +if ${xpdf_cv_func_select_arg+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5468,7 +5531,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::sort" >&5 $as_echo_n "checking for std::sort... " >&6; } -if test "${xpdf_cv_func_std_sort+set}" = set; then : +if ${xpdf_cv_func_std_sort+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5516,7 +5579,7 @@ if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } -if test "${ac_cv_sys_largefile_CC+set}" = set; then : +if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no @@ -5567,7 +5630,7 @@ $as_echo "$ac_cv_sys_largefile_CC" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } -if test "${ac_cv_sys_file_offset_bits+set}" = set; then : +if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do @@ -5636,7 +5699,7 @@ rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } -if test "${ac_cv_sys_large_files+set}" = set; then : +if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do @@ -5703,11 +5766,13 @@ _ACEOF esac rm -rf conftest* fi + + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 $as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } -if test "${ac_cv_sys_largefile_source+set}" = set; then : +if ${ac_cv_sys_largefile_source+:} false; then : $as_echo_n "(cached) " >&6 else while :; do @@ -5776,7 +5841,7 @@ fi for ac_func in fseek64 do : ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" -if test "x$ac_cv_func_fseek64" = x""yes; then : +if test "x$ac_cv_func_fseek64" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FSEEK64 1 _ACEOF @@ -5789,7 +5854,7 @@ done for ac_func in ftell64 do : ac_fn_c_check_func "$LINENO" "ftell64" "ac_cv_func_ftell64" -if test "x$ac_cv_func_ftell64" = x""yes; then : +if test "x$ac_cv_func_ftell64" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FTELL64 1 _ACEOF @@ -5807,7 +5872,7 @@ fi if test -z "$no_x"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then @@ -5821,7 +5886,7 @@ do for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in @@ -5856,7 +5921,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then - as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP @@ -5870,7 +5935,7 @@ $as_echo "$ac_cv_path_GREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 @@ -5887,7 +5952,7 @@ do for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in @@ -5922,7 +5987,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -5937,7 +6002,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6054,8 +6119,7 @@ do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -6091,7 +6155,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xpm library" >&5 $as_echo_n "checking whether to use Xpm library... " >&6; } -if test "${smr_cv_with_Xpm_library+set}" = set; then : +if ${smr_cv_with_Xpm_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xpm_library=maybe @@ -6115,7 +6179,7 @@ $as_echo "$smr_cv_with_Xpm_library" >&6; } elif test -d "$smr_cv_with_Xpm_library"; then Xpm_LIBS="-L$smr_cv_with_Xpm_library -lXpm" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_Xpm=yes ;; @@ -6147,7 +6211,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xpm header files" >&5 $as_echo_n "checking where to find the Xpm header files... " >&6; } -if test "${smr_cv_with_Xpm_includes+set}" = set; then : +if ${smr_cv_with_Xpm_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xpm_includes= @@ -6159,7 +6223,7 @@ $as_echo "$smr_cv_with_Xpm_includes" >&6; } if test -d "$smr_cv_with_Xpm_includes"; then Xpm_CFLAGS="-I$smr_cv_with_Xpm_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else Xpm_CFLAGS= @@ -6172,7 +6236,7 @@ $as_echo "$smr_cv_with_Xpm_includes" >&6; } for ac_header in X11/xpm.h do : ac_fn_c_check_header_mongrel "$LINENO" "X11/xpm.h" "ac_cv_header_X11_xpm_h" "$ac_includes_default" -if test "x$ac_cv_header_X11_xpm_h" = x""yes; then : +if test "x$ac_cv_header_X11_xpm_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_X11_XPM_H 1 _ACEOF @@ -6202,7 +6266,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpmCreatePixmapFromData in -lXpm" >&5 $as_echo_n "checking for XpmCreatePixmapFromData in -lXpm... " >&6; } -if test "${ac_cv_lib_Xpm_XpmCreatePixmapFromData+set}" = set; then : +if ${ac_cv_lib_Xpm_XpmCreatePixmapFromData+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -6236,7 +6300,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&5 $as_echo "$ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&6; } -if test "x$ac_cv_lib_Xpm_XpmCreatePixmapFromData" = x""yes; then : +if test "x$ac_cv_lib_Xpm_XpmCreatePixmapFromData" = xyes; then : smr_have_Xpm_library=yes else smr_have_Xpm_library=no @@ -6302,7 +6366,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xext library" >&5 $as_echo_n "checking whether to use Xext library... " >&6; } -if test "${smr_cv_with_Xext_library+set}" = set; then : +if ${smr_cv_with_Xext_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xext_library=maybe @@ -6326,7 +6390,7 @@ $as_echo "$smr_cv_with_Xext_library" >&6; } elif test -d "$smr_cv_with_Xext_library"; then Xext_LIBS="-L$smr_cv_with_Xext_library -lXext" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_Xext=yes ;; @@ -6358,7 +6422,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xext header files" >&5 $as_echo_n "checking where to find the Xext header files... " >&6; } -if test "${smr_cv_with_Xext_includes+set}" = set; then : +if ${smr_cv_with_Xext_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xext_includes= @@ -6370,7 +6434,7 @@ $as_echo "$smr_cv_with_Xext_includes" >&6; } if test -d "$smr_cv_with_Xext_includes"; then Xext_CFLAGS="-I$smr_cv_with_Xext_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else Xext_CFLAGS= @@ -6383,7 +6447,7 @@ $as_echo "$smr_cv_with_Xext_includes" >&6; } for ac_header in X11/Xlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "X11/Xlib.h" "ac_cv_header_X11_Xlib_h" "$ac_includes_default" -if test "x$ac_cv_header_X11_Xlib_h" = x""yes; then : +if test "x$ac_cv_header_X11_Xlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_X11_XLIB_H 1 _ACEOF @@ -6413,7 +6477,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XextAddDisplay in -lXext" >&5 $as_echo_n "checking for XextAddDisplay in -lXext... " >&6; } -if test "${ac_cv_lib_Xext_XextAddDisplay+set}" = set; then : +if ${ac_cv_lib_Xext_XextAddDisplay+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -6447,7 +6511,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XextAddDisplay" >&5 $as_echo "$ac_cv_lib_Xext_XextAddDisplay" >&6; } -if test "x$ac_cv_lib_Xext_XextAddDisplay" = x""yes; then : +if test "x$ac_cv_lib_Xext_XextAddDisplay" = xyes; then : smr_have_Xext_library=yes else smr_have_Xext_library=no @@ -6510,7 +6574,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xp library" >&5 $as_echo_n "checking whether to use Xp library... " >&6; } -if test "${smr_cv_with_Xp_library+set}" = set; then : +if ${smr_cv_with_Xp_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xp_library=maybe @@ -6534,7 +6598,7 @@ $as_echo "$smr_cv_with_Xp_library" >&6; } elif test -d "$smr_cv_with_Xp_library"; then Xp_LIBS="-L$smr_cv_with_Xp_library -lXp" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_Xp=yes ;; @@ -6566,7 +6630,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xp header files" >&5 $as_echo_n "checking where to find the Xp header files... " >&6; } -if test "${smr_cv_with_Xp_includes+set}" = set; then : +if ${smr_cv_with_Xp_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xp_includes= @@ -6578,7 +6642,7 @@ $as_echo "$smr_cv_with_Xp_includes" >&6; } if test -d "$smr_cv_with_Xp_includes"; then Xp_CFLAGS="-I$smr_cv_with_Xp_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else Xp_CFLAGS= @@ -6591,7 +6655,7 @@ $as_echo "$smr_cv_with_Xp_includes" >&6; } for ac_header in X11/extensions/Print.h do : ac_fn_c_check_header_mongrel "$LINENO" "X11/extensions/Print.h" "ac_cv_header_X11_extensions_Print_h" "$ac_includes_default" -if test "x$ac_cv_header_X11_extensions_Print_h" = x""yes; then : +if test "x$ac_cv_header_X11_extensions_Print_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_X11_EXTENSIONS_PRINT_H 1 _ACEOF @@ -6621,7 +6685,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpStartPage in -lXp" >&5 $as_echo_n "checking for XpStartPage in -lXp... " >&6; } -if test "${ac_cv_lib_Xp_XpStartPage+set}" = set; then : +if ${ac_cv_lib_Xp_XpStartPage+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -6655,7 +6719,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xp_XpStartPage" >&5 $as_echo "$ac_cv_lib_Xp_XpStartPage" >&6; } -if test "x$ac_cv_lib_Xp_XpStartPage" = x""yes; then : +if test "x$ac_cv_lib_Xp_XpStartPage" = xyes; then : smr_have_Xp_library=yes else smr_have_Xp_library=no @@ -6718,7 +6782,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xt library" >&5 $as_echo_n "checking whether to use Xt library... " >&6; } -if test "${smr_cv_with_Xt_library+set}" = set; then : +if ${smr_cv_with_Xt_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xt_library=maybe @@ -6742,7 +6806,7 @@ $as_echo "$smr_cv_with_Xt_library" >&6; } elif test -d "$smr_cv_with_Xt_library"; then Xt_LIBS="-L$smr_cv_with_Xt_library -lXt" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_Xt=yes ;; @@ -6774,7 +6838,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xt header files" >&5 $as_echo_n "checking where to find the Xt header files... " >&6; } -if test "${smr_cv_with_Xt_includes+set}" = set; then : +if ${smr_cv_with_Xt_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xt_includes= @@ -6786,7 +6850,7 @@ $as_echo "$smr_cv_with_Xt_includes" >&6; } if test -d "$smr_cv_with_Xt_includes"; then Xt_CFLAGS="-I$smr_cv_with_Xt_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else Xt_CFLAGS= @@ -6799,7 +6863,7 @@ $as_echo "$smr_cv_with_Xt_includes" >&6; } for ac_header in X11/Intrinsic.h do : ac_fn_c_check_header_mongrel "$LINENO" "X11/Intrinsic.h" "ac_cv_header_X11_Intrinsic_h" "$ac_includes_default" -if test "x$ac_cv_header_X11_Intrinsic_h" = x""yes; then : +if test "x$ac_cv_header_X11_Intrinsic_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_X11_INTRINSIC_H 1 _ACEOF @@ -6829,7 +6893,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtAppInitialize in -lXt" >&5 $as_echo_n "checking for XtAppInitialize in -lXt... " >&6; } -if test "${ac_cv_lib_Xt_XtAppInitialize+set}" = set; then : +if ${ac_cv_lib_Xt_XtAppInitialize+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -6863,7 +6927,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtAppInitialize" >&5 $as_echo "$ac_cv_lib_Xt_XtAppInitialize" >&6; } -if test "x$ac_cv_lib_Xt_XtAppInitialize" = x""yes; then : +if test "x$ac_cv_lib_Xt_XtAppInitialize" = xyes; then : smr_have_Xt_library=yes else smr_have_Xt_library=no @@ -6926,7 +6990,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Xm library" >&5 $as_echo_n "checking whether to use Xm library... " >&6; } -if test "${smr_cv_with_Xm_library+set}" = set; then : +if ${smr_cv_with_Xm_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xm_library=maybe @@ -6950,7 +7014,7 @@ $as_echo "$smr_cv_with_Xm_library" >&6; } elif test -d "$smr_cv_with_Xm_library"; then Xm_LIBS="-L$smr_cv_with_Xm_library -lXm" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_Xm=yes ;; @@ -6982,7 +7046,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Xm header files" >&5 $as_echo_n "checking where to find the Xm header files... " >&6; } -if test "${smr_cv_with_Xm_includes+set}" = set; then : +if ${smr_cv_with_Xm_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Xm_includes= @@ -6994,7 +7058,7 @@ $as_echo "$smr_cv_with_Xm_includes" >&6; } if test -d "$smr_cv_with_Xm_includes"; then Xm_CFLAGS="-I$smr_cv_with_Xm_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else Xm_CFLAGS= @@ -7007,7 +7071,7 @@ $as_echo "$smr_cv_with_Xm_includes" >&6; } for ac_header in Xm/XmAll.h do : ac_fn_c_check_header_mongrel "$LINENO" "Xm/XmAll.h" "ac_cv_header_Xm_XmAll_h" "$ac_includes_default" -if test "x$ac_cv_header_Xm_XmAll_h" = x""yes; then : +if test "x$ac_cv_header_Xm_XmAll_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_XM_XMALL_H 1 _ACEOF @@ -7037,7 +7101,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XmCreateForm in -lXm" >&5 $as_echo_n "checking for XmCreateForm in -lXm... " >&6; } -if test "${ac_cv_lib_Xm_XmCreateForm+set}" = set; then : +if ${ac_cv_lib_Xm_XmCreateForm+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -7071,7 +7135,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xm_XmCreateForm" >&5 $as_echo "$ac_cv_lib_Xm_XmCreateForm" >&6; } -if test "x$ac_cv_lib_Xm_XmCreateForm" = x""yes; then : +if test "x$ac_cv_lib_Xm_XmCreateForm" = xyes; then : smr_have_Xm_library=yes else smr_have_Xm_library=no @@ -7134,7 +7198,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Sgm library" >&5 $as_echo_n "checking whether to use Sgm library... " >&6; } -if test "${smr_cv_with_Sgm_library+set}" = set; then : +if ${smr_cv_with_Sgm_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Sgm_library=maybe @@ -7158,7 +7222,7 @@ $as_echo "$smr_cv_with_Sgm_library" >&6; } elif test -d "$smr_cv_with_Sgm_library"; then Sgm_LIBS="-L$smr_cv_with_Sgm_library -lSgm" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_Sgm=yes ;; @@ -7190,7 +7254,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the Sgm header files" >&5 $as_echo_n "checking where to find the Sgm header files... " >&6; } -if test "${smr_cv_with_Sgm_includes+set}" = set; then : +if ${smr_cv_with_Sgm_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_Sgm_includes= @@ -7202,7 +7266,7 @@ $as_echo "$smr_cv_with_Sgm_includes" >&6; } if test -d "$smr_cv_with_Sgm_includes"; then Sgm_CFLAGS="-I$smr_cv_with_Sgm_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else Sgm_CFLAGS= @@ -7215,7 +7279,7 @@ $as_echo "$smr_cv_with_Sgm_includes" >&6; } for ac_header in Sgm/HPanedW.h do : ac_fn_c_check_header_mongrel "$LINENO" "Sgm/HPanedW.h" "ac_cv_header_Sgm_HPanedW_h" "$ac_includes_default" -if test "x$ac_cv_header_Sgm_HPanedW_h" = x""yes; then : +if test "x$ac_cv_header_Sgm_HPanedW_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SGM_HPANEDW_H 1 _ACEOF @@ -7245,7 +7309,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SgCreateHorzPanedWindow in -lSgm" >&5 $as_echo_n "checking for SgCreateHorzPanedWindow in -lSgm... " >&6; } -if test "${ac_cv_lib_Sgm_SgCreateHorzPanedWindow+set}" = set; then : +if ${ac_cv_lib_Sgm_SgCreateHorzPanedWindow+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -7279,7 +7343,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&5 $as_echo "$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&6; } -if test "x$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" = x""yes; then : +if test "x$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" = xyes; then : smr_have_Sgm_library=yes else smr_have_Sgm_library=no @@ -7320,7 +7384,7 @@ $as_echo "$as_me: WARNING: requested Sgm library not found!" >&2;} if test "x$smr_have_Xt_library" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XtAppSetExitFlag in -lXt" >&5 $as_echo_n "checking for XtAppSetExitFlag in -lXt... " >&6; } -if test "${ac_cv_lib_Xt_XtAppSetExitFlag+set}" = set; then : +if ${ac_cv_lib_Xt_XtAppSetExitFlag+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -7354,7 +7418,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xt_XtAppSetExitFlag" >&5 $as_echo "$ac_cv_lib_Xt_XtAppSetExitFlag" >&6; } -if test "x$ac_cv_lib_Xt_XtAppSetExitFlag" = x""yes; then : +if test "x$ac_cv_lib_Xt_XtAppSetExitFlag" = xyes; then : $as_echo "#define HAVE_XTAPPSETEXITFLAG 1" >>confdefs.h fi @@ -7362,18 +7426,6 @@ fi fi fi -#dnl ##### Check for t1lib. -#smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer], -# T1_InitLib, t1lib.h, -# -lm, $X_CFLAGS) -# t1lib has some potential security holes, and hasn't been updated in -# years -- if you really want to use it, uncomment the preceding lines, -# and comment out the next two lines -t1_LIBS="" -t1_CFLAGS="" - - - @@ -7400,7 +7452,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use freetype2 library" >&5 $as_echo_n "checking whether to use freetype2 library... " >&6; } -if test "${smr_cv_with_freetype2_library+set}" = set; then : +if ${smr_cv_with_freetype2_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_freetype2_library=maybe @@ -7424,7 +7476,7 @@ $as_echo "$smr_cv_with_freetype2_library" >&6; } elif test -d "$smr_cv_with_freetype2_library"; then freetype2_LIBS="-L$smr_cv_with_freetype2_library -lfreetype" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_freetype2=yes ;; @@ -7456,7 +7508,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the freetype2 header files" >&5 $as_echo_n "checking where to find the freetype2 header files... " >&6; } -if test "${smr_cv_with_freetype2_includes+set}" = set; then : +if ${smr_cv_with_freetype2_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_freetype2_includes= @@ -7468,7 +7520,7 @@ $as_echo "$smr_cv_with_freetype2_includes" >&6; } if test -d "$smr_cv_with_freetype2_includes"; then freetype2_CFLAGS="-I$smr_cv_with_freetype2_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else freetype2_CFLAGS= @@ -7481,7 +7533,7 @@ $as_echo "$smr_cv_with_freetype2_includes" >&6; } for ac_header in ft2build.h do : ac_fn_c_check_header_mongrel "$LINENO" "ft2build.h" "ac_cv_header_ft2build_h" "$ac_includes_default" -if test "x$ac_cv_header_ft2build_h" = x""yes; then : +if test "x$ac_cv_header_ft2build_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FT2BUILD_H 1 _ACEOF @@ -7511,7 +7563,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FT_Get_Name_Index in -lfreetype" >&5 $as_echo_n "checking for FT_Get_Name_Index in -lfreetype... " >&6; } -if test "${ac_cv_lib_freetype_FT_Get_Name_Index+set}" = set; then : +if ${ac_cv_lib_freetype_FT_Get_Name_Index+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -7545,7 +7597,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_freetype_FT_Get_Name_Index" >&5 $as_echo "$ac_cv_lib_freetype_FT_Get_Name_Index" >&6; } -if test "x$ac_cv_lib_freetype_FT_Get_Name_Index" = x""yes; then : +if test "x$ac_cv_lib_freetype_FT_Get_Name_Index" = xyes; then : smr_have_freetype2_library=yes else smr_have_freetype2_library=no @@ -7607,6 +7659,215 @@ fi +# Check whether --with-libpng-library was given. +if test "${with_libpng_library+set}" = set; then : + withval=$with_libpng_library; smr_cv_with_libpng_library=$withval +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libpng library" >&5 +$as_echo_n "checking whether to use libpng library... " >&6; } +if ${smr_cv_with_libpng_library+:} false; then : + $as_echo_n "(cached) " >&6 +else + smr_cv_with_libpng_library=maybe +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_libpng_library" >&5 +$as_echo "$smr_cv_with_libpng_library" >&6; } + + + case x"$smr_cv_with_libpng_library" in + xyes | xmaybe) + libpng_LIBS="-lpng" + with_libpng=$smr_cv_with_libpng_library + ;; + xno) + libpng_LIBS= + with_libpng=no + ;; + *) + if test -f "$smr_cv_with_libpng_library"; then + libpng_LIBS=$smr_cv_with_libpng_library + elif test -d "$smr_cv_with_libpng_library"; then + libpng_LIBS="-L$smr_cv_with_libpng_library -lpng" + else + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 + fi + with_libpng=yes + ;; + esac + + + + + + + + if test ! x"$with_libpng" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-libpng-includes was given. +if test "${with_libpng_includes+set}" = set; then : + withval=$with_libpng_includes; smr_cv_with_libpng_includes=$withval +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the libpng header files" >&5 +$as_echo_n "checking where to find the libpng header files... " >&6; } +if ${smr_cv_with_libpng_includes+:} false; then : + $as_echo_n "(cached) " >&6 +else + smr_cv_with_libpng_includes= +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smr_cv_with_libpng_includes" >&5 +$as_echo "$smr_cv_with_libpng_includes" >&6; } + + if test ! x"$smr_cv_with_libpng_includes" = x; then + if test -d "$smr_cv_with_libpng_includes"; then + libpng_CFLAGS="-I$smr_cv_with_libpng_includes" + else + as_fn_error $? "argument must be a directory" "$LINENO" 5 + fi + else + libpng_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $libpng_CFLAGS " + + for ac_header in png.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "png.h" "ac_cv_header_png_h" "$ac_includes_default" +if test "x$ac_cv_header_png_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PNG_H 1 +_ACEOF + smr_have_libpng_header=yes +else + smr_have_libpng_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_libpng_header != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_write_row in -lpng" >&5 +$as_echo_n "checking for png_write_row in -lpng... " >&6; } +if ${ac_cv_lib_png_png_write_row+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpng $libpng_CFLAGS $libpng_LIBS -lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char png_write_row (); +int +main () +{ +return png_write_row (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_png_png_write_row=yes +else + ac_cv_lib_png_png_write_row=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_write_row" >&5 +$as_echo "$ac_cv_lib_png_png_write_row" >&6; } +if test "x$ac_cv_lib_png_png_write_row" = xyes; then : + smr_have_libpng_library=yes +else + smr_have_libpng_library=no +fi + + fi + + if test x"$smr_have_libpng_library" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libpng library" >&5 +$as_echo "using libpng library" >&6; } + else + libpng_LIBS= + libpng_CFLAGS= + + if test x"$with_libpng" = xmaybe; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using libpng library" >&5 +$as_echo "not using libpng library" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested libpng library not found!" >&5 +$as_echo "$as_me: WARNING: requested libpng library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Check whether --with-libpaper-library was given. if test "${with_libpaper_library+set}" = set; then : withval=$with_libpaper_library; smr_cv_with_libpaper_library=$withval @@ -7615,7 +7876,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libpaper library" >&5 $as_echo_n "checking whether to use libpaper library... " >&6; } -if test "${smr_cv_with_libpaper_library+set}" = set; then : +if ${smr_cv_with_libpaper_library+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_libpaper_library=maybe @@ -7639,7 +7900,7 @@ $as_echo "$smr_cv_with_libpaper_library" >&6; } elif test -d "$smr_cv_with_libpaper_library"; then libpaper_LIBS="-L$smr_cv_with_libpaper_library -lpaper" else - as_fn_error "argument must be boolean, file, or directory" "$LINENO" 5 + as_fn_error $? "argument must be boolean, file, or directory" "$LINENO" 5 fi with_libpaper=yes ;; @@ -7671,7 +7932,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the libpaper header files" >&5 $as_echo_n "checking where to find the libpaper header files... " >&6; } -if test "${smr_cv_with_libpaper_includes+set}" = set; then : +if ${smr_cv_with_libpaper_includes+:} false; then : $as_echo_n "(cached) " >&6 else smr_cv_with_libpaper_includes= @@ -7683,7 +7944,7 @@ $as_echo "$smr_cv_with_libpaper_includes" >&6; } if test -d "$smr_cv_with_libpaper_includes"; then libpaper_CFLAGS="-I$smr_cv_with_libpaper_includes" else - as_fn_error "argument must be a directory" "$LINENO" 5 + as_fn_error $? "argument must be a directory" "$LINENO" 5 fi else libpaper_CFLAGS= @@ -7696,7 +7957,7 @@ $as_echo "$smr_cv_with_libpaper_includes" >&6; } for ac_header in paper.h do : ac_fn_c_check_header_mongrel "$LINENO" "paper.h" "ac_cv_header_paper_h" "$ac_includes_default" -if test "x$ac_cv_header_paper_h" = x""yes; then : +if test "x$ac_cv_header_paper_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PAPER_H 1 _ACEOF @@ -7726,7 +7987,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for paperinit in -lpaper" >&5 $as_echo_n "checking for paperinit in -lpaper... " >&6; } -if test "${ac_cv_lib_paper_paperinit+set}" = set; then : +if ${ac_cv_lib_paper_paperinit+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -7760,7 +8021,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_paper_paperinit" >&5 $as_echo "$ac_cv_lib_paper_paperinit" >&6; } -if test "x$ac_cv_lib_paper_paperinit" = x""yes; then : +if test "x$ac_cv_lib_paper_paperinit" = xyes; then : smr_have_libpaper_library=yes else smr_have_libpaper_library=no @@ -7808,6 +8069,11 @@ fi +EXTRA_LIBS= +EXTRA_CFLAGS= + + + ac_config_files="$ac_config_files Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile" cat >confcache <<\_ACEOF @@ -7874,10 +8140,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && + if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} @@ -7893,6 +8170,7 @@ DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= +U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -7908,7 +8186,7 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -8009,6 +8287,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -8054,19 +8333,19 @@ export LANGUAGE (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. +# script with STATUS, using 1 if that was 0. as_fn_error () { - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $1" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -8204,16 +8483,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -8262,7 +8541,7 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -8273,28 +8552,16 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -8316,7 +8583,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.65. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -8378,10 +8645,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.65, +configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" -Copyright (C) 2009 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -8397,11 +8664,16 @@ ac_need_defaults=: while test $# != 0 do case $1 in - --*=*) + --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; *) ac_option=$1 ac_optarg=$2 @@ -8423,6 +8695,7 @@ do $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -8435,7 +8708,7 @@ do ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - as_fn_error "ambiguous option: \`$1' + as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; @@ -8444,7 +8717,7 @@ Try \`$0 --help' for more information.";; ac_cs_silent=: ;; # This is an error. - -*) as_fn_error "unrecognized option: \`$1' + -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -8464,7 +8737,7 @@ fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' @@ -8500,7 +8773,7 @@ do "splash/Makefile") CONFIG_FILES="$CONFIG_FILES splash/Makefile" ;; "xpdf/Makefile") CONFIG_FILES="$CONFIG_FILES xpdf/Makefile" ;; - *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -8522,9 +8795,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -8532,12 +8806,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -8554,12 +8829,12 @@ if test "x$ac_cr" = x; then fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\r' + ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -8568,18 +8843,18 @@ _ACEOF echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -8587,7 +8862,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -8635,7 +8910,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -8667,21 +8942,29 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error "could not setup config files machinery" "$LINENO" 5 +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// s/^[^=]*=[ ]*$// }' fi @@ -8693,7 +8976,7 @@ fi # test -n "$CONFIG_FILES" # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || +cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF @@ -8705,11 +8988,11 @@ _ACEOF # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then break elif $ac_last_try; then - as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -8794,7 +9077,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error "could not setup config headers machinery" "$LINENO" 5 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" @@ -8807,7 +9090,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -8826,7 +9109,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -8835,7 +9118,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -8861,8 +9144,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -8992,23 +9275,24 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 +which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} +which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # @@ -9017,21 +9301,21 @@ which seems to be undefined. Please make sure it is defined." >&2;} if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error "could not create -" "$LINENO" 5 + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; @@ -9046,7 +9330,7 @@ _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -9067,7 +9351,7 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit $? + $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 @@ -9095,3 +9379,8 @@ $as_echo "$as_me: WARNING: -- You will be able to compile pdftops, pdftotext, pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf or pdftoppm" >&2;} fi + +if test "x$smr_have_libpng_library" != xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Couldn't find libpng -- you will not be able to build pdftohtml or pdftopng" >&5 +$as_echo "$as_me: WARNING: Couldn't find libpng -- you will not be able to build pdftohtml or pdftopng" >&2;} +fi diff --git a/Build/source/libs/xpdf/xpdf-3.03/configure.in b/Build/source/libs/xpdf/xpdf-3.04/configure.in index 6592a46ead8..47e33fc3ac4 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/configure.in +++ b/Build/source/libs/xpdf/xpdf-3.04/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -dnl Copyright 1998-2005 Glyph & Cog, LLC +dnl Copyright 1998-2013 Glyph & Cog, LLC AC_PREREQ(2.57) @@ -7,34 +7,54 @@ AC_INIT(xpdf/Gfx.cc) AC_CONFIG_HEADER(aconf.h) dnl ##### Optional features. -AC_ARG_ENABLE(a4-paper, -[ --enable-a4-paper use A4 paper size instead of Letter for - PostScript output], -AC_DEFINE(A4_PAPER)) -AC_ARG_ENABLE(no-text-select, -[ --enable-no-text-select do not allow text selection], -AC_DEFINE(NO_TEXT_SELECT)) -AC_ARG_ENABLE(opi, -[ --enable-opi include support for OPI comments], -AC_DEFINE(OPI_SUPPORT)) -AC_ARG_ENABLE(multithreaded, -[ --enable-multithreaded include support for multithreading], -AC_DEFINE(MULTITHREADED)) -AC_ARG_ENABLE(exceptions, -[ --enable-exceptions use C++ exceptions], -AC_DEFINE(USE_EXCEPTIONS)) -AC_ARG_ENABLE(wordlist, -[ --enable-wordlist include support for building word lists], -AC_DEFINE(TEXTOUT_WORD_LIST)) -AC_ARG_ENABLE(fixedpoint, -[ --enable-fixedpoint use fixed point (instead of floating point) arithmetic], -AC_DEFINE(USE_FIXEDPOINT)) -AC_ARG_ENABLE(cmyk, -[ --enable-cmyk include support for CMYK rasterization], -AC_DEFINE(SPLASH_CMYK)) -AC_ARG_WITH(appdef-dir, -[ --with-appdef-dir set app-defaults directory], -AC_DEFINE_UNQUOTED(APPDEFDIR, "$with_appdef_dir")) + +AC_ARG_ENABLE([a4-paper], + AS_HELP_STRING([--enable-a4-paper], + [use A4 paper size instead of Letter for PostScript output])) +AS_IF([test "x$enable_a4_paper" = "xyes"], + [AC_DEFINE(A4_PAPER)]) + +AC_ARG_ENABLE([no-text-select], + AS_HELP_STRING([--enable-no-text-select], + [do not allow text selection])) +AS_IF([test "x$enable_no_text_select" = "xyes"], + [AC_DEFINE(NO_TEXT_SELECT)]) + +AC_ARG_ENABLE([opi], + AS_HELP_STRING([--enable-opi], + [include support for OPI comments])) +AS_IF([test "x$enable_opi" = "xyes"], + [AC_DEFINE(OPI_SUPPORT)]) + +AC_ARG_ENABLE([multithreaded], + AS_HELP_STRING([--enable-multithreaded], + [include support for multithreading])) +AS_IF([test "x$enable_multithreaded" = "xyes"], + [AC_DEFINE(MULTITHREADED)]) + +AC_ARG_ENABLE([exceptions], + AS_HELP_STRING([--enable-exceptions], + [use C++ exceptions])) +AS_IF([test "x$enable_exceptions" = "xyes"], + [AC_DEFINE(USE_EXCEPTIONS)]) + +AC_ARG_ENABLE([fixedpoint], + AS_HELP_STRING([--enable-fixedpoint], + [use fixed point (instead of floating point) arithmetic])) +AS_IF([test "x$enable_fixedpoint" = "xyes"], + [AC_DEFINE(USE_FIXEDPOINT)]) + +AC_ARG_ENABLE([cmyk], + AS_HELP_STRING([--enable-cmyk], + [include support for CMYK rasterization])) +AS_IF([test "x$enable_cmyk" = "xyes"], + [AC_DEFINE(SPLASH_CMYK)]) + +AC_ARG_WITH([appdef-dir], + AS_HELP_STRING([--with-appdef-dir], + [set app-defaults directory])) +AS_IF([test "x$with_appdef_dir" != "xno"], + [AC_DEFINE_UNQUOTED(APPDEFDIR, "$with_appdef_dir")]) dnl ##### Path to xpdfrc. dnl This ugly kludge to get the sysconfdir path is needed because @@ -241,12 +261,12 @@ dnl ##### Check for std::sort. AC_CACHE_CHECK([for std::sort], xpdf_cv_func_std_sort, [AC_COMPILE_IFELSE( - AC_LANG_PROGRAM([[#include <algorithm> + [AC_LANG_PROGRAM([[#include <algorithm> struct functor { bool operator()(const int &i0, const int &i1) { return i0 < i1; } };]], - [[int a[[100]]; -std::sort(a, a+100, functor());]]), + [[int a[100]; +std::sort(a, a+100, functor());]])], xpdf_cv_func_std_sort=yes, xpdf_cv_func_std_sort=no)]) if test "$xpdf_cv_func_std_sort" = yes; then AC_DEFINE(HAVE_STD_SORT) @@ -314,18 +334,6 @@ if test -z "$no_x"; then fi fi -#dnl ##### Check for t1lib. -#smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer], -# T1_InitLib, t1lib.h, -# -lm, $X_CFLAGS) -# t1lib has some potential security holes, and hasn't been updated in -# years -- if you really want to use it, uncomment the preceding lines, -# and comment out the next two lines -t1_LIBS="" -t1_CFLAGS="" -AC_SUBST(t1_LIBS) -AC_SUBST(t1_CFLAGS) - dnl ##### Check for FreeType 2.x. dnl ##### (Note: FT_Get_Name_Index was added in FT 2.0.5, and is dnl ##### the reason that Xpdf requires 2.0.5+.) @@ -338,6 +346,11 @@ if test "x$smr_have_freetype2_library" = xyes; then AC_DEFINE(HAVE_SPLASH) fi +dnl ##### Check for libpng. +smr_CHECK_LIB(libpng, png, [PNG library], png_write_row, png.h, -lz) +AC_SUBST(libpng_LIBS) +AC_SUBST(libpng_CFLAGS) + dnl ##### Check for libpaper (Debian). smr_CHECK_LIB(libpaper, paper, [Debian libpaper], paperinit, paper.h) AC_SUBST(libpaper_LIBS) @@ -354,6 +367,12 @@ fi AC_SUBST(X) AC_SUBST(XPDF_TARGET) +dnl ##### Extra libraries. +EXTRA_LIBS= +EXTRA_CFLAGS= +AC_SUBST(EXTRA_LIBS) +AC_SUBST(EXTRA_CFLAGS) + dnl ##### Write the makefiles. AC_OUTPUT(Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile) @@ -372,3 +391,8 @@ if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_l pdfinfo, pdffonts, pdfdetach, and pdfimages, but not xpdf or pdftoppm]) fi + +dnl ##### Warn user if libpng is missing. +if test "x$smr_have_libpng_library" != xyes; then + AC_MSG_WARN([Couldn't find libpng -- you will not be able to build pdftohtml or pdftopng]) +fi diff --git a/Build/source/libs/xpdf/xpdf-3.03/dj_make.bat b/Build/source/libs/xpdf/xpdf-3.04/dj_make.bat index 13c192d5b0c..a629e17eda2 100755 --- a/Build/source/libs/xpdf/xpdf-3.03/dj_make.bat +++ b/Build/source/libs/xpdf/xpdf-3.04/dj_make.bat @@ -1,5 +1,5 @@ set CC=gcc
-set CFLAGS=-g -O2 -I.. -I..\fofi -I..\goo
+set CFLAGS=-g -O2 -I.. -I..\splash -I..\fofi -I..\goo
set CXX=gpp
set CXXFLAGS=%CFLAGS%
set LIBPROG=ar
@@ -28,6 +28,7 @@ cd ..\fofi cd ..\xpdf
del *.o
+%CXX% %CXXFLAGS% -c AcroForm.cc
%CXX% %CXXFLAGS% -c Annot.cc
%CXX% %CXXFLAGS% -c Array.cc
%CXX% %CXXFLAGS% -c BuiltinFont.cc
@@ -39,6 +40,7 @@ del *.o %CXX% %CXXFLAGS% -c Dict.cc
%CXX% %CXXFLAGS% -c Error.cc
%CXX% %CXXFLAGS% -c FontEncodingTables.cc
+%CXX% %CXXFLAGS% -c Form.cc
%CXX% %CXXFLAGS% -c Function.cc
%CXX% %CXXFLAGS% -c Gfx.cc
%CXX% %CXXFLAGS% -c GfxFont.cc
@@ -61,12 +63,16 @@ del *.o %CXX% %CXXFLAGS% -c PSTokenizer.cc
%CXX% %CXXFLAGS% -c Page.cc
%CXX% %CXXFLAGS% -c Parser.cc
+%CXX% %CXXFLAGS% -c PreScanOutputDev.cc
%CXX% %CXXFLAGS% -c SecurityHandler.cc
%CXX% %CXXFLAGS% -c Stream.cc
%CXX% %CXXFLAGS% -c TextOutputDev.cc
+%CXX% %CXXFLAGS% -c TextString.cc
%CXX% %CXXFLAGS% -c UnicodeMap.cc
%CXX% %CXXFLAGS% -c UnicodeTypeTable.cc
+%CXX% %CXXFLAGS% -c XFAForm.cc
%CXX% %CXXFLAGS% -c XRef.cc
+%CXX% %CXXFLAGS% -c Zoox.cc
del libxpdf.a
%LIBPROG% -rc libxpdf.a *.o
diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.1 index 1e2f8aa5604..b0d9dd31186 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.1 @@ -1,8 +1,8 @@ -.\" Copyright 2011 Glyph & Cog, LLC -.TH pdfdetach 1 "15 August 2011" +.\" Copyright 2013-2014 Glyph & Cog, LLC +.TH pdfdetach 1 "28 May 2014" .SH NAME pdfdetach \- Portable Document Format (PDF) document embedded file -extractor (version 3.03) +extractor (version 3.04) .SH SYNOPSIS .B pdfdetach [options] @@ -90,15 +90,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdfinfo software and documentation are copyright 1996-2011 Glyph & +The pdfinfo software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.cat index 526bbba01ee..8b052e26c55 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.cat @@ -4,7 +4,7 @@ pdfdetach(1) pdfdetach(1) NAME pdfdetach - Portable Document Format (PDF) document embedded file - extractor (version 3.03) + extractor (version 3.04) SYNOPSIS pdfdetach [options] [PDF-file] @@ -79,14 +79,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdfinfo software and documentation are copyright 1996-2011 Glyph & + The pdfinfo software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), - pdftoppm(1), pdfimages(1), xpdfrc(5) + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + fonts(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 pdfdetach(1) + 28 May 2014 pdfdetach(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.hlp index f85cd0f500c..f85cd0f500c 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfdetach.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfdetach.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.1 index 6e132ac1d8c..70e1f45fd8a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.1 @@ -1,8 +1,8 @@ -.\" Copyright 1999-2011 Glyph & Cog, LLC -.TH pdffonts 1 "15 August 2011" +.\" Copyright 1999-2014 Glyph & Cog, LLC +.TH pdffonts 1 "28 May 2014" .SH NAME pdffonts \- Portable Document Format (PDF) font analyzer (version -3.03) +3.04) .SH SYNOPSIS .B pdffonts [options] @@ -34,6 +34,13 @@ can't be converted to Unicode) .TP .B object ID the font dictionary object ID (number and generation) +.TP +.B location +the font location (see the +.B \-loc +and +.B \-locPS +options). .PP PDF files can contain the following types of fonts: .PP @@ -86,6 +93,14 @@ the corresponding command line option. .BI \-f " number" Specifies the first page to analyze. .TP +.B \-loc +Shows additional information on the location of the font that will be +used when the PDF file is rasterized (with xpdf, pdftoppm, etc.). +.TP +.B \-locPS +Shows additional information on the location of the font that will be +used when the PDF file is converted to PostScript (with pdftops). +.TP .BI \-l " number" Specifies the last page to analyze. .TP @@ -128,15 +143,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdffonts software and documentation are copyright 1996-2011 Glyph +The pdffonts software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.cat index b2d92f32198..0c10b25253a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.cat @@ -3,7 +3,7 @@ pdffonts(1) pdffonts(1) NAME - pdffonts - Portable Document Format (PDF) font analyzer (version 3.03) + pdffonts - Portable Document Format (PDF) font analyzer (version 3.04) SYNOPSIS pdffonts [options] [PDF-file] @@ -30,6 +30,9 @@ DESCRIPTION object ID the font dictionary object ID (number and generation) + location + the font location (see the -loc and -locPS options). + PDF files can contain the following types of fonts: Type 1 @@ -59,6 +62,14 @@ OPTIONS -f number Specifies the first page to analyze. + -loc Shows additional information on the location of the font that + will be used when the PDF file is rasterized (with xpdf, + pdftoppm, etc.). + + -locPS Shows additional information on the location of the font that + will be used when the PDF file is converted to PostScript (with + pdftops). + -l number Specifies the last page to analyze. @@ -91,14 +102,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdffonts software and documentation are copyright 1996-2011 Glyph & + The pdffonts software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdfdetach(1), - pdftoppm(1), pdfimages(1), xpdfrc(5) + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdfde- + tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 pdffonts(1) + 28 May 2014 pdffonts(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.hlp index c5a6c13385f..c5a6c13385f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdffonts.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdffonts.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.1 index a68a5107942..0953ced5636 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.1 @@ -1,8 +1,8 @@ -.\" Copyright 1998-2011 Glyph & Cog, LLC -.TH pdfimages 1 "15 August 2011" +.\" Copyright 1998-2014 Glyph & Cog, LLC +.TH pdfimages 1 "28 May 2014" .SH NAME pdfimages \- Portable Document Format (PDF) image extractor -(version 3.03) +(version 3.04) .SH SYNOPSIS .B pdfimages [options] @@ -15,9 +15,9 @@ Pixmap (PPM), Portable Bitmap (PBM), or JPEG files. Pdfimages reads the PDF file, scans one or more pages, .IR PDF-file , and writes one PPM, PBM, or JPEG file for each image, -.IR image-root - nnn . xxx , +.IR image-root - nnnn . xxx , where -.I nnn +.I nnnn is the image number and .I xxx is the image type (.ppm, .pbm, .jpg). @@ -88,16 +88,18 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdfimages software and documentation are copyright 1998-2011 Glyph +The pdfimages software and documentation are copyright 1998-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR xpdfrc (5) .br .B http://www.foolabs.com/xpdf/ diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.cat index ee8810cfb11..a152e789b64 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.cat @@ -4,7 +4,7 @@ pdfimages(1) pdfimages(1) NAME pdfimages - Portable Document Format (PDF) image extractor (version - 3.03) + 3.04) SYNOPSIS pdfimages [options] PDF-file image-root @@ -14,8 +14,8 @@ DESCRIPTION Portable Pixmap (PPM), Portable Bitmap (PBM), or JPEG files. Pdfimages reads the PDF file, scans one or more pages, PDF-file, and - writes one PPM, PBM, or JPEG file for each image, image-root-nnn.xxx, - where nnn is the image number and xxx is the image type (.ppm, .pbm, + writes one PPM, PBM, or JPEG file for each image, image-root-nnnn.xxx, + where nnnn is the image number and xxx is the image type (.ppm, .pbm, .jpg). NB: pdfimages extracts the raw image data from the PDF file, without @@ -72,14 +72,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdfimages software and documentation are copyright 1998-2011 Glyph + The pdfimages software and documentation are copyright 1998-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde- - tach(1), pdftoppm(1), xpdfrc(5) + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + fonts(1), pdfdetach(1), pdftoppm(1), pdftopng(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 pdfimages(1) + 28 May 2014 pdfimages(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.hlp index 18fef5817bf..18fef5817bf 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfimages.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfimages.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.1 index b6b049898f8..5a02353744f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.1 @@ -1,8 +1,8 @@ -.\" Copyright 1999-2011 Glyph & Cog, LLC -.TH pdfinfo 1 "15 August 2011" +.\" Copyright 1999-2014 Glyph & Cog, LLC +.TH pdfinfo 1 "28 May 2014" .SH NAME pdfinfo \- Portable Document Format (PDF) document information -extractor (version 3.03) +extractor (version 3.04) .SH SYNOPSIS .B pdfinfo [options] @@ -57,7 +57,7 @@ encrypted flag (yes/no) print and copy permissions (if encrypted) .RE .RS -page size +page size and rotation .RE .RS file size @@ -150,15 +150,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdfinfo software and documentation are copyright 1996-2011 Glyph & +The pdfinfo software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdffonts (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.cat index 7f74ced340c..8ef2bb21317 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.cat @@ -4,7 +4,7 @@ pdfinfo(1) pdfinfo(1) NAME pdfinfo - Portable Document Format (PDF) document information extractor - (version 3.03) + (version 3.04) SYNOPSIS pdfinfo [options] [PDF-file] @@ -31,7 +31,7 @@ DESCRIPTION page count encrypted flag (yes/no) print and copy permissions (if encrypted) - page size + page size and rotation file size linearized (yes/no) PDF version @@ -104,14 +104,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdfinfo software and documentation are copyright 1996-2011 Glyph & + The pdfinfo software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdffonts(1), pdfdetach(1), - pdftoppm(1), pdfimages(1), xpdfrc(5) + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdffonts(1), pdfde- + tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 pdfinfo(1) + 28 May 2014 pdfinfo(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.hlp index f4082660fcc..f4082660fcc 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdfinfo.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdfinfo.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.1 new file mode 100644 index 00000000000..a74df55c75a --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.1 @@ -0,0 +1,106 @@ +.\" Copyright 1997-2014 Glyph & Cog, LLC +.TH pdftohtml 1 "28 May 2014" +.SH NAME +pdftohtml \- Portable Document Format (PDF) to HTML converter +(version 3.04) +.SH SYNOPSIS +.B pdftohtml +[options] +.I PDF-file +.I HTML-dir +.SH DESCRIPTION +.B Pdftohtml +converts Portable Document Format (PDF) files to HTML. +.PP +Pdftohtml reads the PDF file, +.IR PDF-file , +and places an HTML file for each page, along with auxiliary images +in the directory, +.IR HTML-dir . +The HTML directory will be created; if it already exists, pdftohtml +will report an error. +.SH CONFIGURATION FILE +Pdftohtml reads a configuration file at startup. It first tries to +find the user's private config file, ~/.xpdfrc. If that doesn't +exist, it looks for a system-wide config file, typically +/usr/local/etc/xpdfrc (but this location can be changed when pdftohtml +is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to convert. +.TP +.BI \-l " number" +Specifies the last page to convert. +.TP +.B \-r +Specifies the resolution, in DPI, for background images. The default +is 150 DPI. +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.BI \-cfg " config-file" +Read +.I config-file +in place of ~/.xpdfrc or the system-wide config file. +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH BUGS +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. +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdftohtml software and documentation are copyright 1996-2014 Glyph +& Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdfdetach (1), +.BR pdftoppm (1), +.BR pdftopng (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff --git a/Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.cat new file mode 100644 index 00000000000..ed46c1a4c43 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftohtml.cat @@ -0,0 +1,87 @@ +pdftohtml(1) pdftohtml(1) + + + +NAME + pdftohtml - Portable Document Format (PDF) to HTML converter (version + 3.04) + +SYNOPSIS + pdftohtml [options] PDF-file HTML-dir + +DESCRIPTION + Pdftohtml converts Portable Document Format (PDF) files to HTML. + + Pdftohtml reads the PDF file, PDF-file, and places an HTML file for + each page, along with auxiliary images in the directory, HTML-dir. The + HTML directory will be created; if it already exists, pdftohtml will + report an error. + +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. + +OPTIONS + Many of the following options can be set with configuration file com- + mands. These are listed in square brackets with the description of the + corresponding command line option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -r Specifies the resolution, in DPI, for background images. The + default is 150 DPI. + + -opw password + 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. + + -q Don't print any messages or errors. [config file: errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the system-wide config + file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are equivalent.) + +BUGS + 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. + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdftohtml software and documentation are copyright 1996-2014 Glyph + & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde- + tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 28 May 2014 pdftohtml(1) diff --git a/Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.1 new file mode 100644 index 00000000000..6d936537bf8 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.1 @@ -0,0 +1,119 @@ +.\" Copyright 2014 Glyph & Cog, LLC +.TH pdftopng 1 "28 May 2014" +.SH NAME +pdftopng \- Portable Document Format (PDF) to Portable Network Graphics +(PNG) converter (version 3.04) +.SH SYNOPSIS +.B pdftopng +[options] +.I PDF-file PNG-root +.SH DESCRIPTION +.B Pdftopng +converts Portable Document Format (PDF) files to color, grayscale, or +monochrome image files in Portable Network Graphics (PNG) format. +.PP +Pdftopng reads the PDF file, +.IR PDF-file , +and writes one PNG file for each page, +.IR PNG-root - nnnnnn .png, +where +.I nnnnnn +is the page number. +If +.I PNG-root +is \'-', the image is sent to stdout (this is probably only useful +when converting a single page). +.SH CONFIGURATION FILE +Pdftopng reads a configuration file at startup. It first tries to +find the user's private config file, ~/.xpdfrc. If that doesn't +exist, it looks for a system-wide config file, typically +/usr/local/etc/xpdfrc (but this location can be changed when pdftopng +is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to convert. +.TP +.BI \-l " number" +Specifies the last page to convert. +.TP +.BI \-r " number" +Specifies the resolution, in DPI. The default is 150 DPI. +.TP +.B \-mono +Generate a monochrome image (instead of a color image). +.TP +.B \-gray +Generate a grayscale image (instead of a color image). +.TP +.BI \-freetype " yes | no" +Enable or disable FreeType (a TrueType / Type 1 font rasterizer). +This defaults to "yes". +.RB "[config file: " enableFreeType ] +.TP +.BI \-aa " yes | no" +Enable or disable font anti-aliasing. This defaults to "yes". +.RB "[config file: " antialias ] +.TP +.BI \-aaVector " yes | no" +Enable or disable vector anti-aliasing. This defaults to "yes". +.RB "[config file: " vectorAntialias ] +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdftopng software and documentation are copyright 1996-2014 Glyph +& Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdftohtml (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdfdetach (1), +.BR pdftoppm (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff --git a/Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.cat new file mode 100644 index 00000000000..ca1c5ed27bb --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftopng.cat @@ -0,0 +1,96 @@ +pdftopng(1) pdftopng(1) + + + +NAME + pdftopng - Portable Document Format (PDF) to Portable Network Graphics + (PNG) converter (version 3.04) + +SYNOPSIS + pdftopng [options] PDF-file PNG-root + +DESCRIPTION + Pdftopng converts Portable Document Format (PDF) files to color, + grayscale, or monochrome image files in Portable Network Graphics (PNG) + format. + + Pdftopng reads the PDF file, PDF-file, and writes one PNG file for each + page, PNG-root-nnnnnn.png, where nnnnnn is the page number. If PNG- + root is '-', the image is sent to stdout (this is probably only useful + when converting a single page). + +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. + +OPTIONS + Many of the following options can be set with configuration file com- + mands. These are listed in square brackets with the description of the + corresponding command line option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -r number + Specifies the resolution, in DPI. The default is 150 DPI. + + -mono Generate a monochrome image (instead of a color image). + + -gray Generate a grayscale image (instead of a color image). + + -freetype yes | no + Enable or disable FreeType (a TrueType / Type 1 font raster- + izer). This defaults to "yes". [config file: enableFreeType] + + -aa yes | no + Enable or disable font anti-aliasing. This defaults to "yes". + [config file: antialias] + + -aaVector yes | no + Enable or disable vector anti-aliasing. This defaults to "yes". + [config file: vectorAntialias] + + -opw password + 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. + + -q Don't print any messages or errors. [config file: errQuiet] + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are equivalent.) + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdftopng software and documentation are copyright 1996-2014 Glyph & + Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + fonts(1), pdfdetach(1), pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 28 May 2014 pdftopng(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.1 index 59a2f18ef7a..4255937ab2a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.1 @@ -1,8 +1,8 @@ -.\" Copyright 2005-2011 Glyph & Cog, LLC -.TH pdftoppm 1 "15 August 2011" +.\" Copyright 2005-2014 Glyph & Cog, LLC +.TH pdftoppm 1 "28 May 2014" .SH NAME pdftoppm \- Portable Document Format (PDF) to Portable Pixmap (PPM) -converter (version 3.03) +converter (version 3.04) .SH SYNOPSIS .B pdftoppm [options] @@ -53,11 +53,6 @@ Generate a monochrome PBM file (instead of a color PPM file). .B \-gray Generate a grayscale PGM file (instead of a color PPM file). .TP -.BI \-t1lib " yes | no" -Enable or disable t1lib (a Type 1 font rasterizer). This defaults to -"yes". -.RB "[config file: " enableT1lib ] -.TP .BI \-freetype " yes | no" Enable or disable FreeType (a TrueType / Type 1 font rasterizer). This defaults to "yes". @@ -109,15 +104,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftoppm software and documentation are copyright 1996-2011 Glyph +The pdftoppm software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdfdetach (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.cat index dd0cc7804ff..bfa37c738b1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.cat @@ -4,7 +4,7 @@ pdftoppm(1) pdftoppm(1) NAME pdftoppm - Portable Document Format (PDF) to Portable Pixmap (PPM) con- - verter (version 3.03) + verter (version 3.04) SYNOPSIS pdftoppm [options] PDF-file PPM-root @@ -45,16 +45,12 @@ OPTIONS -gray Generate a grayscale PGM file (instead of a color PPM file). - -t1lib yes | no - Enable or disable t1lib (a Type 1 font rasterizer). This - defaults to "yes". [config file: enableT1lib] - -freetype yes | no - Enable or disable FreeType (a TrueType / Type 1 font raster- + Enable or disable FreeType (a TrueType / Type 1 font raster- izer). This defaults to "yes". [config file: enableFreeType] -aa yes | no - Enable or disable font anti-aliasing. This defaults to "yes". + Enable or disable font anti-aliasing. This defaults to "yes". [config file: antialias] -aaVector yes | no @@ -62,7 +58,7 @@ OPTIONS [config file: vectorAntialias] -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 @@ -88,14 +84,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdftoppm software and documentation are copyright 1996-2011 Glyph & + The pdftoppm software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde- - tach(1), pdfimages(1), xpdfrc(5) + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + fonts(1), pdfdetach(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 pdftoppm(1) + 28 May 2014 pdftoppm(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.hlp index 6c370ed4ff6..6c370ed4ff6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftoppm.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftoppm.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.1 index 9c688274eb5..d9daf492390 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.1 @@ -1,8 +1,8 @@ -.\" Copyright 1996-2011 Glyph & Cog, LLC -.TH pdftops 1 "15 August 2011" +.\" Copyright 1996-2014 Glyph & Cog, LLC +.TH pdftops 1 "28 May 2014" .SH NAME pdftops \- Portable Document Format (PDF) to PostScript converter -(version 3.03) +(version 3.04) .SH SYNOPSIS .B pdftops [options] @@ -172,6 +172,7 @@ lower-left corner of the paper instead. .B \-pagecrop Treat the CropBox as the PDF page size. By default, the MediaBox is used as the page size. +.RB "[config file: " psUseCropBoxAsPage ] .TP .B \-duplex Set the Duplex pagedevice entry in the PostScript file. This tells @@ -221,15 +222,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftops software and documentation are copyright 1996-2011 Glyph & +The pdftops software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.cat index 8104b37563f..9e119ac30d9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.cat @@ -4,7 +4,7 @@ pdftops(1) pdftops(1) NAME pdftops - Portable Document Format (PDF) to PostScript converter (ver- - sion 3.03) + sion 3.04) SYNOPSIS pdftops [options] [PDF-file [PS-file]] @@ -73,54 +73,54 @@ OPTIONS page PDF file, you must use -f and -l to specify a single page. No more than one of the mode options (-eps, -form) may be given. - -form Generate a PostScript form which can be imported by software - that understands forms. A form contains a single page, so if - you use this option with a multi-page PDF file, you must use -f - and -l to specify a single page. The -level1 option cannot be + -form Generate a PostScript form which can be imported by software + that understands forms. A form contains a single page, so if + you use this option with a multi-page PDF file, you must use -f + and -l to specify a single page. The -level1 option cannot be used with -form. - -opi Generate OPI comments for all images and forms which have OPI + -opi Generate OPI comments for all images and forms which have OPI information. (This option is only available if pdftops was com- piled with OPI support.) [config file: psOPI] -noembt1 - By default, any Type 1 fonts which are embedded in the PDF file + By default, any Type 1 fonts which are embedded in the PDF file are copied into the PostScript file. This option causes pdftops - to substitute base fonts instead. Embedded fonts make Post- - Script files larger, but may be necessary for readable output. + to substitute base fonts instead. Embedded fonts make Post- + Script files larger, but may be necessary for readable output. [config file: psEmbedType1Fonts] -noembtt - By default, any TrueType fonts which are embedded in the PDF - file are copied into the PostScript file. This option causes - pdftops to substitute base fonts instead. Embedded fonts make - PostScript files larger, but may be necessary for readable out- - put. Also, some PostScript interpreters do not have TrueType + By default, any TrueType fonts which are embedded in the PDF + file are copied into the PostScript file. This option causes + pdftops to substitute base fonts instead. Embedded fonts make + PostScript files larger, but may be necessary for readable out- + put. Also, some PostScript interpreters do not have TrueType rasterizers. [config file: psEmbedTrueTypeFonts] -noembcidps - By default, any CID PostScript fonts which are embedded in the - PDF file are copied into the PostScript file. This option dis- + By default, any CID PostScript fonts which are embedded in the + PDF file are copied into the PostScript file. This option dis- ables that embedding. No attempt is made to substitute for non- - embedded CID PostScript fonts. [config file: psEmbedCID- + embedded CID PostScript fonts. [config file: psEmbedCID- PostScriptFonts] -noembcidtt By default, any CID TrueType fonts which are embedded in the PDF - file are copied into the PostScript file. This option disables + file are copied into the PostScript file. This option disables that embedding. No attempt is made to substitute for non-embed- ded CID TrueType fonts. [config file: psEmbedCIDTrueTypeFonts] -preload - Convert PDF forms to PS procedures, and preload image data. - This uses more memory in the PostScript interpreter, but gener- - ates significantly smaller PS files in situations where, e.g., + Convert PDF forms to PS procedures, and preload image data. + This uses more memory in the PostScript interpreter, but gener- + ates significantly smaller PS files in situations where, e.g., the same image is drawn on every page of a long document. -paper size - Set the paper size to one of "letter", "legal", "A4", or "A3". - This can also be set to "match", which will set the paper size - to match the size specified in the PDF file. [config file: + Set the paper size to one of "letter", "legal", "A4", or "A3". + This can also be set to "match", which will set the paper size + to match the size specified in the PDF file. [config file: psPaperSize] -paperw size @@ -130,7 +130,7 @@ OPTIONS Set the paper height, in points. [config file: psPaperSize] -nocrop - By default, output is cropped to the CropBox specified in the + By default, output is cropped to the CropBox specified in the PDF file. This option disables cropping. [config file: psCrop] -expand @@ -151,7 +151,7 @@ OPTIONS -pagecrop Treat the CropBox as the PDF page size. By default, the Media- - Box is used as the page size. + Box is used as the page size. [config file: psUseCropBoxAsPage] -duplex Set the Duplex pagedevice entry in the PostScript file. This @@ -189,14 +189,14 @@ EXIT CODES 99 Other error. AUTHOR - The pdftops software and documentation are copyright 1996-2011 Glyph & + The pdftops software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfdetach(1), - pdftoppm(1), pdfimages(1), xpdfrc(5) + xpdf(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde- + tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 pdftops(1) + 28 May 2014 pdftops(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.hlp index b93febda260..b93febda260 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftops.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftops.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.1 index 83bf7c6a8d4..12d75006702 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.1 @@ -1,8 +1,8 @@ -.\" Copyright 1997-2011 Glyph & Cog, LLC -.TH pdftotext 1 "15 August 2011" +.\" Copyright 1997-2014 Glyph & Cog, LLC +.TH pdftotext 1 "28 May 2014" .SH NAME pdftotext \- Portable Document Format (PDF) to text converter -(version 3.03) +(version 3.04) .SH SYNOPSIS .B pdftotext [options] @@ -47,21 +47,50 @@ Specifies the last page to convert. .B \-layout Maintain (as best as possible) the original physical layout of the text. The default is to \'undo' physical layout (columns, -hyphenation, etc.) and output the text in reading order. +hyphenation, etc.) and output the text in reading order. If the +.B \-fixed +option is given, character spacing within each line will be determined +by the specified character pitch. +.TP +.B \-table +Table mode is similar to physical layout mode, but optimized for +tabular data, with the goal of keeping rows and columns aligned (at +the expense of inserting extra whitespace). If the +.B \-fixed +option is given, character spacing within each line will be determined +by the specified character pitch. +.TP +.B \-lineprinter +Line printer mode uses a strict fixed-character-pitch and -height +layout. That is, the page is broken into a grid, and characters are +placed into that grid. If the grid spacing is too small for the +actual characters, the result is extra whitespace. If the grid +spacing is too large, the result is missing whitespace. The grid +spacing can be specified using the +.B \-fixed +and +.B \-linespacing +options. +If one or both are not given on the command line, pdftotext will +attempt to compute appropriate value(s). +.TP +.B \-raw +Keep the text in content stream order. Depending on how the PDF file +was generated, this may or may not be useful. .TP .BI \-fixed " number" -Assume fixed-pitch (or tabular) text, with the specified character -width (in points). This forces physical layout mode. +Specify the character pitch (character width), in points, for physical +layout, table, or line printer mode. This is ignored in all other +modes. .TP -.B \-raw -Keep the text in content stream order. This is a hack which often -"undoes" column formatting, etc. Use of raw mode is no longer -recommended. +.BI \-linespacing " number" +Specify the line spacing, in points, for line printer mode. This is +ignored in all other modes. .TP -.B \-htmlmeta -Generate a simple HTML file, including the meta information. This -simply wraps the text in <pre> and </pre> and prepends the meta -headers. +.B \-clip +Text which is hidden because of clipping is removed before doing +layout, and then added back in. This can be helpful for tables where +clipped (invisible) text would overlap the next column. .TP .BI \-enc " encoding-name" Sets the encoding to use for text output. The @@ -127,15 +156,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The pdftotext software and documentation are copyright 1996-2011 Glyph +The pdftotext software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.cat new file mode 100644 index 00000000000..8217743e28d --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.cat @@ -0,0 +1,137 @@ +pdftotext(1) pdftotext(1) + + + +NAME + pdftotext - Portable Document Format (PDF) to text converter (version + 3.04) + +SYNOPSIS + pdftotext [options] [PDF-file [text-file]] + +DESCRIPTION + Pdftotext converts Portable Document Format (PDF) files to plain text. + + Pdftotext reads the PDF file, PDF-file, and writes a text file, text- + file. If text-file is not specified, pdftotext converts file.pdf to + file.txt. If text-file is '-', the text is sent to stdout. + +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. + +OPTIONS + Many of the following options can be set with configuration file com- + mands. These are listed in square brackets with the description of the + corresponding command line option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -layout + Maintain (as best as possible) the original physical layout of + the text. The default is to 'undo' physical layout (columns, + hyphenation, etc.) and output the text in reading order. If the + -fixed option is given, character spacing within each line will + be determined by the specified character pitch. + + -table Table mode is similar to physical layout mode, but optimized for + tabular data, with the goal of keeping rows and columns aligned + (at the expense of inserting extra whitespace). If the -fixed + option is given, character spacing within each line will be + determined by the specified character pitch. + + -lineprinter + Line printer mode uses a strict fixed-character-pitch and + -height layout. That is, the page is broken into a grid, and + characters are placed into that grid. If the grid spacing is + too small for the actual characters, the result is extra white- + space. If the grid spacing is too large, the result is missing + whitespace. The grid spacing can be specified using the -fixed + and -linespacing options. If one or both are not given on the + command line, pdftotext will attempt to compute appropriate + value(s). + + -raw Keep the text in content stream order. Depending on how the PDF + file was generated, this may or may not be useful. + + -fixed number + Specify the character pitch (character width), in points, for + physical layout, table, or line printer mode. This is ignored + in all other modes. + + -linespacing number + Specify the line spacing, in points, for line printer mode. + This is ignored in all other modes. + + -clip Text which is hidden because of clipping is removed before doing + layout, and then added back in. This can be helpful for tables + where clipped (invisible) text would overlap the next column. + + -enc encoding-name + Sets the encoding to use for text output. The encoding-name + must be defined with the unicodeMap command (see xpdfrc(5)). + The encoding name is case-sensitive. This defaults to "Latin1" + (which is a built-in encoding). [config file: textEncoding] + + -eol unix | dos | mac + Sets the end-of-line convention to use for text output. [config + file: textEOL] + + -nopgbrk + Don't insert page breaks (form feed characters) between pages. + [config file: textPageBreaks] + + -opw password + 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. + + -q Don't print any messages or errors. [config file: errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the system-wide config + file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are equivalent.) + +BUGS + 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. + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdftotext software and documentation are copyright 1996-2014 Glyph + & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde- + tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 28 May 2014 pdftotext(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.hlp index 651af916398..651af916398 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/pdftotext.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/pdftotext.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/sample-xpdfrc b/Build/source/libs/xpdf/xpdf-3.04/doc/sample-xpdfrc index 0df70a77f45..0a4234fdf9b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/sample-xpdfrc +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/sample-xpdfrc @@ -79,9 +79,8 @@ #----- misc settings -# Enable t1lib, FreeType, and anti-aliased text. +# Enable FreeType, and anti-aliased text. -#enableT1lib yes #enableFreeType yes #antialias yes diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.1 b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.1 index 05c0af93c02..c34ad7fb787 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.1 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.1 @@ -1,7 +1,7 @@ -.\" Copyright 1996-2011 Glyph & Cog, LLC -.TH xpdf 1 "15 August 2011" +.\" Copyright 1996-2014 Glyph & Cog, LLC +.TH xpdf 1 "28 May 2014" .SH NAME -xpdf \- Portable Document Format (PDF) file viewer for X (version 3.03) +xpdf \- Portable Document Format (PDF) file viewer for X (version 3.04) .SH SYNOPSIS .B xpdf [options] @@ -102,11 +102,6 @@ Start in continuous view mode, i.e., with one vertical scroll bar for the whole document. .RB "[config file: " continuousView ] .TP -.BI \-t1lib " yes | no" -Enable or disable t1lib (a Type 1 font rasterizer). This defaults to -"yes". -.RB "[config file: " enableT1lib ] -.TP .BI \-freetype " yes | no" Enable or disable FreeType (a TrueType / Type 1 font rasterizer). This defaults to "yes". @@ -638,7 +633,11 @@ Redraw the window. Raise the window to the front. .TP .B closeWindow -Close the window. +Close the window. If this was the last open window, clear the window, +but don't quit from Xpdf. +.TP +.B closeWindowOrQuit +Close the window. If this was the last open window, quit from Xpdf. .TP .BI run( external-command-string ) Run an external command. The following escapes are allowed in the @@ -668,6 +667,13 @@ command string: %% => % .fi +The external command string will often contain spaces, so the whole +command must be quoted in the xpdfrc file: +.nf + + bind x "run(ls -l)" + +.fi .TP .B openOutline Open the outline pane. @@ -799,7 +805,7 @@ The default key bindings are as follows: bind w any zoomFitWidth bind alt-f any toggleFullScreenMode bind ctrl-l any redraw - bind ctrl-w any closeWindow + bind ctrl-w any closeWindowOrQuit bind ? any about bind q any quit bind Q any quit @@ -863,15 +869,17 @@ Error related to PDF permissions. 99 Other error. .SH AUTHOR -The xpdf software and documentation are copyright 1996-2011 Glyph & +The xpdf software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1), .BR xpdfrc (5) .br diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.cat index eab46abab06..965b3106ed1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.cat @@ -3,7 +3,7 @@ xpdf(1) xpdf(1) NAME - xpdf - Portable Document Format (PDF) file viewer for X (version 3.03) + xpdf - Portable Document Format (PDF) file viewer for X (version 3.04) SYNOPSIS xpdf [options] [PDF-file [page | +dest]] @@ -60,15 +60,15 @@ OPTIONS serve color table entries. This is ignored with private col- ormaps and on TrueColor visuals. [X resource: xpdf.rgbCubeSize] - -rv Set reverse video mode. This reverses the colors of everything - except images. It may not always produce great results for PDF - files which do weird things with color. This also causes the - paper color to default to black. [X resource: xpdf.reverseV- + -rv Set reverse video mode. This reverses the colors of everything + except images. It may not always produce great results for PDF + files which do weird things with color. This also causes the + paper color to default to black. [X resource: xpdf.reverseV- ideo] -papercolor color Set the "paper color", i.e., the background of the page display. - This will not work too well with PDF files that do things like + This will not work too well with PDF files that do things like filling in white behind the text. [X resource: xpdf.paperColor] -mattecolor color @@ -87,16 +87,12 @@ OPTIONS -cont Start in continuous view mode, i.e., with one vertical scroll bar for the whole document. [config file: continuousView] - -t1lib yes | no - Enable or disable t1lib (a Type 1 font rasterizer). This - defaults to "yes". [config file: enableT1lib] - -freetype yes | no - Enable or disable FreeType (a TrueType / Type 1 font raster- + Enable or disable FreeType (a TrueType / Type 1 font raster- izer). This defaults to "yes". [config file: enableFreeType] -aa yes | no - Enable or disable font anti-aliasing. This defaults to "yes". + Enable or disable font anti-aliasing. This defaults to "yes". [config file: antialias] -aaVector yes | no @@ -104,15 +100,15 @@ OPTIONS [config file: vectorAntialias] -ps PS-file - Set the default file name for PostScript output (i.e., the name + Set the default file name for PostScript output (i.e., the name which will appear in the print dialog). This can also be of the form '|command' to pipe the PostScript through a command. [con- fig file: psFile] -paper size - Set the paper size to one of "letter", "legal", "A4", or "A3". - This can also be set to "match", which will set the paper size - to match the size specified in the PDF file. [config file: + Set the paper size to one of "letter", "legal", "A4", or "A3". + This can also be set to "match", which will set the paper size + to match the size specified in the PDF file. [config file: psPaperSize] -paperw size @@ -122,14 +118,14 @@ OPTIONS Set the paper height, in points. [config file: psPaperSize] -level1 - Generate Level 1 PostScript. The resulting PostScript files - will be significantly larger (if they contain images), but will - print on Level 1 printers. This also converts all images to + Generate Level 1 PostScript. The resulting PostScript files + will be significantly larger (if they contain images), but will + print on Level 1 printers. This also converts all images to black and white. [config file: psLevel] -enc encoding-name - Sets the encoding to use for text output. The encoding-name - must be defined with the unicodeMap command (see xpdfrc(5)). + Sets the encoding to use for text output. The encoding-name + must be defined with the unicodeMap command (see xpdfrc(5)). This defaults to "Latin1" (which is a built-in encoding). [con- fig file: textEncoding] @@ -138,7 +134,7 @@ OPTIONS file: textEOL] -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 @@ -148,11 +144,11 @@ OPTIONS Open xpdf in full-screen mode, useful for presentations. -remote name - Start/contact xpdf remote server with specified name (see the + Start/contact xpdf remote server with specified name (see the REMOTE SERVER MODE section below). -exec command - Execute a command (see the COMMANDS section below) in an xpdf + Execute a command (see the COMMANDS section below) in an xpdf remote server window (with -remote only). -reload @@ -162,7 +158,7 @@ OPTIONS -quit Kill xpdf remote server (with -remote only). - -cmd Print commands as they're executed (useful for debugging). + -cmd Print commands as they're executed (useful for debugging). [config file: printCommands] -q Don't print any messages or errors. [config file: errQuiet] @@ -199,7 +195,7 @@ OPTIONS tips on the toolbar buttons. xpdf.fullScreenMatteColor - Sets the matte color to be used in full-screen mode. The + Sets the matte color to be used in full-screen mode. The default setting is "black". CONTROLS @@ -214,19 +210,19 @@ CONTROLS Move backward or forward along the history path. 'Page' entry box - Move to a specific page number. Click in the box to activate + Move to a specific page number. Click in the box to activate it, type the page number, then hit return. zoom popup menu - Change the zoom factor (see the description of the -z option + Change the zoom factor (see the description of the -z option above). binoculars button Find a text string. print button - Bring up a dialog for generating a PostScript file. The dialog - has options to set the pages to be printed and the PostScript + Bring up a dialog for generating a PostScript file. The dialog + has options to set the pages to be printed and the PostScript file name. The file name can be '-' for stdout or '|command' to pipe the PostScript through a command, e.g., '|lpr'. @@ -240,7 +236,6 @@ CONTROLS 'Quit' button Quit xpdf. - Menu Pressing the right mouse button will post a popup menu with the follow- ing commands: @@ -249,11 +244,11 @@ CONTROLS Open a new PDF file via a file requester. Open in new window... - Create a new window and open a new PDF file via a file + Create a new window and open a new PDF file via a file requester. - Reload Reload the current PDF file. Note that Xpdf will reload the - file automatically (on a page change or redraw) if it has + Reload Reload the current PDF file. Note that Xpdf will reload the + file automatically (on a page change or redraw) if it has changed since it was last loaded. Save as... @@ -266,50 +261,45 @@ CONTROLS Rotate the page 90 degrees counterclockwise. Rotate clockwise - Rotate the page 90 degrees clockwise. The two rotate commands - are intended primarily for PDF files where the rotation isn't + Rotate the page 90 degrees clockwise. The two rotate commands + are intended primarily for PDF files where the rotation isn't correctly specified in the file. Zoom to selection Zoom in to the currently selected rectangle. - Close Close the current window. If this is the only open window, the + Close Close the current window. If this is the only open window, the document is closed, but the window is left open (i.e., this menu command won't quit xpdf). Quit Quit xpdf. - Outline - If the PDF contains an outline (a.k.a., bookmarks), there will be an - outline pane on the left side of the window. The width of the outline + If the PDF contains an outline (a.k.a., bookmarks), there will be an + outline pane on the left side of the window. The width of the outline pane is adjustable with a vertical split bar via the knob near its bot- tom end. - Text selection - Dragging the mouse with the left button held down will highlight an - arbitrary rectangle. Any text inside this rectangle will be copied to + Dragging the mouse with the left button held down will highlight an + arbitrary rectangle. Any text inside this rectangle will be copied to the X selection buffer. - Links Clicking on a hyperlink will jump to the link's destination. A link to - another PDF document will make xpdf load that document. A 'launch' - link to an executable program will display a dialog, and if you click + another PDF document will make xpdf load that document. A 'launch' + link to an executable program will display a dialog, and if you click 'ok', execute the program. URL links call an external command (see the WEB BROWSERS section below). - Panning Dragging the mouse with the middle button held down pans the window. - Key bindings o Open a new PDF file via a file requester. - r Reload the current PDF file. Note that Xpdf will reload the - file automatically (on a page change or redraw) if it has + r Reload the current PDF file. Note that Xpdf will reload the + file automatically (on a page change or redraw) if it has changed since it was last loaded. control-L @@ -327,14 +317,14 @@ CONTROLS control-P Print. - n Move to the next page. Scrolls to the top of the page, unless + n Move to the next page. Scrolls to the top of the page, unless scroll lock is turned on. - p Move to the previous page. Scrolls to the top of the page, + p Move to the previous page. Scrolls to the top of the page, unless scroll lock is turned on. <Space> or <PageDown> or <Next> - Scroll down on the current page; if already at bottom, move to + Scroll down on the current page; if already at bottom, move to next page. <Backspace> or <Delete> or <PageUp> or <Previous> @@ -374,9 +364,9 @@ CONTROLS q Quit xpdf. WEB BROWSERS - If you want to run xpdf automatically from netscape or mosaic (and - probably other browsers) when you click on a link to a PDF file, you - need to edit (or create) the files .mime.types and .mailcap in your + If you want to run xpdf automatically from netscape or mosaic (and + probably other browsers) when you click on a link to a PDF file, you + need to edit (or create) the files .mime.types and .mailcap in your home directory. In .mime.types add the line: application/pdf pdf @@ -388,17 +378,17 @@ WEB BROWSERS Make sure that xpdf is on your executable search path. - When you click on a URL link in a PDF file, xpdf will execute the com- - mand specified by the urlCommand config file option, replacing an - occurrence of '%s' with the URL. For example, to call netscape with + When you click on a URL link in a PDF file, xpdf will execute the com- + mand specified by the urlCommand config file option, replacing an + occurrence of '%s' with the URL. For example, to call netscape with the URL, add this line to your config file: urlCommand "netscape -remote 'openURL(%s)'" COMMANDS Xpdf's key and mouse bindings are user-configurable, using the bind and - unbind options in the config file (see xpdfrc(5)). The bind command - allows you to bind a key or mouse button to a sequence of one or more + unbind options in the config file (see xpdfrc(5)). The bind command + allows you to bind a key or mouse button to a sequence of one or more commands. Available Commands @@ -418,14 +408,14 @@ COMMANDS Go to the last page in the PDF file. gotoLastPageNoScroll - Go to the last page in the PDF file, with the current relative + Go to the last page in the PDF file, with the current relative scroll position. nextPage Go to the next page. nextPageNoScroll - Go to the next page, with the current relative scroll position. + Go to the next page, with the current relative scroll position. prevPage Go to the previous page. @@ -459,19 +449,19 @@ COMMANDS Scroll down by n pixels, moving to the next page if appropriate. scrollToTopEdge - Scroll to the top edge of the current page, with no horizontal + Scroll to the top edge of the current page, with no horizontal movement. scrollToBottomEdge - Scroll to the bottom edge of the current page, with no horizon- + Scroll to the bottom edge of the current page, with no horizon- tal movement. scrollToLeftEdge - Scroll to the left edge of the current page, with no vertical + Scroll to the left edge of the current page, with no vertical movement. scrollToRightEdge - Scroll to the right edge of the current page, with no vertical + Scroll to the right edge of the current page, with no vertical movement. scrollToTopLeft @@ -507,7 +497,7 @@ COMMANDS Rotate the page 90 degrees counterclockwise. setSelection(pg,ulx,uly,lrx,lry) - Set the selection to the specified coordinates on the specified + Set the selection to the specified coordinates on the specified page. continuousMode @@ -540,7 +530,7 @@ COMMANDS Open a specified PDF file in a new window. openFileAtDest(file,dest) - Open a specified PDF file in this window and go to a named des- + Open a specified PDF file in this window and go to a named des- tination. openFileAtDestInNewWin(file,dest) @@ -554,10 +544,15 @@ COMMANDS raise Raise the window to the front. closeWindow - Close the window. + Close the window. If this was the last open window, clear the + window, but don't quit from Xpdf. + + closeWindowOrQuit + Close the window. If this was the last open window, quit from + Xpdf. run(external-command-string) - Run an external command. The following escapes are allowed in + Run an external command. The following escapes are allowed in the command string: %f => PDF file name (or an empty string if no @@ -582,6 +577,11 @@ COMMANDS %k => y coordinate of the mouse pointer %% => % + The external command string will often contain spaces, so the + whole command must be quoted in the xpdfrc file: + + bind x "run(ls -l)" + openOutline Open the outline pane. @@ -703,7 +703,7 @@ COMMANDS bind w any zoomFitWidth bind alt-f any toggleFullScreenMode bind ctrl-l any redraw - bind ctrl-w any closeWindow + bind ctrl-w any closeWindowOrQuit bind ? any about bind q any quit bind Q any quit @@ -755,14 +755,14 @@ EXIT CODES 99 Other error. AUTHOR - The xpdf software and documentation are copyright 1996-2011 Glyph & + The xpdf software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfdetach(1), - pdftoppm(1), pdfimages(1), xpdfrc(5) + pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdffonts(1), pdfde- + tach(1), pdftoppm(1), pdftopng(1), pdfimages(1), xpdfrc(5) http://www.foolabs.com/xpdf/ - 15 August 2011 xpdf(1) + 28 May 2014 xpdf(1) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.hlp index 9696ec73553..9696ec73553 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdf.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdf.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.5 b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.5 index 676ad494fe2..afb8d950795 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.5 +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.5 @@ -1,7 +1,7 @@ -.\" Copyright 2002-2011 Glyph & Cog, LLC -.TH xpdfrc 5 "15 August 2011" +.\" Copyright 2002-2014 Glyph & Cog, LLC +.TH xpdfrc 5 "28 May 2014" .SH NAME -xpdfrc \- configuration file for Xpdf tools (version 3.03) +xpdfrc \- configuration file for Xpdf tools (version 3.04) .SH DESCRIPTION All of the Xpdf tools read a single configuration file. If you have a .I .xpdfrc @@ -17,6 +17,9 @@ The xpdfrc file consists of a series of configuration options, one per line. Blank lines and lines starting with a \'#' (comments) are ignored. .PP +Arguments may be quoted, using "double-quote" characters, e.g., for +file names that contain spaces. +.PP The following sections list all of the configuration options, sorted into functional groups. There is an examples section at the end. .SH INCLUDE FILES @@ -259,6 +262,10 @@ If set to "yes", PostScript output is cropped to the CropBox specified in the PDF file; otherwise no cropping is done. This defaults to "yes". .TP +.BR psUseCropBoxAsPage " yes | no" +If set to "yes", PostScript output treats the CropBox as the page size. +By default, this is "no", and the MediaBox is used as the page size. +.TP .BR psExpandSmaller " yes | no" If set to "yes", PDF pages smaller than the PostScript imageable area are expanded to fill the imageable area. Otherwise, no scalling is @@ -299,12 +306,23 @@ the Xpdf tools were compiled with OPI support. This defaults to "no". If set to "yes", the ASCIIHexEncode filter will be used instead of ASCII85Encode for binary data. This defaults to "no". .TP +.BR psLZW " yes | no" +If set to "yes", the LZWEncode filter will be used for lossless +compression in PostScript output; if set to "no", the RunLengthEncode +filter will be used instead. LZW generates better compression +(smaller PS files), but may not be supported by some printers. This +defaults to "yes". +.TP .BR psUncompressPreloadedImages " yes | no" If set to "yes", all preloaded images in PS files will uncompressed. If set to "no", the original compressed images will be used when possible. The "yes" setting is useful to work around certain buggy PostScript interpreters. This defaults to "no". .TP +.BR psMinLineWidth " float" +Set the minimum line width, in points, for PostScript output. The +default value is 0 (no minimum). +.TP .BR psRasterResolution " float" Set the resolution (in dpi) for rasterized pages in PostScript output. (Pdftops will rasterize pages which use transparency.) This defaults @@ -314,6 +332,11 @@ to 300. If set to "yes", rasterized pages in PS files will be monochrome (8-bit gray) instead of color. This defaults to "no". .TP +.BR psRasterSliceSize " pixels" +When rasterizing pages, pdftops splits the page into horizontal +"slices", to limit memory usage. This option sets the maximum slice +size, in pixels. This defaults to 20000000 (20 million). +.TP .BR psAlwaysRasterize " yes | no" If set to "yes", all PostScript output will be rasterized. This defaults to "no". @@ -359,7 +382,7 @@ If set to "yes", text extraction will keep all characters. If set to "no", text extraction will discard tiny (smaller than 3 point) characters after the first 50000 per page, avoiding extremely slow run times for PDF files that use special fonts to do shading or -cross-hatching. This defaults to "no". +cross-hatching. This defaults to "yes". .SH MISCELLANEOUS SETTINGS .TP .BR initialZoom " \fIpercentage\fR | page | width" @@ -373,12 +396,6 @@ If set to "yes", xpdf will start in continuous view mode, i.e., with one vertical screoll bar for the whole document. This defaults to "no". .TP -.BR enableT1lib " yes | no" -Enables or disables use of t1lib (a Type 1 font rasterizer). This is -only relevant if the Xpdf tools were built with t1lib support. -("enableT1lib" replaces the old "t1libControl" option.) This option -defaults to "yes". -.TP .BR enableFreeType " yes | no" Enables or disables use of FreeType (a TrueType / Type 1 font rasterizer). This is only relevant if the Xpdf tools were built with @@ -499,6 +516,21 @@ setting mapNumericCharNames to "no" is unnecessary.) In some cases, this leads to usable text, and in other cases it leads to gibberish -- there is no way for Xpdf to tell. This defaults to "no". .TP +.BI mapExtTrueTypeFontsViaUnicode " yes | no" +When rasterizing text using an external TrueType font, there are two +options for handling character codes. If +mapExtTrueTypeFontsViaUnicode is set to "yes", Xpdf will use the font +encoding/ToUnicode info to map character codes to Unicode, and then +use the font's Unicode cmap to map Unicode to GIDs. If +mapExtTrueTypeFontsViaUnicode is set to "no", Xpdf will assume the +character codes are GIDs (i.e., use an identity mapping). This +defaults to "yes". +.TP +.BI enableXFA " yes | no" +If set to "yes", an XFA form (if present) will be rendered in place of +an AcroForm. If "no", an XFA form will never be rendered. This +defaults to "yes". +.TP .BI bind " modifiers-key context command ..." Add a key or mouse button binding. .I Modifiers @@ -633,7 +665,6 @@ textEncoding UTF-8 textEOL unix # misc options -enableT1lib yes enableFreeType yes launchCommand viewer-script urlCommand "netscape \-remote 'openURL(%s)'" @@ -649,16 +680,18 @@ Depending on build options, it may be placed elsewhere. This is the user's configuration file. If it exists, it will be read in place of the system-wide file. .SH AUTHOR -The Xpdf software and documentation are copyright 1996-2011 Glyph & +The Xpdf software and documentation are copyright 1996-2014 Glyph & Cog, LLC. .SH "SEE ALSO" .BR xpdf (1), .BR pdftops (1), .BR pdftotext (1), +.BR pdftohtml (1), .BR pdfinfo (1), .BR pdffonts (1), .BR pdfdetach (1), .BR pdftoppm (1), +.BR pdftopng (1), .BR pdfimages (1) .br .B http://www.foolabs.com/xpdf/ diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.cat b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.cat index db42866605d..b8faf8a37b8 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.cat +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.cat @@ -3,7 +3,7 @@ xpdfrc(5) xpdfrc(5) NAME - xpdfrc - configuration file for Xpdf tools (version 3.03) + xpdfrc - configuration file for Xpdf tools (version 3.04) DESCRIPTION All of the Xpdf tools read a single configuration file. If you have a @@ -17,65 +17,68 @@ DESCRIPTION line. Blank lines and lines starting with a '#' (comments) are ignored. - The following sections list all of the configuration options, sorted + Arguments may be quoted, using "double-quote" characters, e.g., for + file names that contain spaces. + + The following sections list all of the configuration options, sorted into functional groups. There is an examples section at the end. INCLUDE FILES include config-file - Includes the specified config file. The effect of this is - equivalent to inserting the contents of config-file directly - into the parent config file in place of the include command. + Includes the specified config file. The effect of this is + equivalent to inserting the contents of config-file directly + into the parent config file in place of the include command. Config files can be nested arbitrarily deeply. CHARACTER MAPPING nameToUnicode map-file - Specifies a file with the mapping from character names to Uni- - code. This is used to handle PDF fonts that have valid encod- - ings but no ToUnicode entry. Each line of a nameToUnicode file + Specifies a file with the mapping from character names to Uni- + code. This is used to handle PDF fonts that have valid encod- + ings but no ToUnicode entry. Each line of a nameToUnicode file looks like this: hex-string name - The hex-string is the Unicode (UCS-2) character index, and name - is the corresponding character name. Multiple nameToUnicode - files can be used; if a character name is given more than once, - the code in the last specified file is used. There is a built- - in default nameToUnicode table with all of Adobe's standard + The hex-string is the Unicode (UCS-2) character index, and name + is the corresponding character name. Multiple nameToUnicode + files can be used; if a character name is given more than once, + the code in the last specified file is used. There is a built- + in default nameToUnicode table with all of Adobe's standard character names. cidToUnicode registry-ordering map-file Specifies the file with the mapping from character collection to - Unicode. Each line of a cidToUnicode file represents one char- + Unicode. Each line of a cidToUnicode file represents one char- acter: hex-string - The hex-string is the Unicode (UCS-2) index for that character. - The first line maps CID 0, the second line CID 1, etc. File - size is determined by size of the character collection. Only + The hex-string is the Unicode (UCS-2) index for that character. + The first line maps CID 0, the second line CID 1, etc. File + size is determined by size of the character collection. Only one file is allowed per character collection; the last specified file is used. There are no built-in cidToUnicode mappings. unicodeToUnicode font-name-substring map-file - This is used to work around PDF fonts which have incorrect Uni- + This is used to work around PDF fonts which have incorrect Uni- code information. It specifies a file which maps from the given - (incorrect) Unicode indexes to the correct ones. The mapping - will be used for any font whose name contains font-name-sub- - string. Each line of a unicodeToUnicode file represents one + (incorrect) Unicode indexes to the correct ones. The mapping + will be used for any font whose name contains font-name-sub- + string. Each line of a unicodeToUnicode file represents one Unicode character: in-hex out-hex1 out-hex2 ... - The in-hex field is an input (incorrect) Unicode index, and the - rest of the fields are one or more output (correct) Unicode - indexes. Each occurrence of in-hex will be converted to the + The in-hex field is an input (incorrect) Unicode index, and the + rest of the fields are one or more output (correct) Unicode + indexes. Each occurrence of in-hex will be converted to the specified output sequence. unicodeMap encoding-name map-file - Specifies the file with mapping from Unicode to encoding-name. + Specifies the file with mapping from Unicode to encoding-name. These encodings are used for text output (see below). Each line - of a unicodeMap file represents a range of one or more Unicode - characters which maps linearly to a range in the output encod- + of a unicodeMap file represents a range of one or more Unicode + characters which maps linearly to a range in the output encod- ing: in-start-hex in-end-hex out-start-hex @@ -84,149 +87,154 @@ CHARACTER MAPPING in-hex out-hex - The in-start-hex and in-end-hex fields (or the single in-hex - field) specify the Unicode range. The out-start-hex field (or - the out-hex field) specifies the start of the output encoding - range. The length of the out-start-hex (or out-hex) string + The in-start-hex and in-end-hex fields (or the single in-hex + field) specify the Unicode range. The out-start-hex field (or + the out-hex field) specifies the start of the output encoding + range. The length of the out-start-hex (or out-hex) string determines the length of the output characters (e.g., UTF-8 uses - different numbers of bytes to represent characters in different - ranges). Entries must be given in increasing Unicode order. - Only one file is allowed per encoding; the last specified file - is used. The Latin1, ASCII7, Symbol, ZapfDingbats, UTF-8, and + different numbers of bytes to represent characters in different + ranges). Entries must be given in increasing Unicode order. + Only one file is allowed per encoding; the last specified file + is used. The Latin1, ASCII7, Symbol, ZapfDingbats, UTF-8, and UCS-2 encodings are predefined. cMapDir registry-ordering dir - Specifies a search directory, dir, for CMaps for the reg- - istry-ordering character collection. There can be multiple - directories for a particular collection. There are no default + Specifies a search directory, dir, for CMaps for the reg- + istry-ordering character collection. There can be multiple + directories for a particular collection. There are no default CMap directories. toUnicodeDir dir - Specifies a search directory, dir, for ToUnicode CMaps. There - can be multiple ToUnicode directories. There are no default + Specifies a search directory, dir, for ToUnicode CMaps. There + can be multiple ToUnicode directories. There are no default ToUnicode directories. GENERAL FONT CONFIGURATION fontFile PDF-font-name font-file - Maps a PDF font, PDF-font-name, to a font for display or Post- - Script output. The font file, font-file, can be any type - allowed in a PDF file. This command can be used for 8-bit or + Maps a PDF font, PDF-font-name, to a font for display or Post- + Script output. The font file, font-file, can be any type + allowed in a PDF file. This command can be used for 8-bit or 16-bit (CID) fonts. fontDir dir - Specifies a search directory for font files. There can be mul- + Specifies a search directory for font files. There can be mul- tiple fontDir commands; all of the specified directories will be - searched in order. The font files can be Type 1 (.pfa or .pfb) + searched in order. The font files can be Type 1 (.pfa or .pfb) or TrueType (.ttf or .ttc); other files in the directory will be - ignored. The font file name (not including the extension) must - exactly match the PDF font name. This search is performed if - the font name doesn't match any of the fonts declared with the + ignored. The font file name (not including the extension) must + exactly match the PDF font name. This search is performed if + the font name doesn't match any of the fonts declared with the fontFile command. There are no default fontDir directories. fontFileCC registry-ordering font-file - Maps the registry-ordering character collection to a font for - display or PostScript output. This mapping is used if the font - name doesn't match any of the fonts declared with the fontFile, + Maps the registry-ordering character collection to a font for + display or PostScript output. This mapping is used if the font + name doesn't match any of the fonts declared with the fontFile, fontDir, psResidentFont16, or psResidentFontCC commands. POSTSCRIPT FONT CONFIGURATION psFontPassthrough yes | no If set to "yes", pass 8-bit font names through to the PostScript - output without substitution. Fonts which are not embedded in - the PDF file are expected to be available on the printer. This + output without substitution. Fonts which are not embedded in + the PDF file are expected to be available on the printer. This defaults to "no". psResidentFont PDF-font-name PS-font-name When the 8-bit font PDF-font-name is used (without embedding) in - a PDF file, it will be translated to the PostScript font - PS-font-name, which is assumed to be resident in the printer. - Typically, PDF-font-name and PS-font-name are the same. By + a PDF file, it will be translated to the PostScript font + PS-font-name, which is assumed to be resident in the printer. + Typically, PDF-font-name and PS-font-name are the same. By default, only the Base-14 fonts are assumed to be resident. psResidentFont16 PDF-font-name wMode PS-font-name encoding When the 16-bit (CID) font PDF-font-name with writing mode wMode is used (without embedding) in a PDF file, it will be translated - to the PostScript font PS-font-name, which is assumbed to be - resident in the printer. The writing mode must be either 'H' - for horizontal or 'V' for vertical. The resident font is - assumed to use the specified encoding (which must have been + to the PostScript font PS-font-name, which is assumbed to be + resident in the printer. The writing mode must be either 'H' + for horizontal or 'V' for vertical. The resident font is + assumed to use the specified encoding (which must have been defined with the unicodeMap command). psResidentFontCC registry-ordering wMode PS-font-name encoding - When a 16-bit (CID) font using the registry-ordering character + When a 16-bit (CID) font using the registry-ordering character collection and wMode writing mode is used (without embedding) in - a PDF file, the PostScript font, PS-font-name, is substituted - for it. The substituted font is assumbed to be resident in the - printer. The writing mode must be either 'H' for horizontal or + a PDF file, the PostScript font, PS-font-name, is substituted + for it. The substituted font is assumbed to be resident in the + printer. The writing mode must be either 'H' for horizontal or 'V' for vertical. The resident font is assumed to use the spec- ified encoding (which must have been defined with the unicodeMap command). psEmbedType1Fonts yes | no - If set to "no", prevents embedding of Type 1 fonts in generated + If set to "no", prevents embedding of Type 1 fonts in generated PostScript. This defaults to "yes". psEmbedTrueTypeFonts yes | no - If set to "no", prevents embedding of TrueType fonts in gener- + If set to "no", prevents embedding of TrueType fonts in gener- ated PostScript. This defaults to "yes". psEmbedCIDTrueTypeFonts yes | no If set to "no", prevents embedding of CID TrueType fonts in gen- erated PostScript. For Level 3 PostScript, this generates a CID - font, for lower levels it generates a non-CID composite font. + font, for lower levels it generates a non-CID composite font. This defaults to "yes". psEmbedCIDPostScriptFonts yes | no - If set to "no", prevents embedding of CID PostScript fonts in - generated PostScript. For Level 3 PostScript, this generates a - CID font, for lower levels it generates a non-CID composite + If set to "no", prevents embedding of CID PostScript fonts in + generated PostScript. For Level 3 PostScript, this generates a + CID font, for lower levels it generates a non-CID composite font. This defaults to "yes". POSTSCRIPT CONTROL psPaperSize width(pts) height(pts) Sets the paper size for PostScript output. The width and height - parameters give the paper size in PostScript points (1 point = + parameters give the paper size in PostScript points (1 point = 1/72 inch). psPaperSize letter | legal | A4 | A3 | match - Sets the paper size for PostScript output to a standard size. - The default paper size is set when xpdf and pdftops are built, + Sets the paper size for PostScript output to a standard size. + The default paper size is set when xpdf and pdftops are built, typically to "letter" or "A4". This can also be set to "match", which will set the paper size to match the size specified in the PDF file. psImageableArea llx lly urx ury - Sets the imageable area for PostScript output. The four inte- - gers are the coordinates of the lower-left and upper-right cor- + Sets the imageable area for PostScript output. The four inte- + gers are the coordinates of the lower-left and upper-right cor- ners of the imageable region, specified in points (with the ori- gin being the lower-left corner of the paper). This defaults to - the full paper size; the psPaperSize option will reset the + the full paper size; the psPaperSize option will reset the imageable area coordinates. psCrop yes | no - If set to "yes", PostScript output is cropped to the CropBox - specified in the PDF file; otherwise no cropping is done. This + If set to "yes", PostScript output is cropped to the CropBox + specified in the PDF file; otherwise no cropping is done. This defaults to "yes". + psUseCropBoxAsPage yes | no + If set to "yes", PostScript output treats the CropBox as the + page size. By default, this is "no", and the MediaBox is used + as the page size. + psExpandSmaller yes | no If set to "yes", PDF pages smaller than the PostScript imageable - area are expanded to fill the imageable area. Otherwise, no + area are expanded to fill the imageable area. Otherwise, no scalling is done on smaller pages. This defaults to "no". psShrinkLarger yes | no - If set to yes, PDF pages larger than the PostScript imageable - area are shrunk to fit the imageable area. Otherwise, no scal- + If set to yes, PDF pages larger than the PostScript imageable + area are shrunk to fit the imageable area. Otherwise, no scal- ing is done on larger pages. This defaults to "yes". psCenter yes | no - If set to yes, PDF pages smaller than the PostScript imageable - area (after any scaling) are centered in the imageable area. - Otherwise, they are aligned at the lower-left corner of the + If set to yes, PDF pages smaller than the PostScript imageable + area (after any scaling) are centered in the imageable area. + Otherwise, they are aligned at the lower-left corner of the imageable area. This defaults to "yes". psDuplex yes | no - If set to "yes", the generated PostScript will set the "Duplex" - pagedevice entry. This tells duplex-capable printers to enable + If set to "yes", the generated PostScript will set the "Duplex" + pagedevice entry. This tells duplex-capable printers to enable duplexing. This defaults to "no". psLevel level1 | level1sep | level2 | level2sep | level3 | level3Sep @@ -234,28 +242,39 @@ POSTSCRIPT CONTROL "level2". psPreload yes | no - If set to "yes", PDF forms are converted to PS procedures, and - image data is preloaded. This uses more memory in the Post- + If set to "yes", PDF forms are converted to PS procedures, and + image data is preloaded. This uses more memory in the Post- Script interpreter, but generates significantly smaller PS files in situations where, e.g., the same image is drawn on every page of a long document. This defaults to "no". psOPI yes | no - If set to "yes", generates PostScript OPI comments for all - images and forms which have OPI information. This option is + If set to "yes", generates PostScript OPI comments for all + images and forms which have OPI information. This option is only available if the Xpdf tools were compiled with OPI support. This defaults to "no". psASCIIHex yes | no - If set to "yes", the ASCIIHexEncode filter will be used instead + If set to "yes", the ASCIIHexEncode filter will be used instead of ASCII85Encode for binary data. This defaults to "no". + psLZW yes | no + If set to "yes", the LZWEncode filter will be used for lossless + compression in PostScript output; if set to "no", the RunLength- + Encode filter will be used instead. LZW generates better com- + pression (smaller PS files), but may not be supported by some + printers. This defaults to "yes". + psUncompressPreloadedImages yes | no - If set to "yes", all preloaded images in PS files will uncom- + If set to "yes", all preloaded images in PS files will uncom- pressed. If set to "no", the original compressed images will be - used when possible. The "yes" setting is useful to work around + used when possible. The "yes" setting is useful to work around certain buggy PostScript interpreters. This defaults to "no". + psMinLineWidth float + Set the minimum line width, in points, for PostScript output. + The default value is 0 (no minimum). + psRasterResolution float Set the resolution (in dpi) for rasterized pages in PostScript output. (Pdftops will rasterize pages which use transparency.) @@ -265,6 +284,11 @@ POSTSCRIPT CONTROL If set to "yes", rasterized pages in PS files will be monochrome (8-bit gray) instead of color. This defaults to "no". + psRasterSliceSize pixels + When rasterizing pages, pdftops splits the page into horizontal + "slices", to limit memory usage. This option sets the maximum + slice size, in pixels. This defaults to 20000000 (20 million). + psAlwaysRasterize yes | no If set to "yes", all PostScript output will be rasterized. This defaults to "no". @@ -307,7 +331,7 @@ TEXT CONTROL set to "no", text extraction will discard tiny (smaller than 3 point) characters after the first 50000 per page, avoiding extremely slow run times for PDF files that use special fonts to - do shading or cross-hatching. This defaults to "no". + do shading or cross-hatching. This defaults to "yes". MISCELLANEOUS SETTINGS initialZoom percentage | page | width @@ -321,136 +345,145 @@ MISCELLANEOUS SETTINGS with one vertical screoll bar for the whole document. This defaults to "no". - enableT1lib yes | no - Enables or disables use of t1lib (a Type 1 font rasterizer). - This is only relevant if the Xpdf tools were built with t1lib - support. ("enableT1lib" replaces the old "t1libControl" - option.) This option defaults to "yes". - 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". 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". 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 - Enables or disables stroke adjustment. Stroke adjustment moves + Enables or disables stroke adjustment. Stroke adjustment moves horizontal and vertical lines by up to half a pixel to make them - look "cleaner" when vector anti-aliasing is enabled. This + look "cleaner" when vector anti-aliasing is enabled. This defaults to "yes". 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). 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". 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". 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). urlCommand command - Sets the command executed when you click on a URL link. The - string "%s" will be replaced with the URL. (See the example + Sets the command executed when you click on a URL link. The + string "%s" will be replaced with the URL. (See the example below.) This has no default value. 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. mapNumericCharNames yes | no - If set to "yes", the Xpdf tools will attempt to map various + If set to "yes", the Xpdf tools will attempt to map various numeric character names sometimes used in font subsets. In some - cases this leads to usable text, and in other cases it leads to + cases this leads to usable text, and in other cases it leads to gibberish -- there is no way for Xpdf to tell. This defaults to "yes". mapUnknownCharNames yes | no - If set to "yes", and mapNumericCharNames is set to "no", the - Xpdf tools will apply a simple pass-through mapping (Unicode - index = character code) for all unrecognized glyph names. (For - CID fonts, setting mapNumericCharNames to "no" is unnecessary.) - In some cases, this leads to usable text, and in other cases it - leads to gibberish -- there is no way for Xpdf to tell. This + If set to "yes", and mapNumericCharNames is set to "no", the + Xpdf tools will apply a simple pass-through mapping (Unicode + index = character code) for all unrecognized glyph names. (For + CID fonts, setting mapNumericCharNames to "no" is unnecessary.) + In some cases, this leads to usable text, and in other cases it + leads to gibberish -- there is no way for Xpdf to tell. This defaults to "no". + mapExtTrueTypeFontsViaUnicode yes | no + When rasterizing text using an external TrueType font, there are + two options for handling character codes. If mapExtTrueType- + FontsViaUnicode is set to "yes", Xpdf will use the font encod- + ing/ToUnicode info to map character codes to Unicode, and then + use the font's Unicode cmap to map Unicode to GIDs. If mapExt- + TrueTypeFontsViaUnicode is set to "no", Xpdf will assume the + character codes are GIDs (i.e., use an identity mapping). This + defaults to "yes". + + enableXFA yes | no + If set to "yes", an XFA form (if present) will be rendered in + place of an AcroForm. If "no", an XFA form will never be ren- + dered. This defaults to "yes". + bind modifiers-key context command ... Add a key or mouse button binding. Modifiers can be zero or more of: @@ -572,7 +605,6 @@ EXAMPLES textEOL unix # misc options - enableT1lib yes enableFreeType yes launchCommand viewer-script urlCommand "netscape -remote 'openURL(%s)'" @@ -588,14 +620,14 @@ FILES read in place of the system-wide file. AUTHOR - The Xpdf software and documentation are copyright 1996-2011 Glyph & + The Xpdf software and documentation are copyright 1996-2014 Glyph & Cog, LLC. SEE ALSO - xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), pdfde- - tach(1), pdftoppm(1), pdfimages(1) + xpdf(1), pdftops(1), pdftotext(1), pdftohtml(1), pdfinfo(1), pdf- + fonts(1), pdfdetach(1), pdftoppm(1), pdftopng(1), pdfimages(1) http://www.foolabs.com/xpdf/ - 15 August 2011 xpdfrc(5) + 28 May 2014 xpdfrc(5) diff --git a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.hlp b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.hlp index 224456cb4f7..224456cb4f7 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/doc/xpdfrc.hlp +++ b/Build/source/libs/xpdf/xpdf-3.04/doc/xpdfrc.hlp diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiBase.cc b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiBase.cc index 4adef2a4c38..c9ca440b814 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiBase.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiBase.cc @@ -84,7 +84,7 @@ int FoFiBase::getU8(int pos, GBool *ok) { int FoFiBase::getS16BE(int pos, GBool *ok) { int x; - if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) { + if (pos < 0 || pos > INT_MAX - 1 || pos+1 >= len) { *ok = gFalse; return 0; } @@ -99,7 +99,7 @@ int FoFiBase::getS16BE(int pos, GBool *ok) { int FoFiBase::getU16BE(int pos, GBool *ok) { int x; - if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) { + if (pos < 0 || pos > INT_MAX - 1 || pos+1 >= len) { *ok = gFalse; return 0; } @@ -111,7 +111,7 @@ int FoFiBase::getU16BE(int pos, GBool *ok) { int FoFiBase::getS32BE(int pos, GBool *ok) { int x; - if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) { + if (pos < 0 || pos > INT_MAX - 3 || pos+3 >= len) { *ok = gFalse; return 0; } @@ -128,7 +128,7 @@ int FoFiBase::getS32BE(int pos, GBool *ok) { Guint FoFiBase::getU32BE(int pos, GBool *ok) { Guint x; - if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) { + if (pos < 0 || pos > INT_MAX - 3 || pos+3 >= len) { *ok = gFalse; return 0; } @@ -142,7 +142,7 @@ Guint FoFiBase::getU32BE(int pos, GBool *ok) { Guint FoFiBase::getU32LE(int pos, GBool *ok) { Guint x; - if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) { + if (pos < 0 || pos > INT_MAX - 3 || pos+3 >= len) { *ok = gFalse; return 0; } @@ -157,7 +157,7 @@ Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) { Guint x; int i; - if (pos < 0 || pos + size > len || pos > INT_MAX - size) { + if (pos < 0 || pos > INT_MAX - size || pos + size > len) { *ok = gFalse; return 0; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiBase.h b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiBase.h index c9f93ebacda..c9f93ebacda 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiBase.h +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiBase.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiEncodings.cc b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiEncodings.cc index e654fab19bf..e654fab19bf 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiEncodings.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiEncodings.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiEncodings.h b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiEncodings.h index dd85458c070..dd85458c070 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiEncodings.h +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiEncodings.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiIdentifier.cc b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiIdentifier.cc index 10ac486c9d0..978cc700ee3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiIdentifier.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiIdentifier.cc @@ -16,6 +16,9 @@ #include <string.h> #include <limits.h> #include "gtypes.h" +#include "gmem.h" +#include "GString.h" +#include "GList.h" #include "FoFiIdentifier.h" //------------------------------------------------------------------------ @@ -436,12 +439,23 @@ FoFiIdentifierType FoFiIdentifier::identifyMem(char *file, int len) { FoFiIdentifierType FoFiIdentifier::identifyFile(char *fileName) { FileReader *reader; FoFiIdentifierType type; + int n; if (!(reader = FileReader::make(fileName))) { return fofiIdError; } type = identify(reader); delete reader; + + // Mac OS X dfont files don't have any sort of header or magic number, + // so look at the file name extension + if (type == fofiIdUnknown) { + n = (int)strlen(fileName); + if (n >= 6 && !strcmp(fileName + n - 6, ".dfont")) { + type = fofiIdDfont; + } + } + return type; } @@ -630,3 +644,244 @@ static FoFiIdentifierType identifyCFF(Reader *reader, int start) { return fofiIdCFF8Bit; } } + +//------------------------------------------------------------------------ + +static GList *getTTCFontList(FILE *f); +static GList *getDfontFontList(FILE *f); + +GList *FoFiIdentifier::getFontList(char *fileName) { + FILE *f; + char buf[4]; + GList *ret; + + if (!(f = fopen(fileName, "rb"))) { + return NULL; + } + if (fread(buf, 1, 4, f) == 4 && + buf[0] == 0x74 && // 'ttcf' + buf[1] == 0x74 && + buf[2] == 0x63 && + buf[3] == 0x66) { + ret = getTTCFontList(f); + } else { + ret = getDfontFontList(f); + } + fclose(f); + return ret; +} + +static GList *getTTCFontList(FILE *f) { + Guchar buf[12]; + Guchar *buf2; + int fileLength, nFonts; + int tabDirOffset, nTables, nameTabOffset, nNames, stringsOffset; + int stringPlatform, stringLength, stringOffset; + GBool stringUnicode; + int i, j; + GList *ret; + + fseek(f, 0, SEEK_END); + fileLength = (int)ftell(f); + if (fileLength < 0) { + goto err1; + } + fseek(f, 8, SEEK_SET); + if (fread(buf, 1, 4, f) != 4) { + goto err1; + } + nFonts = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + if (nFonts < 0 || + 12 + 4 * nFonts > fileLength) { + goto err1; + } + ret = new GList(); + for (i = 0; i < nFonts; ++i) { + fseek(f, 12 + 4 * i, SEEK_SET); + if (fread(buf, 1, 4, f) != 4) { + goto err2; + } + tabDirOffset = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + if (tabDirOffset < 0 || + tabDirOffset + 12 < 0 || + tabDirOffset + 12 > fileLength) { + goto err2; + } + fseek(f, tabDirOffset, SEEK_SET); + if (fread(buf, 1, 12, f) != 12) { + goto err2; + } + nTables = (buf[4] << 8) | buf[5]; + if (tabDirOffset + 12 + 16 * nTables < 0 || + tabDirOffset + 12 + 16 * nTables > fileLength) { + goto err2; + } + buf2 = (Guchar *)gmallocn(nTables, 16); + if ((int)fread(buf2, 1, 16 * nTables, f) != 16 * nTables) { + goto err3; + } + nameTabOffset = 0; // make gcc happy + for (j = 0; j < nTables; ++j) { + if (buf2[16*j + 0] == 'n' && + buf2[16*j + 1] == 'a' && + buf2[16*j + 2] == 'm' && + buf2[16*j + 3] == 'e') { + nameTabOffset = (buf2[16*j + 8] << 24) | (buf2[16*j + 9] << 16) | + (buf2[16*j + 10] << 8) | buf2[16*j + 11]; + break; + } + } + gfree(buf2); + if (j >= nTables) { + goto err2; + } + if (nameTabOffset < 0 || + nameTabOffset + 6 < 0 || + nameTabOffset + 6 > fileLength) { + goto err2; + } + fseek(f, nameTabOffset, SEEK_SET); + if (fread(buf, 1, 6, f) != 6) { + goto err2; + } + nNames = (buf[2] << 8) | buf[3]; + stringsOffset = (buf[4] << 8) | buf[5]; + if (nameTabOffset + 6 + 12 * nNames < 0 || + nameTabOffset + 6 + 12 * nNames > fileLength || + nameTabOffset + stringsOffset < 0) { + goto err2; + } + buf2 = (Guchar *)gmallocn(nNames, 12); + if ((int)fread(buf2, 1, 12 * nNames, f) != 12 * nNames) { + goto err3; + } + for (j = 0; j < nNames; ++j) { + if (buf2[12*j + 6] == 0 && // 0x0004 = full name + buf2[12*j + 7] == 4) { + break; + } + } + if (j >= nNames) { + goto err3; + } + stringPlatform = (buf2[12*j] << 8) | buf2[12*j + 1]; + // stringEncoding = (buf2[12*j + 2] << 8) | buf2[12*j + 3]; + stringUnicode = stringPlatform == 0 || stringPlatform == 3; + stringLength = (buf2[12*j + 8] << 8) | buf2[12*j + 9]; + stringOffset = nameTabOffset + stringsOffset + + ((buf2[12*j + 10] << 8) | buf2[12*j + 11]); + gfree(buf2); + if (stringOffset < 0 || + stringOffset + stringLength < 0 || + stringOffset + stringLength > fileLength) { + goto err2; + } + buf2 = (Guchar *)gmalloc(stringLength); + fseek(f, stringOffset, SEEK_SET); + if ((int)fread(buf2, 1, stringLength, f) != stringLength) { + goto err3; + } + if (stringUnicode) { + stringLength /= 2; + for (j = 0; j < stringLength; ++j) { + buf2[j] = buf2[2*j + 1]; + } + } + ret->append(new GString((char *)buf2, stringLength)); + gfree(buf2); + } + return ret; + + err3: + gfree(buf2); + err2: + deleteGList(ret, GString); + err1: + return NULL; +} + +static GList *getDfontFontList(FILE *f) { + Guchar buf[16]; + Guchar *resMap; + int fileLength, resMapOffset, resMapLength; + int resTypeListOffset, resNameListOffset, nTypes; + int refListOffset, nFonts, nameOffset, nameLen; + int offset, i; + GList *ret; + + fseek(f, 0, SEEK_END); + fileLength = (int)ftell(f); + if (fileLength < 0) { + goto err1; + } + fseek(f, 0, SEEK_SET); + if (fread((char *)buf, 1, 16, f) != 16) { + goto err1; + } + resMapOffset = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; + resMapLength = (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15]; + if (resMapOffset < 0 || + resMapOffset >= fileLength || + resMapLength < 0 || + resMapOffset + resMapLength > fileLength || + resMapOffset + resMapLength < 0) { + goto err1; + } + if (resMapLength > 32768) { + // sanity check - this probably isn't a dfont file + goto err1; + } + resMap = (Guchar *)gmalloc(resMapLength); + fseek(f, resMapOffset, SEEK_SET); + if ((int)fread((char *)resMap, 1, resMapLength, f) != resMapLength) { + goto err2; + } + resTypeListOffset = (resMap[24] << 8) | resMap[25]; + resNameListOffset = (resMap[26] << 8) | resMap[27]; + nTypes = ((resMap[28] << 8) | resMap[29]) + 1; + if (resTypeListOffset + 2 + nTypes * 8 > resMapLength || + resNameListOffset >= resMapLength) { + goto err2; + } + for (i = 0; i < nTypes; ++i) { + offset = resTypeListOffset + 2 + 8 * i; + if (resMap[offset] == 0x73 && // 'sfnt' + resMap[offset+1] == 0x66 && + resMap[offset+2] == 0x6e && + resMap[offset+3] == 0x74) { + nFonts = ((resMap[offset+4] << 8) | resMap[offset+5]) + 1; + refListOffset = (resMap[offset+6] << 8) | resMap[offset+7]; + break; + } + } + if (i >= nTypes) { + goto err2; + } + if (resTypeListOffset + refListOffset >= resMapLength || + resTypeListOffset + refListOffset + nFonts * 12 > resMapLength) { + goto err2; + } + ret = new GList(); + for (i = 0; i < nFonts; ++i) { + offset = resTypeListOffset + refListOffset + 12 * i; + nameOffset = (resMap[offset+2] << 8) | resMap[offset+3]; + offset = resNameListOffset + nameOffset; + if (offset >= resMapLength) { + goto err3; + } + nameLen = resMap[offset]; + if (offset + 1 + nameLen > resMapLength) { + goto err3; + } + ret->append(new GString((char *)resMap + offset + 1, nameLen)); + } + gfree(resMap); + return ret; + + err3: + deleteGList(ret, GString); + err2: + gfree(resMap); + err1: + return NULL; +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiIdentifier.h b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiIdentifier.h index 79da845a3d4..b0307a0b8d2 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiIdentifier.h +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiIdentifier.h @@ -15,6 +15,8 @@ #pragma interface #endif +class GList; + //------------------------------------------------------------------------ // FoFiIdentifier //------------------------------------------------------------------------ @@ -28,6 +30,7 @@ enum FoFiIdentifierType { fofiIdTrueTypeCollection, // TrueType collection fofiIdOpenTypeCFF8Bit, // OpenType wrapper with 8-bit CFF font fofiIdOpenTypeCFFCID, // OpenType wrapper with CID CFF font + fofiIdDfont, // Mac OS X dfont fofiIdUnknown, // unknown type fofiIdError // error in reading the file }; @@ -35,10 +38,18 @@ enum FoFiIdentifierType { class FoFiIdentifier { public: + // Identify a font file. static FoFiIdentifierType identifyMem(char *file, int len); static FoFiIdentifierType identifyFile(char *fileName); static FoFiIdentifierType identifyStream(int (*getChar)(void *data), void *data); + + // Return a list of font names (GString *) in a font collection + // file. Indexes into the returned list are indexes into the + // collection. This function is only useful with TrueType + // collections and Mac dfont files. Returns NULL on error + // (including invalid font type). + static GList *getFontList(char *fileName); }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiTrueType.cc b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiTrueType.cc index 6503fda5474..8a1bfec7080 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiTrueType.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiTrueType.cc @@ -275,10 +275,11 @@ static const char *macGlyphNames[258] = { // FoFiTrueType //------------------------------------------------------------------------ -FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) { +FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA, int fontNum, + GBool allowHeadlessCFF) { FoFiTrueType *ff; - ff = new FoFiTrueType(fileA, lenA, gFalse); + ff = new FoFiTrueType(fileA, lenA, gFalse, fontNum, gFalse, allowHeadlessCFF); if (!ff->parsedOk) { delete ff; return NULL; @@ -286,15 +287,20 @@ FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) { return ff; } -FoFiTrueType *FoFiTrueType::load(char *fileName) { +FoFiTrueType *FoFiTrueType::load(char *fileName, int fontNum, + GBool allowHeadlessCFF) { FoFiTrueType *ff; char *fileA; - int lenA; + int lenA, n; + GBool isDfontA; if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { return NULL; } - ff = new FoFiTrueType(fileA, lenA, gTrue); + n = (int)strlen(fileName); + isDfontA = n >= 6 && !strcmp(fileName + n - 6, ".dfont"); + ff = new FoFiTrueType(fileA, lenA, gTrue, fontNum, isDfontA, + allowHeadlessCFF); if (!ff->parsedOk) { delete ff; return NULL; @@ -302,7 +308,9 @@ FoFiTrueType *FoFiTrueType::load(char *fileName) { return ff; } -FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA): +FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, + int fontNum, GBool isDfontA, + GBool allowHeadlessCFF): FoFiBase(fileA, lenA, freeFileDataA) { tables = NULL; @@ -310,9 +318,10 @@ FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA): cmaps = NULL; nCmaps = 0; nameToGID = NULL; + isDfont = isDfontA; parsedOk = gFalse; - parse(); + parse(fontNum, allowHeadlessCFF); } FoFiTrueType::~FoFiTrueType() { @@ -363,7 +372,26 @@ int FoFiTrueType::mapCodeToGID(int i, int c) { if (c < 0 || c >= cmaps[i].len - 6) { return 0; } - gid = getU8(cmaps[i].offset + 6 + c, &ok); + gid = getU8(pos + 6 + c, &ok); + break; + case 2: + // this only handles single-byte codes + if (c < 0 || c > 0xff) { + return 0; + } + // check that: subHeaderKeys[0] = 0 + // subHeaders[0].firstCode = 0 + // subHeaders[0].entryCount = 256 + // subHeaders[0].idDelta = 0 + if (getU16BE(pos + 6, &ok) != 0 || + getU16BE(pos + 518 + 0, &ok) != 0 || + getU16BE(pos + 518 + 2, &ok) != 256 || + getU16BE(pos + 518 + 4, &ok) != 0) { + return 0; + } + // subHeaders[0].idRangeOffset is a byte offset from itself + pos = pos + 518 + 6 + getU16BE(pos + 518 + 6, &ok); + gid = getU16BE(pos + 2 * c, &ok); break; case 4: segCnt = getU16BE(pos + 6, &ok) / 2; @@ -1022,7 +1050,7 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, if (!missingCmap && !missingName && !missingPost && !missingOS2 && !unsortedLoca && !emptyCmap && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 && nBogusTables == 0 && - !name && !codeToGID) { + !name && !codeToGID && !isDfont) { (*outputFunc)(outputStream, (char *)file, len); goto done1; } @@ -1632,6 +1660,14 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, // table, cmpTrueTypeLocaOffset uses offset as its primary sort key, // and idx as its secondary key (ensuring that adjacent entries with // the same pos value remain in the same order) + // + // NB: a glyph description containing 12 zero bytes should be a + // valid empty glyph (from my reading of the TrueType spec), but + // Acrobat chokes on this (which is an issue when an Xpdf-generated + // PS file is converted back to PDF - with Ghostscript or + // Distiller), so we drop any glyph descriptions of 12 or fewer + // bytes -- an empty glyph description generates an empty glyph with + // no errors locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); i = seekTable("loca"); pos = tables[i].offset; @@ -1670,11 +1706,11 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, *maxUsedGlyph = -1; for (i = 0; i <= nGlyphs; ++i) { locaTable[i].newOffset = pos; - pos += locaTable[i].len; - if (pos & 3) { - pos += 4 - (pos & 3); - } - if (locaTable[i].len > 0) { + if (locaTable[i].len > 12) { + pos += locaTable[i].len; + if (pos & 3) { + pos += 4 - (pos & 3); + } *maxUsedGlyph = i; } } @@ -1737,14 +1773,17 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, checksum = 0; glyfPos = tables[seekTable("glyf")].offset; for (j = 0; j < nGlyphs; ++j) { - length += locaTable[j].len; - if (length & 3) { - length += 4 - (length & 3); - } - if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { - checksum += - computeTableChecksum(file + glyfPos + locaTable[j].origOffset, - locaTable[j].len); + if (locaTable[j].len > 12) { + length += locaTable[j].len; + if (length & 3) { + length += 4 - (length & 3); + } + if (checkRegion(glyfPos + locaTable[j].origOffset, + locaTable[j].len)) { + checksum += + computeTableChecksum(file + glyfPos + locaTable[j].origOffset, + locaTable[j].len); + } } } } else { @@ -1858,7 +1897,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, } else if (i == t42GlyfTable) { glyfPos = tables[seekTable("glyf")].offset; for (j = 0; j < nGlyphs; ++j) { - if (locaTable[j].len > 0 && + if (locaTable[j].len > 12 && checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { dumpString(file + glyfPos + locaTable[j].origOffset, locaTable[j].len, outputFunc, outputStream); @@ -1950,35 +1989,43 @@ Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) { return checksum; } -void FoFiTrueType::parse() { +void FoFiTrueType::parse(int fontNum, GBool allowHeadlessCFF) { Guint topTag; - int pos, ver, i, j; + int offset, pos, ver, i, j; parsedOk = gTrue; - // look for a collection (TTC) - topTag = getU32BE(0, &parsedOk); - if (!parsedOk) { - return; - } - if (topTag == ttcfTag) { - pos = getU32BE(12, &parsedOk); + // check for a dfont or TrueType collection (TTC) + // offset = start of actual TrueType font file (table positions are + // relative to this + // pos = position of table directory (relative to offset) + if (isDfont) { + parseDfont(fontNum, &offset, &pos); + } else { + offset = 0; + topTag = getU32BE(0, &parsedOk); if (!parsedOk) { return; } - } else { - pos = 0; + if (topTag == ttcfTag) { + parseTTC(fontNum, &pos); + } else { + pos = 0; + } + } + if (!parsedOk) { + return; } // check the sfnt version - ver = getU32BE(pos, &parsedOk); + ver = getU32BE(offset + pos, &parsedOk); if (!parsedOk) { return; } openTypeCFF = ver == 0x4f54544f; // 'OTTO' // read the table directory - nTables = getU16BE(pos + 4, &parsedOk); + nTables = getU16BE(offset + pos + 4, &parsedOk); if (!parsedOk) { return; } @@ -1986,10 +2033,10 @@ void FoFiTrueType::parse() { pos += 12; j = 0; for (i = 0; i < nTables; ++i) { - tables[j].tag = getU32BE(pos, &parsedOk); - tables[j].checksum = getU32BE(pos + 4, &parsedOk); - tables[j].offset = (int)getU32BE(pos + 8, &parsedOk); - tables[j].len = (int)getU32BE(pos + 12, &parsedOk); + tables[j].tag = getU32BE(offset + pos, &parsedOk); + tables[j].checksum = getU32BE(offset + pos + 4, &parsedOk); + tables[j].offset = offset + (int)getU32BE(offset + pos + 8, &parsedOk); + tables[j].len = (int)getU32BE(offset + pos + 12, &parsedOk); if (tables[j].offset + tables[j].len >= tables[j].offset && tables[j].offset + tables[j].len <= len) { // ignore any bogus entries in the table directory @@ -2002,10 +2049,23 @@ void FoFiTrueType::parse() { return; } - // check for tables that are required by both the TrueType spec and - // the Type 42 spec - if (seekTable("head") < 0 || - seekTable("hhea") < 0 || + // check for the head table; allow for a head-less OpenType CFF font + headlessCFF = gFalse; + if (seekTable("head") < 0) { + if (openTypeCFF && allowHeadlessCFF) { + headlessCFF = gTrue; + nGlyphs = 0; + bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0; + locaFmt = 0; + return; + } + parsedOk = gFalse; + return; + } + + // check for other tables that are required by both the TrueType + // spec and the Type 42 spec + if (seekTable("hhea") < 0 || seekTable("maxp") < 0 || seekTable("hmtx") < 0 || (!openTypeCFF && seekTable("loca") < 0) || @@ -2016,7 +2076,7 @@ void FoFiTrueType::parse() { } // read the cmaps - if ((i = seekTable("cmap")) >= 0) { + if ((i = seekTable("cmap")) >= 0 && tables[i].len >= 4) { pos = tables[i].offset + 2; nCmaps = getU16BE(pos, &parsedOk); pos += 2; @@ -2035,8 +2095,6 @@ void FoFiTrueType::parse() { if (!parsedOk) { return; } - } else { - nCmaps = 0; } // get the number of glyphs from the maxp table @@ -2087,6 +2145,74 @@ void FoFiTrueType::parse() { readPostTable(); } +// Get the table directory position +void FoFiTrueType::parseTTC(int fontNum, int *pos) { + int nFonts; + + nFonts = getU32BE(8, &parsedOk); + if (!parsedOk) { + return; + } + if (fontNum < 0 || fontNum >= nFonts) { + parsedOk = gFalse; + return; + } + *pos = getU32BE(12 + 4 * fontNum, &parsedOk); +} + +void FoFiTrueType::parseDfont(int fontNum, int *offset, int *startPos) { + int resMapOffset, resDataOffset; + int resTypeListOffset, nTypes, typeTag; + int nFonts, refListOffset, dataOffset; + int pos, i; + + resDataOffset = getU32BE(0, &parsedOk); + resMapOffset = getU32BE(4, &parsedOk); + if (!parsedOk) { + return; + } + + resTypeListOffset = getU16BE(resMapOffset + 24, &parsedOk); + // resNameListOffset = getU16BE(resMapOffset + 26, &parsedOk); + nTypes = getU16BE(resMapOffset + 28, &parsedOk) + 1; + if (!parsedOk) { + return; + } + + pos = 0; // make gcc happy + for (i = 0; i < nTypes; ++i) { + pos = resMapOffset + resTypeListOffset + 2 + 8*i; + typeTag = getU32BE(pos, &parsedOk); + if (!parsedOk) { + return; + } + if (typeTag == 0x73666e74) { // 'sfnt' + break; + } + } + if (i >= nTypes) { + parsedOk = gFalse; + return; + } + nFonts = getU16BE(pos + 4, &parsedOk) + 1; + refListOffset = getU16BE(pos + 6, &parsedOk); + if (!parsedOk) { + return; + } + if (fontNum < 0 || fontNum >= nFonts) { + parsedOk = gFalse; + return; + } + pos = resMapOffset + resTypeListOffset + refListOffset + 12 * fontNum; + dataOffset = getU32BE(pos + 4, &parsedOk) & 0x00ffffff; + if (!parsedOk) { + return; + } + // the data offset points to a 4-byte length field, which we skip over + *offset = resDataOffset + dataOffset + 4; + *startPos = 0; +} + void FoFiTrueType::readPostTable() { GString *name; int tablePos, postFmt, stringIdx, stringPos; diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiTrueType.h b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiTrueType.h index 53d50624483..2cf9417d609 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiTrueType.h +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiTrueType.h @@ -30,11 +30,19 @@ struct TrueTypeCmap; class FoFiTrueType: public FoFiBase { public: - // Create a FoFiTrueType object from a memory buffer. - static FoFiTrueType *make(char *fileA, int lenA); - - // Create a FoFiTrueType object from a file on disk. - static FoFiTrueType *load(char *fileName); + // Create a FoFiTrueType object from a memory buffer. If + // <allowHeadlessCFF> is true, OpenType CFF fonts without the 'head' + // table are permitted -- this is useful when calling the convert* + // functions. + static FoFiTrueType *make(char *fileA, int lenA, int fontNum, + GBool allowHeadlessCFF = gFalse); + + // Create a FoFiTrueType object from a file on disk. If + // <allowHeadlessCFF> is true, OpenType CFF fonts without the 'head' + // table are permitted -- this is useful when calling the convert* + // functions. + static FoFiTrueType *load(char *fileName, int fontNum, + GBool allowHeadlessCFF = gFalse); virtual ~FoFiTrueType(); @@ -42,6 +50,12 @@ public: // if it's a TrueType font (or OpenType font with TrueType data). GBool isOpenTypeCFF() { return openTypeCFF; } + // Returns true if this is an OpenType CFF font that is missing the + // 'head' table. This is a violation of the OpenType spec, but the + // embedded CFF font can be usable for some purposes (e.g., the + // convert* functions). + GBool isHeadlessCFF() { return headlessCFF; } + // Return the number of cmaps defined by this font. int getNumCmaps(); @@ -148,7 +162,8 @@ public: private: - FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA); + FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, + int fontNum, GBool isDfont, GBool allowHeadlessCFF); void cvtEncoding(char **encoding, FoFiOutputFunc outputFunc, void *outputStream); @@ -164,7 +179,9 @@ private: FoFiOutputFunc outputFunc, void *outputStream); Guint computeTableChecksum(Guchar *data, int length); - void parse(); + void parse(int fontNum, GBool allowHeadlessCFF); + void parseTTC(int fontNum, int *pos); + void parseDfont(int fontNum, int *offset, int *pos); void readPostTable(); int seekTable(const char *tag); @@ -177,6 +194,8 @@ private: int bbox[4]; GHash *nameToGID; GBool openTypeCFF; + GBool headlessCFF; + GBool isDfont; GBool parsedOk; }; diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1.cc b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1.cc index 9eeb363d459..9eeb363d459 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1.h b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1.h index 4a64f246dcb..4a64f246dcb 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1.h +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1C.cc b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1C.cc index 93af207696f..7986cee88f1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1C.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1C.cc @@ -387,24 +387,42 @@ void FoFiType1C::convertToType1(char *psName, const char **newEncoding, delete buf; } if (privateDicts[0].nStemSnapH) { - eexecWrite(&eb, "/StemSnapH ["); - for (i = 0; i < privateDicts[0].nStemSnapH; ++i) { - buf = GString::format("{0:s}{1:.4g}", - i > 0 ? " " : "", privateDicts[0].stemSnapH[i]); - eexecWrite(&eb, buf->getCString()); - delete buf; + // the StemSnapH array should be unique values in ascending order -- + // if not, just skip it + for (i = 1; i < privateDicts[0].nStemSnapH; ++i) { + if (privateDicts[0].stemSnapH[i-1] >= privateDicts[0].stemSnapH[i]) { + break; + } + } + if (i == privateDicts[0].nStemSnapH) { + eexecWrite(&eb, "/StemSnapH ["); + for (i = 0; i < privateDicts[0].nStemSnapH; ++i) { + buf = GString::format("{0:s}{1:.4g}", + i > 0 ? " " : "", privateDicts[0].stemSnapH[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); } - eexecWrite(&eb, "] def\n"); } if (privateDicts[0].nStemSnapV) { - eexecWrite(&eb, "/StemSnapV ["); - for (i = 0; i < privateDicts[0].nStemSnapV; ++i) { - buf = GString::format("{0:s}{1:.4g}", - i > 0 ? " " : "", privateDicts[0].stemSnapV[i]); - eexecWrite(&eb, buf->getCString()); - delete buf; + // the StemSnapV array should be unique values in ascending order -- + // if not, just skip it + for (i = 1; i < privateDicts[0].nStemSnapV; ++i) { + if (privateDicts[0].stemSnapV[i-1] >= privateDicts[0].stemSnapV[i]) { + break; + } + } + if (i == privateDicts[0].nStemSnapV) { + eexecWrite(&eb, "/StemSnapV ["); + for (i = 0; i < privateDicts[0].nStemSnapV; ++i) { + buf = GString::format("{0:s}{1:.4g}", + i > 0 ? " " : "", privateDicts[0].stemSnapV[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); } - eexecWrite(&eb, "] def\n"); } if (privateDicts[0].hasForceBold) { buf = GString::format("/ForceBold {0:s} def\n", @@ -719,24 +737,42 @@ void FoFiType1C::convertToCIDType0(char *psName, int *codeMap, int nCodes, delete buf; } if (privateDicts[i].nStemSnapH) { - (*outputFunc)(outputStream, "/StemSnapH [", 12); - for (j = 0; j < privateDicts[i].nStemSnapH; ++j) { - buf = GString::format("{0:s}{1:.4g}", - j > 0 ? " " : "", privateDicts[i].stemSnapH[j]); - (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); - delete buf; + // the StemSnapH array should be unique values in ascending order -- + // if not, just skip it + for (j = 1; j < privateDicts[i].nStemSnapH; ++j) { + if (privateDicts[i].stemSnapH[j-1] >= privateDicts[i].stemSnapH[j]) { + break; + } + } + if (j == privateDicts[0].nStemSnapH) { + (*outputFunc)(outputStream, "/StemSnapH [", 12); + for (j = 0; j < privateDicts[i].nStemSnapH; ++j) { + buf = GString::format("{0:s}{1:.4g}", + j > 0 ? " " : "", privateDicts[i].stemSnapH[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); } - (*outputFunc)(outputStream, "] def\n", 6); } if (privateDicts[i].nStemSnapV) { - (*outputFunc)(outputStream, "/StemSnapV [", 12); - for (j = 0; j < privateDicts[i].nStemSnapV; ++j) { - buf = GString::format("{0:s}{1:.4g}", - j > 0 ? " " : "", privateDicts[i].stemSnapV[j]); - (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); - delete buf; + // the StemSnapV array should be unique values in ascending order -- + // if not, just skip it + for (j = 1; j < privateDicts[i].nStemSnapV; ++j) { + if (privateDicts[i].stemSnapV[j-1] >= privateDicts[i].stemSnapV[j]) { + break; + } + } + if (j == privateDicts[0].nStemSnapV) { + (*outputFunc)(outputStream, "/StemSnapV [", 12); + for (j = 0; j < privateDicts[i].nStemSnapV; ++j) { + buf = GString::format("{0:s}{1:.4g}", + j > 0 ? " " : "", privateDicts[i].stemSnapV[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); } - (*outputFunc)(outputStream, "] def\n", 6); } if (privateDicts[i].hasForceBold) { buf = GString::format("/ForceBold {0:s} def\n", @@ -1017,24 +1053,44 @@ void FoFiType1C::convertToType0(char *psName, int *codeMap, int nCodes, delete buf; } if (privateDicts[fd].nStemSnapH) { - eexecWrite(&eb, "/StemSnapH ["); - for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) { - buf = GString::format("{0:s}{1:.4g}", - k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]); - eexecWrite(&eb, buf->getCString()); - delete buf; + // the StemSnapH array should be unique values in ascending order -- + // if not, just skip it + for (k = 1; k < privateDicts[fd].nStemSnapH; ++k) { + if (privateDicts[fd].stemSnapH[k-1] >= privateDicts[fd].stemSnapH[k]) { + break; + } + } + if (k == privateDicts[0].nStemSnapH) { + eexecWrite(&eb, "/StemSnapH ["); + for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) { + buf = GString::format("{0:s}{1:.4g}", + k > 0 ? " " : "", + privateDicts[fd].stemSnapH[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); } - eexecWrite(&eb, "] def\n"); } if (privateDicts[fd].nStemSnapV) { - eexecWrite(&eb, "/StemSnapV ["); - for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) { - buf = GString::format("{0:s}{1:.4g}", - k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]); - eexecWrite(&eb, buf->getCString()); - delete buf; + // the StemSnapV array should be unique values in ascending order -- + // if not, just skip it + for (k = 1; k < privateDicts[fd].nStemSnapV; ++k) { + if (privateDicts[fd].stemSnapV[k-1] >= privateDicts[fd].stemSnapV[k]) { + break; + } + } + if (k == privateDicts[0].nStemSnapV) { + eexecWrite(&eb, "/StemSnapV ["); + for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) { + buf = GString::format("{0:s}{1:.4g}", + k > 0 ? " " : "", + privateDicts[fd].stemSnapV[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); } - eexecWrite(&eb, "] def\n"); } if (privateDicts[fd].hasForceBold) { buf = GString::format("/ForceBold {0:s} def\n", diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1C.h b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1C.h index 0c5b4fb6ead..0c5b4fb6ead 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/FoFiType1C.h +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/FoFiType1C.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/Makefile.dep b/Build/source/libs/xpdf/xpdf-3.04/fofi/Makefile.dep index e69de29bb2d..e69de29bb2d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/Makefile.dep +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/Makefile.in b/Build/source/libs/xpdf/xpdf-3.04/fofi/Makefile.in index f4f5d0050ba..d00f83f1c25 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/Makefile.in +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/Makefile.in @@ -14,7 +14,7 @@ VPATH = @srcdir@ GOOSRCDIR = $(srcdir)/../goo GOOLIBDIR = ../goo -CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(GOOSRCDIR) -I$(srcdir) +CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir)/.. -I$(GOOSRCDIR) -I$(srcdir) CXX = @CXX@ AR = @AR@ @@ -68,4 +68,4 @@ clean: depend: $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep -include Makefile.dep +-include Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/fofi/vms_make.com b/Build/source/libs/xpdf/xpdf-3.04/fofi/vms_make.com index e69de29bb2d..e69de29bb2d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/fofi/vms_make.com +++ b/Build/source/libs/xpdf/xpdf-3.04/fofi/vms_make.com diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/FixedPoint.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/FixedPoint.cc index 34661ad0f30..34661ad0f30 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/FixedPoint.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/FixedPoint.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/FixedPoint.h b/Build/source/libs/xpdf/xpdf-3.04/goo/FixedPoint.h index f9cdd4e8a84..1f4be7095d0 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/FixedPoint.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/FixedPoint.h @@ -49,35 +49,35 @@ public: FixedPoint operator =(FixedPoint x) { val = x.val; return *this; } - int operator ==(FixedPoint x) { return val == x.val; } - int operator ==(double x) { return *this == (FixedPoint)x; } - int operator ==(int x) { return *this == (FixedPoint)x; } - int operator ==(long x) { return *this == (FixedPoint)x; } - - int operator !=(FixedPoint x) { return val != x.val; } - int operator !=(double x) { return *this != (FixedPoint)x; } - int operator !=(int x) { return *this != (FixedPoint)x; } - int operator !=(long x) { return *this != (FixedPoint)x; } - - int operator <(FixedPoint x) { return val < x.val; } - int operator <(double x) { return *this < (FixedPoint)x; } - int operator <(int x) { return *this < (FixedPoint)x; } - int operator <(long x) { return *this < (FixedPoint)x; } - - int operator <=(FixedPoint x) { return val <= x.val; } - int operator <=(double x) { return *this <= (FixedPoint)x; } - int operator <=(int x) { return *this <= (FixedPoint)x; } - int operator <=(long x) { return *this <= (FixedPoint)x; } - - int operator >(FixedPoint x) { return val > x.val; } - int operator >(double x) { return *this > (FixedPoint)x; } - int operator >(int x) { return *this > (FixedPoint)x; } - int operator >(long x) { return *this > (FixedPoint)x; } - - int operator >=(FixedPoint x) { return val >= x.val; } - int operator >=(double x) { return *this >= (FixedPoint)x; } - int operator >=(int x) { return *this >= (FixedPoint)x; } - int operator >=(long x) { return *this >= (FixedPoint)x; } + int operator ==(FixedPoint x) const { return val == x.val; } + int operator ==(double x) const { return *this == (FixedPoint)x; } + int operator ==(int x) const { return *this == (FixedPoint)x; } + int operator ==(long x) const { return *this == (FixedPoint)x; } + + int operator !=(FixedPoint x) const { return val != x.val; } + int operator !=(double x) const { return *this != (FixedPoint)x; } + int operator !=(int x) const { return *this != (FixedPoint)x; } + int operator !=(long x) const { return *this != (FixedPoint)x; } + + int operator <(FixedPoint x) const { return val < x.val; } + int operator <(double x) const { return *this < (FixedPoint)x; } + int operator <(int x) const { return *this < (FixedPoint)x; } + int operator <(long x) const { return *this < (FixedPoint)x; } + + int operator <=(FixedPoint x) const { return val <= x.val; } + int operator <=(double x) const { return *this <= (FixedPoint)x; } + int operator <=(int x) const { return *this <= (FixedPoint)x; } + int operator <=(long x) const { return *this <= (FixedPoint)x; } + + int operator >(FixedPoint x) const { return val > x.val; } + int operator >(double x) const { return *this > (FixedPoint)x; } + int operator >(int x) const { return *this > (FixedPoint)x; } + int operator >(long x) const { return *this > (FixedPoint)x; } + + int operator >=(FixedPoint x) const { return val >= x.val; } + int operator >=(double x) const { return *this >= (FixedPoint)x; } + int operator >=(int x) const { return *this >= (FixedPoint)x; } + int operator >=(long x) const { return *this >= (FixedPoint)x; } FixedPoint operator -() { return make(-val); } diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GHash.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/GHash.cc index 32e85b41dea..32e85b41dea 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GHash.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GHash.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GHash.h b/Build/source/libs/xpdf/xpdf-3.04/goo/GHash.h index 179753a50b4..179753a50b4 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GHash.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GHash.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GList.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/GList.cc index 5d9cba3787e..5d9cba3787e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GList.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GList.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GList.h b/Build/source/libs/xpdf/xpdf-3.04/goo/GList.h index 005043726a5..005043726a5 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GList.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GList.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GMutex.h b/Build/source/libs/xpdf/xpdf-3.04/goo/GMutex.h index 7fa93d85e06..5d5621af2ae 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GMutex.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GMutex.h @@ -22,7 +22,7 @@ // ... // gDestroyMutex(&m); -#ifdef WIN32 +#ifdef _WIN32 #include <windows.h> diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GString.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/GString.cc index ea0b3cafea8..adf7739c9aa 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GString.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GString.cc @@ -19,6 +19,7 @@ #include <string.h> #include <ctype.h> #include <math.h> +#include <limits.h> #include "gmem.h" #include "GString.h" @@ -100,6 +101,9 @@ static const char *formatStrings[] = { static inline int size(int len) { int delta; for (delta = 8; delta < len && delta < 0x100000; delta <<= 1) ; + if (len > INT_MAX - delta) { + gMemError("Integer overflow in GString::size()"); + } // this is ((len + 1) + (delta - 1)) & ~(delta - 1) return (len + delta) & ~(delta - 1); } @@ -107,6 +111,9 @@ static inline int size(int len) { inline void GString::resize(int length1) { char *s1; + if (length1 < 0) { + gMemError("GString::resize() with negative length"); + } if (!s) { s = new char[size(length1)]; } else if (size(length1) != size(length)) { @@ -161,6 +168,9 @@ GString::GString(GString *str1, GString *str2) { int n2 = str2->getLength(); s = NULL; + if (n1 > INT_MAX - n2) { + gMemError("Integer overflow in GString::GString()"); + } resize(length = n1 + n2); memcpy(s, str1->getCString(), n1); memcpy(s + n1, str2->getCString(), n2 + 1); @@ -168,7 +178,7 @@ GString::GString(GString *str1, GString *str2) { GString *GString::fromInt(int x) { char buf[24]; // enough space for 64-bit ints plus a little extra - char *p; + const char *p; int len; formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len); @@ -205,6 +215,9 @@ GString *GString::clear() { } GString *GString::append(char c) { + if (length > INT_MAX - 1) { + gMemError("Integer overflow in GString::append()"); + } resize(length + 1); s[length++] = c; s[length] = '\0'; @@ -214,6 +227,9 @@ GString *GString::append(char c) { GString *GString::append(GString *str) { int n = str->getLength(); + if (length > INT_MAX - n) { + gMemError("Integer overflow in GString::append()"); + } resize(length + n); memcpy(s + length, str->getCString(), n + 1); length += n; @@ -223,6 +239,9 @@ GString *GString::append(GString *str) { GString *GString::append(const char *str) { int n = (int)strlen(str); + if (length > INT_MAX - n) { + gMemError("Integer overflow in GString::append()"); + } resize(length + n); memcpy(s + length, str, n + 1); length += n; @@ -230,6 +249,9 @@ GString *GString::append(const char *str) { } GString *GString::append(const char *str, int lengthA) { + if (lengthA < 0 || length > INT_MAX - lengthA) { + gMemError("Integer overflow in GString::append()"); + } resize(length + lengthA); memcpy(s + length, str, lengthA); length += lengthA; @@ -256,7 +278,7 @@ GString *GString::appendfv(const char *fmt, va_list argList) { char buf[65]; int len, i; const char *p0, *p1; - char *str; + const char *str; argsLen = 0; argsSize = 8; @@ -491,13 +513,23 @@ GString *GString::appendfv(const char *fmt, va_list argList) { reverseAlign = !reverseAlign; break; case fmtString: - str = arg.s; - len = (int)strlen(str); + if (arg.s) { + str = arg.s; + len = (int)strlen(str); + } else { + str = "(null)"; + len = 6; + } reverseAlign = !reverseAlign; break; case fmtGString: - str = arg.gs->getCString(); - len = arg.gs->getLength(); + if (arg.gs) { + str = arg.gs->getCString(); + len = arg.gs->getLength(); + } else { + str = "(null)"; + len = 6; + } reverseAlign = !reverseAlign; break; case fmtSpace: @@ -542,11 +574,11 @@ GString *GString::appendfv(const char *fmt, va_list argList) { #ifdef LLONG_MAX void GString::formatInt(long long x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len) { + const char **p, int *len) { #else void GString::formatInt(long x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len) { + const char **p, int *len) { #endif static char vals[17] = "0123456789abcdef"; GBool neg; @@ -580,11 +612,11 @@ void GString::formatInt(long x, char *buf, int bufSize, #ifdef ULLONG_MAX void GString::formatUInt(unsigned long long x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len) { + const char **p, int *len) { #else void GString::formatUInt(Gulong x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len) { + const char **p, int *len) { #endif static char vals[17] = "0123456789abcdef"; int i, j; @@ -608,7 +640,7 @@ void GString::formatUInt(Gulong x, char *buf, int bufSize, } void GString::formatDouble(double x, char *buf, int bufSize, int prec, - GBool trim, char **p, int *len) { + GBool trim, const char **p, int *len) { GBool neg, started; double x2; int d, i, j; @@ -649,6 +681,9 @@ void GString::formatDouble(double x, char *buf, int bufSize, int prec, GString *GString::insert(int i, char c) { int j; + if (length > INT_MAX - 1) { + gMemError("Integer overflow in GString::insert()"); + } resize(length + 1); for (j = length + 1; j > i; --j) s[j] = s[j-1]; @@ -661,6 +696,9 @@ GString *GString::insert(int i, GString *str) { int n = str->getLength(); int j; + if (length > INT_MAX - n) { + gMemError("Integer overflow in GString::insert()"); + } resize(length + n); for (j = length; j >= i; --j) s[j+n] = s[j]; @@ -673,6 +711,9 @@ GString *GString::insert(int i, const char *str) { int n = (int)strlen(str); int j; + if (length > INT_MAX - n) { + gMemError("Integer overflow in GString::insert()"); + } resize(length + n); for (j = length; j >= i; --j) s[j+n] = s[j]; @@ -684,6 +725,9 @@ GString *GString::insert(int i, const char *str) { GString *GString::insert(int i, const char *str, int lengthA) { int j; + if (lengthA < 0 || length > INT_MAX - lengthA) { + gMemError("Integer overflow in GString::insert()"); + } resize(length + lengthA); for (j = length; j >= i; --j) s[j+lengthA] = s[j]; @@ -695,7 +739,7 @@ GString *GString::insert(int i, const char *str, int lengthA) { GString *GString::del(int i, int n) { int j; - if (i >= 0 && n > 0 && i + n > 0) { + if (i >= 0 && n > 0 && i <= INT_MAX - n) { if (i + n > length) { n = length - i; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/GString.h b/Build/source/libs/xpdf/xpdf-3.04/goo/GString.h index 611efdaa9d1..6b342f85ec7 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/GString.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/GString.h @@ -129,23 +129,23 @@ private: #ifdef LLONG_MAX static void formatInt(long long x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len); + const char **p, int *len); #else static void formatInt(long x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len); + const char **p, int *len); #endif #ifdef ULLONG_MAX static void formatUInt(unsigned long long x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len); + const char **p, int *len); #else static void formatUInt(Gulong x, char *buf, int bufSize, GBool zeroFill, int width, int base, - char **p, int *len); + const char **p, int *len); #endif static void formatDouble(double x, char *buf, int bufSize, int prec, - GBool trim, char **p, int *len); + GBool trim, const char **p, int *len); }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/Makefile.dep b/Build/source/libs/xpdf/xpdf-3.04/goo/Makefile.dep index e69de29bb2d..e69de29bb2d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/Makefile.dep +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/Makefile.in b/Build/source/libs/xpdf/xpdf-3.04/goo/Makefile.in index 0baddbb0489..f61d4030f60 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/Makefile.in +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/Makefile.in @@ -11,8 +11,8 @@ SHELL = /bin/sh srcdir = @srcdir@ VPATH = @srcdir@ -CFLAGS = @CFLAGS@ @DEFS@ -I.. -I$(srcdir) -CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir) +CFLAGS = @CFLAGS@ @DEFS@ -I.. -I$(srcdir)/.. -I$(srcdir) +CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir)/.. -I$(srcdir) CC = @CC@ CXX = @CXX@ @@ -68,4 +68,4 @@ depend: $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep $(CC) $(CFLAGS) -MM $(C_SRC) >>Makefile.dep -include Makefile.dep +-include Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/gfile.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/gfile.cc index a76b3ff2de0..c2ce80508de 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/gfile.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/gfile.cc @@ -13,8 +13,9 @@ #include <aconf.h> -#ifdef WIN32 +#ifdef _WIN32 # include <time.h> +# include <direct.h> #else # if defined(MACOS) # include <sys/stat.h> @@ -32,7 +33,7 @@ # if defined(VMS) && (__DECCXX_VER < 50200000) # include <unixlib.h> # endif -#endif // WIN32 +#endif // _WIN32 #include "GString.h" #include "gfile.h" @@ -49,7 +50,7 @@ GString *getHomeDir() { //---------- VMS ---------- return new GString("SYS$LOGIN:"); -#elif defined(__EMX__) || defined(WIN32) +#elif defined(__EMX__) || defined(_WIN32) //---------- OS/2+EMX and Win32 ---------- char *s; GString *ret; @@ -95,8 +96,8 @@ GString *getCurrentDir() { #if defined(__EMX__) if (_getcwd2(buf, sizeof(buf))) -#elif defined(WIN32) - if (GetCurrentDirectory(sizeof(buf), buf)) +#elif defined(_WIN32) + if (GetCurrentDirectoryA(sizeof(buf), buf)) #elif defined(ACORN) if (strcpy(buf, "@")) #elif defined(MACOS) @@ -149,7 +150,7 @@ GString *appendToPath(GString *path, const char *fileName) { } return path; -#elif defined(WIN32) +#elif defined(_WIN32) //---------- Win32 ---------- GString *tmp; char buf[256]; @@ -158,7 +159,7 @@ GString *appendToPath(GString *path, const char *fileName) { tmp = new GString(path); tmp->append('/'); tmp->append(fileName); - GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp); + GetFullPathNameA(tmp->getCString(), sizeof(buf), buf, &fp); delete tmp; path->clear(); path->append(buf); @@ -285,7 +286,7 @@ GString *grabPath(char *fileName) { return new GString(fileName, p + 1 - fileName); return new GString(); -#elif defined(__EMX__) || defined(WIN32) +#elif defined(__EMX__) || defined(_WIN32) //---------- OS/2+EMX and Win32 ---------- char *p; @@ -329,7 +330,7 @@ GBool isAbsolutePath(char *path) { return strchr(path, ':') || (path[0] == '[' && path[1] != '.' && path[1] != '-'); -#elif defined(__EMX__) || defined(WIN32) +#elif defined(__EMX__) || defined(_WIN32) //---------- OS/2+EMX and Win32 ---------- return path[0] == '/' || path[0] == '\\' || path[1] == ':'; @@ -359,13 +360,13 @@ GString *makePathAbsolute(GString *path) { } return path; -#elif defined(WIN32) +#elif defined(_WIN32) //---------- Win32 ---------- char buf[_MAX_PATH]; char *fp; buf[0] = '\0'; - if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) { + if (!GetFullPathNameA(path->getCString(), _MAX_PATH, buf, &fp)) { path->clear(); return path; } @@ -430,7 +431,7 @@ GString *makePathAbsolute(GString *path) { } time_t getModTime(char *fileName) { -#ifdef WIN32 +#ifdef _WIN32 //~ should implement this, but it's (currently) only used in xpdf return 0; #else @@ -444,8 +445,9 @@ time_t getModTime(char *fileName) { } #ifndef PDF_PARSER_ONLY -GBool openTempFile(GString **name, FILE **f, const char *mode, char *ext) { -#if defined(WIN32) +GBool openTempFile(GString **name, FILE **f, + const char *mode, const char *ext) { +#if defined(_WIN32) //---------- Win32 ---------- char *tempDir; GString *s, *s2; @@ -555,6 +557,14 @@ GBool openTempFile(GString **name, FILE **f, const char *mode, char *ext) { } #endif +GBool createDir(char *path, int mode) { +#ifdef _WIN32 + return !mkdir(path); +#else + return !mkdir(path, mode); +#endif +} + GBool executeCommand(char *cmd) { #ifdef VMS return system(cmd) ? gTrue : gFalse; @@ -563,7 +573,7 @@ GBool executeCommand(char *cmd) { #endif } -#ifdef WIN32 +#ifdef _WIN32 GString *fileNameToUTF8(char *path) { GString *s; char *p; @@ -602,7 +612,7 @@ GString *fileNameToUTF8(wchar_t *path) { #endif FILE *openFile(const char *path, const char *mode) { -#ifdef WIN32 +#ifdef _WIN32 OSVERSIONINFO version; wchar_t wPath[_MAX_PATH + 1]; char nPath[_MAX_PATH + 1]; @@ -693,6 +703,30 @@ char *getLine(char *buf, int size, FILE *f) { return buf; } +int gfseek(FILE *f, GFileOffset offset, int whence) { +#if HAVE_FSEEKO + return fseeko(f, offset, whence); +#elif HAVE_FSEEK64 + return fseek64(f, offset, whence); +#elif HAVE_FSEEKI64 + return _fseeki64(f, offset, whence); +#else + return fseek(f, offset, whence); +#endif +} + +GFileOffset gftell(FILE *f) { +#if HAVE_FSEEKO + return ftello(f); +#elif HAVE_FSEEK64 + return ftell64(f); +#elif HAVE_FSEEKI64 + return _ftelli64(f); +#else + return ftell(f); +#endif +} + //------------------------------------------------------------------------ // GDir and GDirEntry //------------------------------------------------------------------------ @@ -700,7 +734,7 @@ char *getLine(char *buf, int size, FILE *f) { GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) { #ifdef VMS char *p; -#elif defined(WIN32) +#elif defined(_WIN32) int fa; GString *s; #elif defined(ACORN) @@ -720,8 +754,8 @@ GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) { #else s = new GString(dirPath); appendToPath(s, nameA); -#ifdef WIN32 - fa = GetFileAttributes(s->getCString()); +#ifdef _WIN32 + fa = GetFileAttributesA(s->getCString()); dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY)); #else if (stat(s->getCString(), &st) == 0) @@ -739,15 +773,16 @@ GDirEntry::~GDirEntry() { GDir::GDir(char *name, GBool doStatA) { path = new GString(name); doStat = doStatA; -#if defined(WIN32) +#if defined(_WIN32) GString *tmp; tmp = path->copy(); tmp->append("/*.*"); - hnd = FindFirstFile(tmp->getCString(), &ffd); + hnd = FindFirstFileA(tmp->getCString(), &ffd); delete tmp; #elif defined(ACORN) #elif defined(MACOS) +#elif defined(ANDROID) #else dir = opendir(name); #ifdef VMS @@ -758,13 +793,14 @@ GDir::GDir(char *name, GBool doStatA) { GDir::~GDir() { delete path; -#if defined(WIN32) +#if defined(_WIN32) if (hnd) { FindClose(hnd); hnd = NULL; } #elif defined(ACORN) #elif defined(MACOS) +#elif defined(ANDROID) #else if (dir) closedir(dir); @@ -774,10 +810,10 @@ GDir::~GDir() { GDirEntry *GDir::getNextEntry() { GDirEntry *e; -#if defined(WIN32) +#if defined(_WIN32) if (hnd) { e = new GDirEntry(path->getCString(), ffd.cFileName, doStat); - if (hnd && !FindNextFile(hnd, &ffd)) { + if (hnd && !FindNextFileA(hnd, &ffd)) { FindClose(hnd); hnd = NULL; } @@ -786,6 +822,7 @@ GDirEntry *GDir::getNextEntry() { } #elif defined(ACORN) #elif defined(MACOS) +#elif defined(ANDROID) #elif defined(VMS) struct dirent *ent; e = NULL; @@ -818,17 +855,18 @@ GDirEntry *GDir::getNextEntry() { } void GDir::rewind() { -#ifdef WIN32 +#ifdef _WIN32 GString *tmp; if (hnd) FindClose(hnd); tmp = path->copy(); tmp->append("/*.*"); - hnd = FindFirstFile(tmp->getCString(), &ffd); + hnd = FindFirstFileA(tmp->getCString(), &ffd); delete tmp; #elif defined(ACORN) #elif defined(MACOS) +#elif defined(ANDROID) #else if (dir) rewinddir(dir); diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/gfile.h b/Build/source/libs/xpdf/xpdf-3.04/goo/gfile.h index 4f8c65fd620..5b171e62089 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/gfile.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/gfile.h @@ -14,7 +14,7 @@ #include <stdio.h> #include <stdlib.h> #include <stddef.h> -#if defined(WIN32) +#if defined(_WIN32) # include <sys/stat.h> # ifdef FPTEX # include <win32lib.h> @@ -24,6 +24,7 @@ #elif defined(ACORN) #elif defined(MACOS) # include <ctime.h> +#elif defined(ANDROID) #else # include <unistd.h> # include <sys/types.h> @@ -84,12 +85,15 @@ extern time_t getModTime(char *fileName); // reopened later for reading, but not for writing. The <mode> string // should be "w" or "wb". Returns true on success. extern GBool openTempFile(GString **name, FILE **f, - const char *mode, char *ext); + const char *mode, const char *ext); + +// Create a directory. Returns true on success. +extern GBool createDir(char *path, int mode); // Execute <command>. Returns true on success. extern GBool executeCommand(char *cmd); -#ifdef WIN32 +#ifdef _WIN32 // Convert a file name from Latin-1 to UTF-8. extern GString *fileNameToUTF8(char *path); @@ -106,6 +110,28 @@ extern FILE *openFile(const char *path, const char *mode); // conventions. extern char *getLine(char *buf, int size, FILE *f); +// Type used by gfseek/gftell for file offsets. This will be 64 bits +// on systems that support it. +#if HAVE_FSEEKO +typedef off_t GFileOffset; +#define GFILEOFFSET_MAX 0x7fffffffffffffffLL +#elif HAVE_FSEEK64 +typedef long long GFileOffset; +#define GFILEOFFSET_MAX 0x7fffffffffffffffLL +#elif HAVE_FSEEKI64 +typedef __int64 GFileOffset; +#define GFILEOFFSET_MAX 0x7fffffffffffffffLL +#else +typedef long GFileOffset; +#define GFILEOFFSET_MAX LONG_MAX +#endif + +// Like fseek, but uses a 64-bit file offset if available. +extern int gfseek(FILE *f, GFileOffset offset, int whence); + +// Like ftell, but returns a 64-bit file offset if available. +extern GFileOffset gftell(FILE *f); + //------------------------------------------------------------------------ // GDir and GDirEntry //------------------------------------------------------------------------ @@ -136,11 +162,12 @@ private: GString *path; // directory path GBool doStat; // call stat() for each entry? -#if defined(WIN32) - WIN32_FIND_DATA ffd; +#if defined(_WIN32) + WIN32_FIND_DATAA ffd; HANDLE hnd; #elif defined(ACORN) #elif defined(MACOS) +#elif defined(ANDROID) #else DIR *dir; // the DIR structure from opendir() #ifdef VMS diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/gmem.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/gmem.cc index af85dd012f0..6fd51364071 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/gmem.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/gmem.cc @@ -44,6 +44,7 @@ static GMemHdr *gMemTail = NULL; static int gMemIndex = 0; static int gMemAlloc = 0; static int gMemInUse = 0; +static int gMaxMemInUse = 0; #endif /* DEBUG_MEM */ @@ -56,24 +57,14 @@ void *gmalloc(int size) GMEM_EXCEP { unsigned long *trl, *p; if (size < 0) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Invalid memory allocation size\n"); - exit(1); -#endif + gMemError("Invalid memory allocation size"); } if (size == 0) { return NULL; } size1 = gMemDataSize(size); if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Out of memory\n"); - exit(1); -#endif + gMemError("Out of memory"); } hdr = (GMemHdr *)mem; data = (void *)(mem + gMemHdrSize); @@ -92,6 +83,9 @@ void *gmalloc(int size) GMEM_EXCEP { hdr->next = NULL; ++gMemAlloc; gMemInUse += size; + if (gMemInUse > gMaxMemInUse) { + gMaxMemInUse = gMemInUse; + } for (p = (unsigned long *)data; p <= trl; ++p) { *p = gMemDeadVal; } @@ -100,23 +94,13 @@ void *gmalloc(int size) GMEM_EXCEP { void *p; if (size < 0) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Invalid memory allocation size\n"); - exit(1); -#endif + gMemError("Invalid memory allocation size"); } if (size == 0) { return NULL; } if (!(p = malloc(size))) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Out of memory\n"); - exit(1); -#endif + gMemError("Out of memory"); } return p; #endif @@ -129,12 +113,7 @@ void *grealloc(void *p, int size) GMEM_EXCEP { int oldSize; if (size < 0) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Invalid memory allocation size\n"); - exit(1); -#endif + gMemError("Invalid memory allocation size"); } if (size == 0) { if (p) { @@ -156,12 +135,7 @@ void *grealloc(void *p, int size) GMEM_EXCEP { void *q; if (size < 0) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Invalid memory allocation size\n"); - exit(1); -#endif + gMemError("Invalid memory allocation size"); } if (size == 0) { if (p) { @@ -175,12 +149,7 @@ void *grealloc(void *p, int size) GMEM_EXCEP { q = malloc(size); } if (!q) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Out of memory\n"); - exit(1); -#endif + gMemError("Out of memory"); } return q; #endif @@ -194,12 +163,7 @@ void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { } n = nObjs * objSize; if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Bogus memory allocation size\n"); - exit(1); -#endif + gMemError("Bogus memory allocation size"); } return gmalloc(n); } @@ -215,12 +179,7 @@ void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { } n = nObjs * objSize; if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { -#if USE_EXCEPTIONS - throw GMemException(); -#else - fprintf(stderr, "Bogus memory allocation size\n"); - exit(1); -#endif + gMemError("Bogus memory allocation size"); } return grealloc(p, n); } @@ -269,11 +228,21 @@ void gfree(void *p) { #endif } +void gMemError(const char *msg) GMEM_EXCEP { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "%s\n", msg); + exit(1); +#endif +} + #ifdef DEBUG_MEM void gMemReport(FILE *f) { GMemHdr *p; fprintf(f, "%d memory allocations in all\n", gMemIndex); + fprintf(f, "maximum memory in use: %d bytes\n", gMaxMemInUse); if (gMemAlloc > 0) { fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc); fprintf(f, " index size\n"); diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/gmem.h b/Build/source/libs/xpdf/xpdf-3.04/goo/gmem.h index de324531ecb..bfa9658e451 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/gmem.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/gmem.h @@ -58,6 +58,11 @@ extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP; */ extern void gfree(void *p); +/* + * Report a memory error. + */ +extern void gMemError(const char *msg) GMEM_EXCEP; + #ifdef DEBUG_MEM /* * Report on unfreed memory. diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/gmempp.cc b/Build/source/libs/xpdf/xpdf-3.04/goo/gmempp.cc index b1ee970d38a..b1ee970d38a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/gmempp.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/gmempp.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/gtypes.h b/Build/source/libs/xpdf/xpdf-3.04/goo/gtypes.h index 9f64f57d4a1..9f64f57d4a1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/gtypes.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/gtypes.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/parseargs.c b/Build/source/libs/xpdf/xpdf-3.04/goo/parseargs.c index fdefa6c3351..fdefa6c3351 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/parseargs.c +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/parseargs.c diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/parseargs.h b/Build/source/libs/xpdf/xpdf-3.04/goo/parseargs.h index b4daa3f29fc..b4daa3f29fc 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/parseargs.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/parseargs.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_directory.c b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_directory.c index 92d94932099..92d94932099 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_directory.c +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_directory.c diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_dirent.h b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_dirent.h index 13e21a072e3..13e21a072e3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_dirent.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_dirent.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_make.com b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_make.com index 676643fcc73..676643fcc73 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_make.com +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_make.com diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_sys_dirent.h b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_sys_dirent.h index 2c20d714803..2c20d714803 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_sys_dirent.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_sys_dirent.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_unix_time.h b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_unix_time.h index f8e83825b9e..f8e83825b9e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_unix_time.h +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_unix_time.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_unix_times.c b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_unix_times.c index 004c0d04b29..004c0d04b29 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_unix_times.c +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_unix_times.c diff --git a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_unlink.c b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_unlink.c index e2cf687de4b..e2cf687de4b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/goo/vms_unlink.c +++ b/Build/source/libs/xpdf/xpdf-3.04/goo/vms_unlink.c diff --git a/Build/source/libs/xpdf/xpdf-3.03/misc/hello.pdf b/Build/source/libs/xpdf/xpdf-3.04/misc/hello.pdf Binary files differindex d097335982d..d097335982d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/misc/hello.pdf +++ b/Build/source/libs/xpdf/xpdf-3.04/misc/hello.pdf diff --git a/Build/source/libs/xpdf/xpdf-3.03/misc/xpdf.dt b/Build/source/libs/xpdf/xpdf-3.04/misc/xpdf.dt index d3d41b7c897..d3d41b7c897 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/misc/xpdf.dt +++ b/Build/source/libs/xpdf/xpdf-3.04/misc/xpdf.dt diff --git a/Build/source/libs/xpdf/xpdf-3.04/ms_make.bat b/Build/source/libs/xpdf/xpdf-3.04/ms_make.bat new file mode 100755 index 00000000000..684b26fd1ce --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/ms_make.bat @@ -0,0 +1,134 @@ +set CC=cl
+set CXX=cl
+set FT2DIR=..\freetype-2.5.3
+rem *** Set PNGDIR and ZLIBDIR to build pdftohtml
+rem set PNGDIR=..\libpng-1.5.12
+rem set ZLIBDIR=..\zlib-1.2.7
+set CFLAGS=/I.. /I..\goo /I..\fofi /I..\splash /O2 /nologo /I%FT2DIR%\include
+set CXXFLAGS=%CFLAGS% /TP
+set LIBPROG=lib
+set LINKFLAGS=/MT /nologo
+
+copy aconf-win32.h aconf.h
+
+cd goo
+%CXX% %CXXFLAGS% /c GHash.cc
+%CXX% %CXXFLAGS% /c GList.cc
+%CXX% %CXXFLAGS% /c GString.cc
+%CXX% %CXXFLAGS% /c gmem.cc
+%CXX% %CXXFLAGS% /c gmempp.cc
+%CXX% %CXXFLAGS% /c gfile.cc
+%CC% %CFLAGS% /c parseargs.c
+%LIBPROG% /nologo /out:Goo.lib GHash.obj GList.obj GString.obj gmempp.obj gfile.obj gmem.obj parseargs.obj
+
+cd ..\fofi
+%CXX% %CXXFLAGS% /c FoFiBase.cc
+%CXX% %CXXFLAGS% /c FoFiEncodings.cc
+%CXX% %CXXFLAGS% /c FoFiIdentifier.cc
+%CXX% %CXXFLAGS% /c FoFiTrueType.cc
+%CXX% %CXXFLAGS% /c FoFiType1.cc
+%CXX% %CXXFLAGS% /c FoFiType1C.cc
+%LIBPROG% /nologo /out:fofi.lib FoFiBase.obj FoFiEncodings.obj FoFiIdentifier.obj FoFiTrueType.obj FoFiType1.obj FoFiType1C.obj
+
+cd ..\splash
+%CXX% %CXXFLAGS% /c Splash.cc
+%CXX% %CXXFLAGS% /c SplashBitmap.cc
+%CXX% %CXXFLAGS% /c SplashClip.cc
+%CXX% %CXXFLAGS% /c SplashFTFont.cc
+%CXX% %CXXFLAGS% /c SplashFTFontEngine.cc
+%CXX% %CXXFLAGS% /c SplashFTFontFile.cc
+%CXX% %CXXFLAGS% /c SplashFont.cc
+%CXX% %CXXFLAGS% /c SplashFontEngine.cc
+%CXX% %CXXFLAGS% /c SplashFontFile.cc
+%CXX% %CXXFLAGS% /c SplashFontFileID.cc
+%CXX% %CXXFLAGS% /c SplashPath.cc
+%CXX% %CXXFLAGS% /c SplashPattern.cc
+%CXX% %CXXFLAGS% /c SplashScreen.cc
+%CXX% %CXXFLAGS% /c SplashState.cc
+%CXX% %CXXFLAGS% /c SplashXPath.cc
+%CXX% %CXXFLAGS% /c SplashXPathScanner.cc
+%LIBPROG% /nologo /out:splash.lib Splash.obj SplashBitmap.obj SplashClip.obj SplashFTFont.obj SplashFTFontEngine.obj SplashFTFontFile.obj SplashFont.obj SplashFontEngine.obj SplashFontFile.obj SplashFontFileID.obj SplashPath.obj SplashPattern.obj SplashScreen.obj SplashState.obj SplashXPath.obj SplashXPathScanner.obj
+
+cd ..\xpdf
+%CXX% %CXXFLAGS% /c AcroForm.cc
+%CXX% %CXXFLAGS% /c Annot.cc
+%CXX% %CXXFLAGS% /c Array.cc
+%CXX% %CXXFLAGS% /c BuiltinFont.cc
+%CXX% %CXXFLAGS% /c BuiltinFontTables.cc
+%CXX% %CXXFLAGS% /c CMap.cc
+%CXX% %CXXFLAGS% /c Catalog.cc
+%CXX% %CXXFLAGS% /c CharCodeToUnicode.cc
+%CXX% %CXXFLAGS% /c Decrypt.cc
+%CXX% %CXXFLAGS% /c Dict.cc
+%CXX% %CXXFLAGS% /c Error.cc
+%CXX% %CXXFLAGS% /c FontEncodingTables.cc
+%CXX% %CXXFLAGS% /c Form.cc
+%CXX% %CXXFLAGS% /c Function.cc
+%CXX% %CXXFLAGS% /c Gfx.cc
+%CXX% %CXXFLAGS% /c GfxFont.cc
+%CXX% %CXXFLAGS% /c GfxState.cc
+%CXX% %CXXFLAGS% /c GlobalParams.cc
+%CXX% %CXXFLAGS% /c ImageOutputDev.cc
+%CXX% %CXXFLAGS% /c JArithmeticDecoder.cc
+%CXX% %CXXFLAGS% /c JBIG2Stream.cc
+%CXX% %CXXFLAGS% /c JPXStream.cc
+%CXX% %CXXFLAGS% /c Lexer.cc
+%CXX% %CXXFLAGS% /c Link.cc
+%CXX% %CXXFLAGS% /c NameToCharCode.cc
+%CXX% %CXXFLAGS% /c Object.cc
+%CXX% %CXXFLAGS% /c OptionalContent.cc
+%CXX% %CXXFLAGS% /c Outline.cc
+%CXX% %CXXFLAGS% /c OutputDev.cc
+%CXX% %CXXFLAGS% /c PDFDoc.cc
+%CXX% %CXXFLAGS% /c PDFDocEncoding.cc
+%CXX% %CXXFLAGS% /c PSOutputDev.cc
+%CXX% %CXXFLAGS% /c PSTokenizer.cc
+%CXX% %CXXFLAGS% /c Page.cc
+%CXX% %CXXFLAGS% /c Parser.cc
+%CXX% %CXXFLAGS% /c PreScanOutputDev.cc
+%CXX% %CXXFLAGS% /c SecurityHandler.cc
+%CXX% %CXXFLAGS% /c SplashOutputDev.cc
+%CXX% %CXXFLAGS% /c Stream.cc
+%CXX% %CXXFLAGS% /c TextOutputDev.cc
+%CXX% %CXXFLAGS% /c TextString.cc
+%CXX% %CXXFLAGS% /c UnicodeMap.cc
+%CXX% %CXXFLAGS% /c UnicodeTypeTable.cc
+%CXX% %CXXFLAGS% /c XFAForm.cc
+%CXX% %CXXFLAGS% /c XRef.cc
+%CXX% %CXXFLAGS% /c Zoox.cc
+%CXX% %CXXFLAGS% /c pdftops.cc
+%CXX% %CXXFLAGS% /c pdftotext.cc
+%CXX% %CXXFLAGS% /c pdftoppm.cc
+%CXX% %CXXFLAGS% /c pdfinfo.cc
+%CXX% %CXXFLAGS% /c pdffonts.cc
+%CXX% %CXXFLAGS% /c pdfdetach.cc
+%CXX% %CXXFLAGS% /c pdfimages.cc
+
+%CXX% %LINKFLAGS% /Fepdftops.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj PreScanOutputDev.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj TextString.obj UnicodeMap.obj XFAForm.obj XRef.obj Zoox.obj pdftops.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdftotext.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextOutputDev.obj TextString.obj UnicodeMap.obj UnicodeTypeTable.obj XFAForm.obj XRef.obj Zoox.obj pdftotext.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdftoppm.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj TextString.obj UnicodeMap.obj UnicodeTypeTable.obj XFAForm.obj XRef.obj Zoox.obj pdftoppm.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdfinfo.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextString.obj UnicodeMap.obj XFAForm.obj XRef.obj Zoox.obj pdfinfo.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdffonts.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextString.obj UnicodeMap.obj XFAForm.obj XRef.obj Zoox.obj pdffonts.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdfdetach.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextString.obj UnicodeMap.obj XFAForm.obj XRef.obj Zoox.obj pdfdetach.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+%CXX% %LINKFLAGS% /Fepdfimages.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj ImageOutputDev.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextString.obj UnicodeMap.obj XFAForm.obj XRef.obj Zoox.obj pdfimages.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+if x%PNGDIR% == x goto noHTML
+if x%ZLIBDIR% == x goto noHTML
+
+%CXX% %CXXFLAGS% /I%PNGDIR% /I%ZLIBDIR% /c pdftopng.cc
+%CXX% %LINKFLAGS% /Fepdftopng.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj TextString.obj UnicodeMap.obj UnicodeTypeTable.obj XFAForm.obj XRef.obj Zoox.obj pdftopng.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib %PNGDIR%\libpng.lib %ZLIBDIR%\zlib.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+echo "building pdftohtml"
+%CXX% %CXXFLAGS% /I%PNGDIR% /I%ZLIBDIR% /c HTMLGen.cc
+%CXX% %CXXFLAGS% /I%PNGDIR% /I%ZLIBDIR% /c pdftohtml.cc
+%CXX% %LINKFLAGS% /Fepdftohtml.exe AcroForm.obj Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Form.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj HTMLGen.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj OptionalContent.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj TextOutputDev.obj TextString.obj UnicodeMap.obj UnicodeTypeTable.obj XFAForm.obj XRef.obj Zoox.obj pdftohtml.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib %PNGDIR%\libpng.lib %ZLIBDIR%\zlib.lib shell32.lib user32.lib gdi32.lib advapi32.lib
+
+:noHTML
+
+cd ..
diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/Makefile.dep b/Build/source/libs/xpdf/xpdf-3.04/splash/Makefile.dep index e69de29bb2d..e69de29bb2d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/Makefile.dep +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/Makefile.in b/Build/source/libs/xpdf/xpdf-3.04/splash/Makefile.in index 66c449b3985..6479b1543ee 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/Makefile.in +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/Makefile.in @@ -16,7 +16,7 @@ GOOLIBDIR = ../goo FOFISRCDIR = $(srcdir)/../fofi FOFILIBDIR = ../fofi -CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(GOOSRCDIR) -I$(FOFISRCDIR) -I$(srcdir) @t1_CFLAGS@ @freetype2_CFLAGS@ +CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir)/.. -I$(GOOSRCDIR) -I$(FOFISRCDIR) -I$(srcdir) @freetype2_CFLAGS@ CXX = @CXX@ AR = @AR@ @@ -48,9 +48,6 @@ CXX_SRC = \ $(srcdir)/SplashPattern.cc \ $(srcdir)/SplashScreen.cc \ $(srcdir)/SplashState.cc \ - $(srcdir)/SplashT1Font.cc \ - $(srcdir)/SplashT1FontEngine.cc \ - $(srcdir)/SplashT1FontFile.cc \ $(srcdir)/SplashXPath.cc \ $(srcdir)/SplashXPathScanner.cc @@ -75,9 +72,6 @@ SPLASH_OBJS = \ SplashPattern.o \ SplashScreen.o \ SplashState.o \ - SplashT1Font.o \ - SplashT1FontEngine.o \ - SplashT1FontFile.o \ SplashXPath.o \ SplashXPathScanner.o @@ -96,4 +90,4 @@ clean: depend: $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep -include Makefile.dep +-include Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/Splash.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/Splash.cc index 879a4f223b8..d9035b37aa9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/Splash.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/Splash.cc @@ -2,6 +2,8 @@ // // Splash.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -29,7 +31,7 @@ //------------------------------------------------------------------------ -#define splashAAGamma 1.5 +#define splashAAGamma 0.67 // distance of Bezier control point from center for circle approximation // = (4 * (sqrt(2) - 1) / 3) * r @@ -46,41 +48,12 @@ static inline Guchar clip255(int x) { return x < 0 ? 0 : x > 255 ? 255 : x; } -// The PDF spec says that all pixels whose *centers* lie within the -// image target region get painted, so we want to round n+0.5 down to -// n. But this causes problems, e.g., with PDF files that fill a -// rectangle with black and then draw an image to the exact same -// rectangle, so we instead use the fill scan conversion rule. -// However, the correct rule works better for glyphs, so we also -// provide that option in fillImageMask. -#if 0 -static inline int imgCoordMungeLower(SplashCoord x) { - return splashCeil(x + 0.5) - 1; -} -static inline int imgCoordMungeUpper(SplashCoord x) { - return splashCeil(x + 0.5) - 1; -} -#else -static inline int imgCoordMungeLower(SplashCoord x) { - return splashFloor(x); -} -static inline int imgCoordMungeUpper(SplashCoord x) { - return splashFloor(x) + 1; -} -static inline int imgCoordMungeLowerC(SplashCoord x, GBool glyphMode) { - return glyphMode ? (splashCeil(x + 0.5) - 1) : splashFloor(x); -} -static inline int imgCoordMungeUpperC(SplashCoord x, GBool glyphMode) { - return glyphMode ? (splashCeil(x + 0.5) - 1) : (splashFloor(x) + 1); -} -#endif - // Used by drawImage and fillImageMask to divide the target // quadrilateral into sections. struct ImageSection { int y0, y1; // actual y range int ia0, ia1; // vertex indices for edge A - int ib0, ib1; // vertex indices for edge A + int ib0, ib1; // vertex indices for edge B SplashCoord xa0, ya0, xa1, ya1; // edge A SplashCoord dxdya; // slope of edge A SplashCoord xb0, yb0, xb1, yb1; // edge B @@ -94,41 +67,26 @@ struct ImageSection { #define splashPipeMaxStages 9 struct SplashPipe { - // pixel coordinates - int x, y; - // source pattern SplashPattern *pattern; // source alpha and color Guchar aInput; - GBool usesShape; - SplashColorPtr cSrc; SplashColor cSrcVal; - // non-isolated group alpha0 - Guchar *alpha0Ptr; - - // soft mask - SplashColorPtr softMaskPtr; - - // destination alpha and color - SplashColorPtr destColorPtr; - int destColorMask; - Guchar *destAlphaPtr; - - // shape - Guchar shape; - - // result alpha and color + // special cases and result color GBool noTransparency; + GBool shapeOnly; SplashPipeResultColorCtrl resultColorCtrl; // non-isolated group correction + // (this is only used when Splash::composite() is called to composite + // a non-isolated group onto the backdrop) GBool nonIsolatedGroup; // the "run" function - void (Splash::*run)(SplashPipe *pipe); + void (Splash::*run)(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); }; SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = { @@ -208,36 +166,37 @@ inline void Splash::updateModY(int y) { // pipeline //------------------------------------------------------------------------ -inline void Splash::pipeInit(SplashPipe *pipe, int x, int y, - SplashPattern *pattern, SplashColorPtr cSrc, +inline void Splash::pipeInit(SplashPipe *pipe, SplashPattern *pattern, Guchar aInput, GBool usesShape, GBool nonIsolatedGroup) { - pipeSetXY(pipe, x, y); pipe->pattern = NULL; // source color - if (pattern) { - if (pattern->isStatic()) { - pattern->getColor(x, y, pipe->cSrcVal); - } else { - pipe->pattern = pattern; - } - pipe->cSrc = pipe->cSrcVal; + if (pattern && pattern->isStatic()) { + pattern->getColor(0, 0, pipe->cSrcVal); + pipe->pattern = NULL; } else { - pipe->cSrc = cSrc; + pipe->pattern = pattern; } // source alpha pipe->aInput = aInput; - pipe->usesShape = usesShape; - // result alpha - if (aInput == 255 && !state->softMask && !usesShape && - !state->inNonIsolatedGroup && !nonIsolatedGroup) { - pipe->noTransparency = gTrue; - } else { - pipe->noTransparency = gFalse; - } + // special cases + pipe->noTransparency = aInput == 255 && + !state->softMask && + !usesShape && + !state->inNonIsolatedGroup && + !state->inKnockoutGroup && + !nonIsolatedGroup && + state->overprintMask == 0xffffffff; + pipe->shapeOnly = aInput == 255 && + !state->softMask && + usesShape && + !state->inNonIsolatedGroup && + !state->inKnockoutGroup && + !nonIsolatedGroup && + state->overprintMask == 0xffffffff; // result color if (pipe->noTransparency) { @@ -255,33 +214,48 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y, // select the 'run' function pipe->run = &Splash::pipeRun; if (!pipe->pattern && pipe->noTransparency && !state->blendFunc) { - if (bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) { + if (bitmap->mode == splashModeMono1 && !bitmap->alpha) { pipe->run = &Splash::pipeRunSimpleMono1; - } else if (bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeMono8 && bitmap->alpha) { pipe->run = &Splash::pipeRunSimpleMono8; - } else if (bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeRGB8 && bitmap->alpha) { pipe->run = &Splash::pipeRunSimpleRGB8; - } else if (bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeBGR8 && bitmap->alpha) { pipe->run = &Splash::pipeRunSimpleBGR8; #if SPLASH_CMYK - } else if (bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeCMYK8 && bitmap->alpha) { pipe->run = &Splash::pipeRunSimpleCMYK8; #endif } + } else if (!pipe->pattern && pipe->shapeOnly && !state->blendFunc) { + if (bitmap->mode == splashModeMono1 && !bitmap->alpha) { + pipe->run = &Splash::pipeRunShapeMono1; + } else if (bitmap->mode == splashModeMono8 && bitmap->alpha) { + pipe->run = &Splash::pipeRunShapeMono8; + } else if (bitmap->mode == splashModeRGB8 && bitmap->alpha) { + pipe->run = &Splash::pipeRunShapeRGB8; + } else if (bitmap->mode == splashModeBGR8 && bitmap->alpha) { + pipe->run = &Splash::pipeRunShapeBGR8; +#if SPLASH_CMYK + } else if (bitmap->mode == splashModeCMYK8 && bitmap->alpha) { + pipe->run = &Splash::pipeRunShapeCMYK8; +#endif + } } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask && - pipe->usesShape && - !(state->inNonIsolatedGroup && alpha0Bitmap->alpha) && + usesShape && + !(state->inNonIsolatedGroup && groupBackBitmap->alpha) && + !state->inKnockoutGroup && !state->blendFunc && !pipe->nonIsolatedGroup) { - if (bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) { + if (bitmap->mode == splashModeMono1 && !bitmap->alpha) { pipe->run = &Splash::pipeRunAAMono1; - } else if (bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeMono8 && bitmap->alpha) { pipe->run = &Splash::pipeRunAAMono8; - } else if (bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeRGB8 && bitmap->alpha) { pipe->run = &Splash::pipeRunAARGB8; - } else if (bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeBGR8 && bitmap->alpha) { pipe->run = &Splash::pipeRunAABGR8; #if SPLASH_CMYK - } else if (bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) { + } else if (bitmap->mode == splashModeCMYK8 && bitmap->alpha) { pipe->run = &Splash::pipeRunAACMYK8; #endif } @@ -289,932 +263,1654 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y, } // general case -void Splash::pipeRun(SplashPipe *pipe) { - Guchar aSrc, aDest, alphaI, alphaIm1, alpha0, aResult; - SplashColor cSrcNonIso, cDest, cBlend; - SplashColorPtr cSrc; - Guchar cResult0, cResult1, cResult2, cResult3; - int t; +void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar *shapePtr2; + Guchar shape, aSrc, aDest, alphaI, alphaIm1, alpha0, aResult; + SplashColor cSrc, cDest, cBlend; + Guchar shapeVal, cResult0, cResult1, cResult2, cResult3; + int cSrcStride, shapeStride, x, lastX, t, i; + SplashColorPtr destColorPtr; + Guchar destColorMask; + Guchar *destAlphaPtr; + SplashColorPtr color0Ptr; + Guchar color0Mask; + Guchar *alpha0Ptr; + SplashColorPtr softMaskPtr; #if SPLASH_CMYK SplashColor cSrc2, cDest2; #endif - //----- source color + if (cSrcPtr && !pipe->pattern) { + cSrcStride = bitmapComps; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } - // static pattern: handled in pipeInit - // fixed color: handled in pipeInit + if (shapePtr) { + shapePtr2 = shapePtr; + shapeStride = 1; + for (; x0 <= x1; ++x0) { + if (*shapePtr2) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr2; + } + } else { + shapeVal = 0xff; + shapePtr2 = &shapeVal; + shapeStride = 0; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; - // dynamic pattern - if (pipe->pattern) { - pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal); + if (bitmap->mode == splashModeMono1) { + destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; + destColorMask = 0x80 >> (x0 & 7); + } else { + destColorPtr = &bitmap->data[y * bitmap->rowSize + x0 * bitmapComps]; + destColorMask = 0; // make gcc happy + } + if (bitmap->alpha) { + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + } else { + destAlphaPtr = NULL; + } + if (state->softMask) { + softMaskPtr = &state->softMask->data[y * state->softMask->rowSize + x0]; + } else { + softMaskPtr = NULL; + } + if (state->inKnockoutGroup) { + if (bitmap->mode == splashModeMono1) { + color0Ptr = + &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize + + ((groupBackX + x0) >> 3)]; + color0Mask = 0x80 >> ((groupBackX + x0) & 7); + } else { + color0Ptr = + &groupBackBitmap->data[(groupBackY + y) * groupBackBitmap->rowSize + + (groupBackX + x0) * bitmapComps]; + color0Mask = 0; // make gcc happy + } + } else { + color0Ptr = NULL; + color0Mask = 0; // make gcc happy + } + if (state->inNonIsolatedGroup && groupBackBitmap->alpha) { + alpha0Ptr = + &groupBackBitmap->alpha[(groupBackY + y) * groupBackBitmap->width + + (groupBackX + x0)]; + } else { + alpha0Ptr = NULL; } - if (pipe->noTransparency && !state->blendFunc) { + for (x = x0; x <= x1; ++x) { - //----- write destination pixel + //----- shape - switch (bitmap->mode) { - case splashModeMono1: - cResult0 = state->grayTransfer[pipe->cSrc[0]]; - if (state->screen->test(pipe->x, pipe->y, cResult0)) { - *pipe->destColorPtr |= pipe->destColorMask; + shape = *shapePtr2; + if (!shape) { + if (bitmap->mode == splashModeMono1) { + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); } else { - *pipe->destColorPtr &= ~pipe->destColorMask; + destColorPtr += bitmapComps; } - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; - } - break; - case splashModeMono8: - *pipe->destColorPtr++ = state->grayTransfer[pipe->cSrc[0]]; - break; - case splashModeRGB8: - *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]]; - *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]]; - *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]]; - break; - case splashModeBGR8: - *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]]; - *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]]; - *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]]; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - if (state->overprintMask & 1) { - pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]]; + if (destAlphaPtr) { + ++destAlphaPtr; } - if (state->overprintMask & 2) { - pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]]; + if (softMaskPtr) { + ++softMaskPtr; } - if (state->overprintMask & 4) { - pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]]; + if (color0Ptr) { + if (bitmap->mode == splashModeMono1) { + color0Ptr += color0Mask & 1; + color0Mask = (color0Mask << 7) | (color0Mask >> 1); + } else { + color0Ptr += bitmapComps; + } } - if (state->overprintMask & 8) { - pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]]; + if (alpha0Ptr) { + ++alpha0Ptr; } - pipe->destColorPtr += 4; - break; -#endif + cSrcPtr += cSrcStride; + shapePtr2 += shapeStride; + continue; } - if (pipe->destAlphaPtr) { - *pipe->destAlphaPtr++ = 255; + lastX = x; + + //----- source color + + // static pattern: handled in pipeInit + // fixed color: handled in pipeInit + + // dynamic pattern + if (pipe->pattern) { + pipe->pattern->getColor(x, y, pipe->cSrcVal); } - } else { + if (pipe->noTransparency && !state->blendFunc) { - //----- read destination pixel + //----- write destination pixel - switch (bitmap->mode) { - case splashModeMono1: - cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00; - break; - case splashModeMono8: - cDest[0] = *pipe->destColorPtr; - break; - case splashModeRGB8: - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - break; - case splashModeBGR8: - cDest[0] = pipe->destColorPtr[2]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[0]; - break; + switch (bitmap->mode) { + case splashModeMono1: + cResult0 = state->grayTransfer[cSrcPtr[0]]; + if (state->screen->test(x, y, cResult0)) { + *destColorPtr |= destColorMask; + } else { + *destColorPtr &= ~destColorMask; + } + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + break; + case splashModeMono8: + *destColorPtr++ = state->grayTransfer[cSrcPtr[0]]; + break; + case splashModeRGB8: + destColorPtr[0] = state->rgbTransferR[cSrcPtr[0]]; + destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]]; + destColorPtr[2] = state->rgbTransferB[cSrcPtr[2]]; + destColorPtr += 3; + break; + case splashModeBGR8: + destColorPtr[0] = state->rgbTransferB[cSrcPtr[2]]; + destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]]; + destColorPtr[2] = state->rgbTransferR[cSrcPtr[0]]; + destColorPtr += 3; + break; #if SPLASH_CMYK - case splashModeCMYK8: - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - cDest[3] = pipe->destColorPtr[3]; - break; + case splashModeCMYK8: + destColorPtr[0] = state->cmykTransferC[cSrcPtr[0]]; + destColorPtr[1] = state->cmykTransferM[cSrcPtr[1]]; + destColorPtr[2] = state->cmykTransferY[cSrcPtr[2]]; + destColorPtr[3] = state->cmykTransferK[cSrcPtr[3]]; + destColorPtr += 4; + break; #endif - } - if (pipe->destAlphaPtr) { - aDest = *pipe->destAlphaPtr; - } else { - aDest = 0xff; - } + } + if (destAlphaPtr) { + *destAlphaPtr++ = 255; + } - //----- source alpha + } else { // if (noTransparency && !blendFunc) + + //----- read destination pixel + // (or backdrop color, for knockout groups) + + if (color0Ptr) { + + switch (bitmap->mode) { + case splashModeMono1: + cDest[0] = (*color0Ptr & color0Mask) ? 0xff : 0x00; + color0Ptr += color0Mask & 1; + color0Mask = (color0Mask << 7) | (color0Mask >> 1); + break; + case splashModeMono8: + cDest[0] = *color0Ptr++; + break; + case splashModeRGB8: + cDest[0] = color0Ptr[0]; + cDest[1] = color0Ptr[1]; + cDest[2] = color0Ptr[2]; + color0Ptr += 3; + break; + case splashModeBGR8: + cDest[2] = color0Ptr[0]; + cDest[1] = color0Ptr[1]; + cDest[0] = color0Ptr[2]; + color0Ptr += 3; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + cDest[0] = color0Ptr[0]; + cDest[1] = color0Ptr[1]; + cDest[2] = color0Ptr[2]; + cDest[3] = color0Ptr[3]; + color0Ptr += 4; + break; +#endif + } - if (state->softMask) { - if (pipe->usesShape) { - aSrc = div255(div255(pipe->aInput * *pipe->softMaskPtr++) * - pipe->shape); } else { - aSrc = div255(pipe->aInput * *pipe->softMaskPtr++); + + switch (bitmap->mode) { + case splashModeMono1: + cDest[0] = (*destColorPtr & destColorMask) ? 0xff : 0x00; + break; + case splashModeMono8: + cDest[0] = *destColorPtr; + break; + case splashModeRGB8: + cDest[0] = destColorPtr[0]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[2]; + break; + case splashModeBGR8: + cDest[0] = destColorPtr[2]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[0]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + cDest[0] = destColorPtr[0]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[2]; + cDest[3] = destColorPtr[3]; + break; +#endif + } + } - } else if (pipe->usesShape) { - aSrc = div255(pipe->aInput * pipe->shape); - } else { - aSrc = pipe->aInput; - } - //----- non-isolated group correction + if (destAlphaPtr) { + aDest = *destAlphaPtr; + } else { + aDest = 0xff; + } + + //----- overprint - if (pipe->nonIsolatedGroup) { - // This path is only used when Splash::composite() is called to - // composite a non-isolated group onto the backdrop. In this - // case, pipe->shape is the source (group) alpha. - if (pipe->shape == 0) { - // this value will be multiplied by zero later, so it doesn't - // matter what we use - cSrc = pipe->cSrc; + for (i = 0; i < bitmapComps; ++i) { +#if SPLASH_CMYK + if (state->overprintMask & (1 << i)) { + cSrc[i] = cSrcPtr[i]; + } else { + cSrc[i] = div255(aDest * cDest[i]); + } +#else + cSrc[i] = cSrcPtr[i]; +#endif + } + + //----- source alpha + + if (softMaskPtr) { + if (shapePtr) { + aSrc = div255(div255(pipe->aInput * *softMaskPtr++) * shape); + } else { + aSrc = div255(pipe->aInput * *softMaskPtr++); + } + } else if (shapePtr) { + aSrc = div255(pipe->aInput * shape); } else { - t = (aDest * 255) / pipe->shape - aDest; + aSrc = pipe->aInput; + } + + //----- non-isolated group correction + + if (pipe->nonIsolatedGroup) { + // 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; switch (bitmap->mode) { #if SPLASH_CMYK case splashModeCMYK8: - cSrcNonIso[3] = clip255(pipe->cSrc[3] + - ((pipe->cSrc[3] - cDest[3]) * t) / 255); + cSrc[3] = clip255(cSrc[3] + ((cSrc[3] - cDest[3]) * t) / 255); #endif case splashModeRGB8: case splashModeBGR8: - cSrcNonIso[2] = clip255(pipe->cSrc[2] + - ((pipe->cSrc[2] - cDest[2]) * t) / 255); - cSrcNonIso[1] = clip255(pipe->cSrc[1] + - ((pipe->cSrc[1] - cDest[1]) * t) / 255); + cSrc[2] = clip255(cSrc[2] + ((cSrc[2] - cDest[2]) * t) / 255); + cSrc[1] = clip255(cSrc[1] + ((cSrc[1] - cDest[1]) * t) / 255); case splashModeMono1: case splashModeMono8: - cSrcNonIso[0] = clip255(pipe->cSrc[0] + - ((pipe->cSrc[0] - cDest[0]) * t) / 255); + cSrc[0] = clip255(cSrc[0] + ((cSrc[0] - cDest[0]) * t) / 255); break; } - cSrc = cSrcNonIso; } - } else { - cSrc = pipe->cSrc; - } - //----- blend function + //----- blend function - if (state->blendFunc) { + if (state->blendFunc) { #if SPLASH_CMYK - if (bitmap->mode == splashModeCMYK8) { - // convert colors to additive - cSrc2[0] = 0xff - cSrc[0]; - cSrc2[1] = 0xff - cSrc[1]; - cSrc2[2] = 0xff - cSrc[2]; - cSrc2[3] = 0xff - cSrc[3]; - cDest2[0] = 0xff - cDest[0]; - cDest2[1] = 0xff - cDest[1]; - cDest2[2] = 0xff - cDest[2]; - cDest2[3] = 0xff - cDest[3]; - (*state->blendFunc)(cSrc2, cDest2, cBlend, bitmap->mode); - // convert result back to subtractive - cBlend[0] = 0xff - cBlend[0]; - cBlend[1] = 0xff - cBlend[1]; - cBlend[2] = 0xff - cBlend[2]; - cBlend[3] = 0xff - cBlend[3]; - } else + if (bitmap->mode == splashModeCMYK8) { + // convert colors to additive + cSrc2[0] = 0xff - cSrc[0]; + cSrc2[1] = 0xff - cSrc[1]; + cSrc2[2] = 0xff - cSrc[2]; + cSrc2[3] = 0xff - cSrc[3]; + cDest2[0] = 0xff - cDest[0]; + cDest2[1] = 0xff - cDest[1]; + cDest2[2] = 0xff - cDest[2]; + cDest2[3] = 0xff - cDest[3]; + (*state->blendFunc)(cSrc2, cDest2, cBlend, bitmap->mode); + // convert result back to subtractive + cBlend[0] = 0xff - cBlend[0]; + cBlend[1] = 0xff - cBlend[1]; + cBlend[2] = 0xff - cBlend[2]; + cBlend[3] = 0xff - cBlend[3]; + } else #endif - (*state->blendFunc)(cSrc, cDest, cBlend, bitmap->mode); - } - - //----- result alpha and non-isolated group element correction + (*state->blendFunc)(cSrc, cDest, cBlend, bitmap->mode); + } - if (pipe->noTransparency) { - alphaI = alphaIm1 = aResult = 255; - } else { - aResult = aSrc + aDest - div255(aSrc * aDest); + //----- result alpha and non-isolated group element correction // alphaI = alpha_i // alphaIm1 = alpha_(i-1) - if (pipe->alpha0Ptr) { - alpha0 = *pipe->alpha0Ptr++; - alphaI = aResult + alpha0 - div255(aResult * alpha0); - alphaIm1 = alpha0 + aDest - div255(alpha0 * aDest); + + if (pipe->noTransparency) { + alphaI = alphaIm1 = aResult = 255; + } else if (alpha0Ptr) { + if (color0Ptr) { + // non-isolated, knockout + aResult = aSrc; + alpha0 = *alpha0Ptr++; + alphaI = aSrc + alpha0 - div255(aSrc * alpha0); + alphaIm1 = alpha0; + } else { + // non-isolated, non-knockout + aResult = aSrc + aDest - div255(aSrc * aDest); + alpha0 = *alpha0Ptr++; + alphaI = aResult + alpha0 - div255(aResult * alpha0); + alphaIm1 = alpha0 + aDest - div255(alpha0 * aDest); + } } else { - alphaI = aResult; - alphaIm1 = aDest; + if (color0Ptr) { + // isolated, knockout + aResult = aSrc; + alphaI = aSrc; + alphaIm1 = 0; + } else { + // isolated, non-knockout + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; + alphaIm1 = aDest; + } } - } - //----- result color + //----- result color - cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy + cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy - switch (pipe->resultColorCtrl) { + switch (pipe->resultColorCtrl) { - case splashPipeResultColorNoAlphaBlendMono: - cResult0 = state->grayTransfer[div255((255 - aDest) * cSrc[0] + - aDest * cBlend[0])]; - break; - case splashPipeResultColorNoAlphaBlendRGB: - cResult0 = state->rgbTransferR[div255((255 - aDest) * cSrc[0] + - aDest * cBlend[0])]; - cResult1 = state->rgbTransferG[div255((255 - aDest) * cSrc[1] + - aDest * cBlend[1])]; - cResult2 = state->rgbTransferB[div255((255 - aDest) * cSrc[2] + - aDest * cBlend[2])]; - break; + case splashPipeResultColorNoAlphaBlendMono: + cResult0 = state->grayTransfer[div255((255 - aDest) * cSrc[0] + + aDest * cBlend[0])]; + break; + case splashPipeResultColorNoAlphaBlendRGB: + cResult0 = state->rgbTransferR[div255((255 - aDest) * cSrc[0] + + aDest * cBlend[0])]; + cResult1 = state->rgbTransferG[div255((255 - aDest) * cSrc[1] + + aDest * cBlend[1])]; + cResult2 = state->rgbTransferB[div255((255 - aDest) * cSrc[2] + + aDest * cBlend[2])]; + break; #if SPLASH_CMYK - case splashPipeResultColorNoAlphaBlendCMYK: - cResult0 = state->cmykTransferC[div255((255 - aDest) * cSrc[0] + - aDest * cBlend[0])]; - cResult1 = state->cmykTransferM[div255((255 - aDest) * cSrc[1] + - aDest * cBlend[1])]; - cResult2 = state->cmykTransferY[div255((255 - aDest) * cSrc[2] + - aDest * cBlend[2])]; - cResult3 = state->cmykTransferK[div255((255 - aDest) * cSrc[3] + - aDest * cBlend[3])]; - break; + case splashPipeResultColorNoAlphaBlendCMYK: + cResult0 = state->cmykTransferC[div255((255 - aDest) * cSrc[0] + + aDest * cBlend[0])]; + cResult1 = state->cmykTransferM[div255((255 - aDest) * cSrc[1] + + aDest * cBlend[1])]; + cResult2 = state->cmykTransferY[div255((255 - aDest) * cSrc[2] + + aDest * cBlend[2])]; + cResult3 = state->cmykTransferK[div255((255 - aDest) * cSrc[3] + + aDest * cBlend[3])]; + break; #endif - case splashPipeResultColorAlphaNoBlendMono: - if (alphaI == 0) { - cResult0 = 0; - } else { - cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] + - aSrc * cSrc[0]) / alphaI]; - } - break; - case splashPipeResultColorAlphaNoBlendRGB: - if (alphaI == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - } else { - cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] + - aSrc * cSrc[0]) / alphaI]; - cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] + - aSrc * cSrc[1]) / alphaI]; - cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] + - aSrc * cSrc[2]) / alphaI]; - } - break; + case splashPipeResultColorAlphaNoBlendMono: + if (alphaI == 0) { + cResult0 = 0; + } else { + cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] + + aSrc * cSrc[0]) / alphaI]; + } + break; + case splashPipeResultColorAlphaNoBlendRGB: + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] + + aSrc * cSrc[0]) / alphaI]; + cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] + + aSrc * cSrc[1]) / alphaI]; + cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] + + aSrc * cSrc[2]) / alphaI]; + } + break; #if SPLASH_CMYK - case splashPipeResultColorAlphaNoBlendCMYK: - if (alphaI == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - cResult3 = 0; - } else { - cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] + - aSrc * cSrc[0]) / alphaI]; - cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] + - aSrc * cSrc[1]) / alphaI]; - cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] + - aSrc * cSrc[2]) / alphaI]; - cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] + - aSrc * cSrc[3]) / alphaI]; - } - break; + case splashPipeResultColorAlphaNoBlendCMYK: + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + cResult3 = 0; + } else { + cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] + + aSrc * cSrc[0]) / alphaI]; + cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] + + aSrc * cSrc[1]) / alphaI]; + cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] + + aSrc * cSrc[2]) / alphaI]; + cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] + + aSrc * cSrc[3]) / alphaI]; + } + break; #endif - case splashPipeResultColorAlphaBlendMono: - if (alphaI == 0) { - cResult0 = 0; - } else { - cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] + - aSrc * ((255 - alphaIm1) * cSrc[0] + - alphaIm1 * cBlend[0]) / 255) / - alphaI]; - } - break; - case splashPipeResultColorAlphaBlendRGB: - if (alphaI == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - } else { - cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] + - aSrc * ((255 - alphaIm1) * cSrc[0] + - alphaIm1 * cBlend[0]) / 255) / - alphaI]; - cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] + - aSrc * ((255 - alphaIm1) * cSrc[1] + - alphaIm1 * cBlend[1]) / 255) / - alphaI]; - cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] + - aSrc * ((255 - alphaIm1) * cSrc[2] + - alphaIm1 * cBlend[2]) / 255) / - alphaI]; - } - break; + case splashPipeResultColorAlphaBlendMono: + if (alphaI == 0) { + cResult0 = 0; + } else { + cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] + + aSrc * ((255 - alphaIm1) * cSrc[0] + + alphaIm1 * cBlend[0]) / 255) / + alphaI]; + } + break; + case splashPipeResultColorAlphaBlendRGB: + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] + + aSrc * ((255 - alphaIm1) * cSrc[0] + + alphaIm1 * cBlend[0]) / 255) / + alphaI]; + cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] + + aSrc * ((255 - alphaIm1) * cSrc[1] + + alphaIm1 * cBlend[1]) / 255) / + alphaI]; + cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] + + aSrc * ((255 - alphaIm1) * cSrc[2] + + alphaIm1 * cBlend[2]) / 255) / + alphaI]; + } + break; #if SPLASH_CMYK - case splashPipeResultColorAlphaBlendCMYK: - if (alphaI == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - cResult3 = 0; - } else { - cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] + - aSrc * ((255 - alphaIm1) * cSrc[0] + - alphaIm1 * cBlend[0]) / 255) / - alphaI]; - cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] + - aSrc * ((255 - alphaIm1) * cSrc[1] + - alphaIm1 * cBlend[1]) / 255) / - alphaI]; - cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] + - aSrc * ((255 - alphaIm1) * cSrc[2] + - alphaIm1 * cBlend[2]) / 255) / - alphaI]; - cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] + - aSrc * ((255 - alphaIm1) * cSrc[3] + - alphaIm1 * cBlend[3]) / 255) / - alphaI]; - } - break; + case splashPipeResultColorAlphaBlendCMYK: + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + cResult3 = 0; + } else { + cResult0 = + state->cmykTransferC[((alphaI - aSrc) * cDest[0] + + aSrc * ((255 - alphaIm1) * cSrc[0] + + alphaIm1 * cBlend[0]) / 255) / + alphaI]; + cResult1 = + state->cmykTransferM[((alphaI - aSrc) * cDest[1] + + aSrc * ((255 - alphaIm1) * cSrc[1] + + alphaIm1 * cBlend[1]) / 255) / + alphaI]; + cResult2 = + state->cmykTransferY[((alphaI - aSrc) * cDest[2] + + aSrc * ((255 - alphaIm1) * cSrc[2] + + alphaIm1 * cBlend[2]) / 255) / + alphaI]; + cResult3 = + state->cmykTransferK[((alphaI - aSrc) * cDest[3] + + aSrc * ((255 - alphaIm1) * cSrc[3] + + alphaIm1 * cBlend[3]) / 255) / + alphaI]; + } + break; #endif - } + } - //----- write destination pixel + //----- write destination pixel - switch (bitmap->mode) { - case splashModeMono1: - if (state->screen->test(pipe->x, pipe->y, cResult0)) { - *pipe->destColorPtr |= pipe->destColorMask; - } else { - *pipe->destColorPtr &= ~pipe->destColorMask; - } - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; - } - break; - case splashModeMono8: - *pipe->destColorPtr++ = cResult0; - break; - case splashModeRGB8: - *pipe->destColorPtr++ = cResult0; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult2; - break; - case splashModeBGR8: - *pipe->destColorPtr++ = cResult2; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult0; - break; + switch (bitmap->mode) { + case splashModeMono1: + if (state->screen->test(x, y, cResult0)) { + *destColorPtr |= destColorMask; + } else { + *destColorPtr &= ~destColorMask; + } + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + break; + case splashModeMono8: + *destColorPtr++ = cResult0; + break; + case splashModeRGB8: + destColorPtr[0] = cResult0; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult2; + destColorPtr += 3; + break; + case splashModeBGR8: + destColorPtr[0] = cResult2; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult0; + destColorPtr += 3; + break; #if SPLASH_CMYK - case splashModeCMYK8: - if (state->overprintMask & 1) { - pipe->destColorPtr[0] = cResult0; - } - if (state->overprintMask & 2) { - pipe->destColorPtr[1] = cResult1; - } - if (state->overprintMask & 4) { - pipe->destColorPtr[2] = cResult2; + case splashModeCMYK8: + destColorPtr[0] = cResult0; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult2; + destColorPtr[3] = cResult3; + destColorPtr += 4; + break; +#endif } - if (state->overprintMask & 8) { - pipe->destColorPtr[3] = cResult3; + if (destAlphaPtr) { + *destAlphaPtr++ = aResult; } - pipe->destColorPtr += 4; - break; -#endif - } - if (pipe->destAlphaPtr) { - *pipe->destAlphaPtr++ = aResult; - } - } + } // if (noTransparency && !blendFunc) + + cSrcPtr += cSrcStride; + shapePtr2 += shapeStride; + } // for (x ...) - ++pipe->x; + updateModX(lastX); } // special case: // !pipe->pattern && pipe->noTransparency && !state->blendFunc && -// bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) { -void Splash::pipeRunSimpleMono1(SplashPipe *pipe) { +// bitmap->mode == splashModeMono1 && !bitmap->alpha) { +void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { Guchar cResult0; + SplashColorPtr destColorPtr; + Guchar destColorMask; + int cSrcStride, x; - //----- write destination pixel - cResult0 = state->grayTransfer[pipe->cSrc[0]]; - if (state->screen->test(pipe->x, pipe->y, cResult0)) { - *pipe->destColorPtr |= pipe->destColorMask; + if (cSrcPtr) { + cSrcStride = 1; } else { - *pipe->destColorPtr &= ~pipe->destColorMask; + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; } - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; + if (x0 > x1) { + return; } + updateModX(x0); + updateModX(x1); + updateModY(y); - ++pipe->x; + destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; + destColorMask = 0x80 >> (x0 & 7); + + for (x = x0; x <= x1; ++x) { + + //----- write destination pixel + cResult0 = state->grayTransfer[cSrcPtr[0]]; + if (state->screen->test(x, y, cResult0)) { + *destColorPtr |= destColorMask; + } else { + *destColorPtr &= ~destColorMask; + } + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + + cSrcPtr += cSrcStride; + } } // special case: // !pipe->pattern && pipe->noTransparency && !state->blendFunc && -// bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) { -void Splash::pipeRunSimpleMono8(SplashPipe *pipe) { - //----- write destination pixel - *pipe->destColorPtr++ = state->grayTransfer[pipe->cSrc[0]]; - *pipe->destAlphaPtr++ = 255; +// bitmap->mode == splashModeMono8 && bitmap->alpha) { +void Splash::pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x; + + if (cSrcPtr) { + cSrcStride = 1; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModX(x1); + updateModY(y); + + destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- write destination pixel + *destColorPtr++ = state->grayTransfer[cSrcPtr[0]]; + *destAlphaPtr++ = 255; - ++pipe->x; + cSrcPtr += cSrcStride; + } } // special case: // !pipe->pattern && pipe->noTransparency && !state->blendFunc && -// bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) { -void Splash::pipeRunSimpleRGB8(SplashPipe *pipe) { - //----- write destination pixel - *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]]; - *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]]; - *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]]; - *pipe->destAlphaPtr++ = 255; - - ++pipe->x; +// bitmap->mode == splashModeRGB8 && bitmap->alpha) { +void Splash::pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x; + + if (cSrcPtr) { + cSrcStride = 3; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModX(x1); + updateModY(y); + + destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- write destination pixel + destColorPtr[0] = state->rgbTransferR[cSrcPtr[0]]; + destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]]; + destColorPtr[2] = state->rgbTransferB[cSrcPtr[2]]; + destColorPtr += 3; + *destAlphaPtr++ = 255; + + cSrcPtr += cSrcStride; + } } // special case: // !pipe->pattern && pipe->noTransparency && !state->blendFunc && -// bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) { -void Splash::pipeRunSimpleBGR8(SplashPipe *pipe) { - //----- write destination pixel - *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]]; - *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]]; - *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]]; - *pipe->destAlphaPtr++ = 255; - - ++pipe->x; +// bitmap->mode == splashModeBGR8 && bitmap->alpha) { +void Splash::pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x; + + if (cSrcPtr) { + cSrcStride = 3; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModX(x1); + updateModY(y); + + destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- write destination pixel + destColorPtr[0] = state->rgbTransferB[cSrcPtr[2]]; + destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]]; + destColorPtr[2] = state->rgbTransferR[cSrcPtr[0]]; + destColorPtr += 3; + *destAlphaPtr++ = 255; + + cSrcPtr += cSrcStride; + } } #if SPLASH_CMYK // special case: // !pipe->pattern && pipe->noTransparency && !state->blendFunc && -// bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) { -void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe) { - //----- write destination pixel - if (state->overprintMask & 1) { - pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]]; - } - if (state->overprintMask & 2) { - pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]]; - } - if (state->overprintMask & 4) { - pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]]; +// bitmap->mode == splashModeCMYK8 && bitmap->alpha) { +void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x; + + if (cSrcPtr) { + cSrcStride = 4; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; } - if (state->overprintMask & 8) { - pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]]; + if (x0 > x1) { + return; } - pipe->destColorPtr += 4; - *pipe->destAlphaPtr++ = 255; + updateModX(x0); + updateModX(x1); + updateModY(y); + + destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- write destination pixel + destColorPtr[0] = state->cmykTransferC[cSrcPtr[0]]; + destColorPtr[1] = state->cmykTransferM[cSrcPtr[1]]; + destColorPtr[2] = state->cmykTransferY[cSrcPtr[2]]; + destColorPtr[3] = state->cmykTransferK[cSrcPtr[3]]; + destColorPtr += 4; + *destAlphaPtr++ = 255; - ++pipe->x; + cSrcPtr += cSrcStride; + } } #endif // special case: -// !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && -// !pipe->nonIsolatedGroup && -// bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr -void Splash::pipeRunAAMono1(SplashPipe *pipe) { - Guchar aSrc; - SplashColor cDest; - Guchar cResult0; +// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// bitmap->mode == splashModeMono1 && !bitmap->alpha +void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, cDest0, cResult0; + SplashColorPtr destColorPtr; + Guchar destColorMask; + int cSrcStride, x, lastX; + + if (cSrcPtr) { + cSrcStride = 1; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; - //----- read destination pixel - cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00; + destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; + destColorMask = 0x80 >> (x0 & 7); - //----- source alpha - aSrc = div255(pipe->aInput * pipe->shape); + for (x = x0; x <= x1; ++x) { - //----- result color - // note: aDest = alpha2 = aResult = 0xff - cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0])]; + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; - //----- write destination pixel - if (state->screen->test(pipe->x, pipe->y, cResult0)) { - *pipe->destColorPtr |= pipe->destColorMask; - } else { - *pipe->destColorPtr &= ~pipe->destColorMask; - } - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; + //----- read destination pixel + cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00; + + //----- source alpha + aSrc = shape; + + //----- result color + // note: aDest = alphaI = aResult = 0xff + cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest0 + + aSrc * cSrcPtr[0])]; + + //----- write destination pixel + if (state->screen->test(x, y, cResult0)) { + *destColorPtr |= destColorMask; + } else { + *destColorPtr &= ~destColorMask; + } + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + + cSrcPtr += cSrcStride; + ++shapePtr; } - ++pipe->x; + updateModX(lastX); } // special case: -// !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && -// !pipe->nonIsolatedGroup && -// bitmap->mode == splashModeMono8 && pipe->destAlphaPtr -void Splash::pipeRunAAMono8(SplashPipe *pipe) { - Guchar aSrc, aDest, alpha2, aResult; - SplashColor cDest; - Guchar cResult0; +// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// bitmap->mode == splashModeMono8 && bitmap->alpha +void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult, cDest0, cResult0; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; - //----- read destination pixel - cDest[0] = *pipe->destColorPtr; - aDest = *pipe->destAlphaPtr; + if (cSrcPtr) { + cSrcStride = 1; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; - //----- source alpha - aSrc = div255(pipe->aInput * pipe->shape); + destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; - //----- result alpha and non-isolated group element correction - aResult = aSrc + aDest - div255(aSrc * aDest); - alpha2 = aResult; + for (x = x0; x <= x1; ++x) { - //----- result color - if (alpha2 == 0) { - cResult0 = 0; - } else { - cResult0 = state->grayTransfer[(Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2)]; - } + //----- shape + shape = *shapePtr; + if (!shape) { + ++destColorPtr; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; - //----- write destination pixel - *pipe->destColorPtr++ = cResult0; - *pipe->destAlphaPtr++ = aResult; + //----- read destination pixel + cDest0 = *destColorPtr; + aDest = *destAlphaPtr; + + //----- source alpha + aSrc = shape; + + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; - ++pipe->x; + //----- result color + if (alphaI == 0) { + cResult0 = 0; + } else { + cResult0 = state->grayTransfer[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrcPtr[0]) / alphaI)]; + } + + //----- write destination pixel + *destColorPtr++ = cResult0; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; + } + + updateModX(lastX); } // special case: -// !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && -// !pipe->nonIsolatedGroup && -// bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr -void Splash::pipeRunAARGB8(SplashPipe *pipe) { - Guchar aSrc, aDest, alpha2, aResult; - SplashColor cDest; +// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// bitmap->mode == splashModeRGB8 && bitmap->alpha +void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; + + if (cSrcPtr) { + cSrcStride = 3; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; - //----- read destination pixel - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - aDest = *pipe->destAlphaPtr; + destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; - //----- source alpha - aSrc = div255(pipe->aInput * pipe->shape); + for (x = x0; x <= x1; ++x) { - //----- result alpha and non-isolated group element correction - aResult = aSrc + aDest - div255(aSrc * aDest); - alpha2 = aResult; + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += 3; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; - //----- result color - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - } else { - cResult0 = state->rgbTransferR[(Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2)]; - cResult1 = state->rgbTransferG[(Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * pipe->cSrc[1]) / alpha2)]; - cResult2 = state->rgbTransferB[(Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * pipe->cSrc[2]) / alpha2)]; - } + //----- read destination pixel + cDest0 = destColorPtr[0]; + cDest1 = destColorPtr[1]; + cDest2 = destColorPtr[2]; + aDest = *destAlphaPtr; - //----- write destination pixel - *pipe->destColorPtr++ = cResult0; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult2; - *pipe->destAlphaPtr++ = aResult; + //----- source alpha + aSrc = shape; - ++pipe->x; + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; + + //----- result color + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrcPtr[0]) / alphaI)]; + cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 + + aSrc * cSrcPtr[1]) / alphaI)]; + cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 + + aSrc * cSrcPtr[2]) / alphaI)]; + } + + //----- write destination pixel + destColorPtr[0] = cResult0; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult2; + destColorPtr += 3; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; + } + + updateModX(lastX); } // special case: -// !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && -// !pipe->nonIsolatedGroup && -// bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr -void Splash::pipeRunAABGR8(SplashPipe *pipe) { - Guchar aSrc, aDest, alpha2, aResult; - SplashColor cDest; +// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// bitmap->mode == splashModeBGR8 && bitmap->alpha +void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar cDest0, cDest1, cDest2; Guchar cResult0, cResult1, cResult2; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; - //----- read destination pixel - cDest[0] = pipe->destColorPtr[2]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[0]; - aDest = *pipe->destAlphaPtr; + if (cSrcPtr) { + cSrcStride = 3; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; + } + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; - //----- source alpha - aSrc = div255(pipe->aInput * pipe->shape); + destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; - //----- result alpha and non-isolated group element correction - aResult = aSrc + aDest - div255(aSrc * aDest); - alpha2 = aResult; + for (x = x0; x <= x1; ++x) { - //----- result color - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - } else { - cResult0 = state->rgbTransferR[(Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2)]; - cResult1 = state->rgbTransferG[(Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * pipe->cSrc[1]) / alpha2)]; - cResult2 = state->rgbTransferB[(Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * pipe->cSrc[2]) / alpha2)]; - } + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += 3; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = destColorPtr[2]; + cDest1 = destColorPtr[1]; + cDest2 = destColorPtr[0]; + aDest = *destAlphaPtr; - //----- write destination pixel - *pipe->destColorPtr++ = cResult2; - *pipe->destColorPtr++ = cResult1; - *pipe->destColorPtr++ = cResult0; - *pipe->destAlphaPtr++ = aResult; + //----- source alpha + aSrc = shape; + + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; - ++pipe->x; + //----- result color + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrcPtr[0]) / alphaI)]; + cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 + + aSrc * cSrcPtr[1]) / alphaI)]; + cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 + + aSrc * cSrcPtr[2]) / alphaI)]; + } + + //----- write destination pixel + destColorPtr[0] = cResult2; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult0; + destColorPtr += 3; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; + } + + updateModX(lastX); } #if SPLASH_CMYK // special case: -// !pipe->pattern && !pipe->noTransparency && !state->softMask && -// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && -// !pipe->nonIsolatedGroup && -// bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr -void Splash::pipeRunAACMYK8(SplashPipe *pipe) { - Guchar aSrc, aDest, alpha2, aResult; - SplashColor cDest; +// !pipe->pattern && pipe->shapeOnly && !state->blendFunc && +// bitmap->mode == splashModeCMYK8 && bitmap->alpha +void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar cSrc0, cSrc1, cSrc2, cSrc3; + Guchar cDest0, cDest1, cDest2, cDest3; Guchar cResult0, cResult1, cResult2, cResult3; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; - //----- read destination pixel - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - cDest[3] = pipe->destColorPtr[3]; - aDest = *pipe->destAlphaPtr; - - //----- source alpha - aSrc = div255(pipe->aInput * pipe->shape); - - //----- result alpha and non-isolated group element correction - aResult = aSrc + aDest - div255(aSrc * aDest); - alpha2 = aResult; - - //----- result color - if (alpha2 == 0) { - cResult0 = 0; - cResult1 = 0; - cResult2 = 0; - cResult3 = 0; + if (cSrcPtr) { + cSrcStride = 4; } else { - cResult0 = state->cmykTransferC[(Guchar)(((alpha2 - aSrc) * cDest[0] + - aSrc * pipe->cSrc[0]) / alpha2)]; - cResult1 = state->cmykTransferM[(Guchar)(((alpha2 - aSrc) * cDest[1] + - aSrc * pipe->cSrc[1]) / alpha2)]; - cResult2 = state->cmykTransferY[(Guchar)(((alpha2 - aSrc) * cDest[2] + - aSrc * pipe->cSrc[2]) / alpha2)]; - cResult3 = state->cmykTransferK[(Guchar)(((alpha2 - aSrc) * cDest[3] + - aSrc * pipe->cSrc[3]) / alpha2)]; + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; } - - //----- write destination pixel - if (state->overprintMask & 1) { - pipe->destColorPtr[0] = cResult0; - } - if (state->overprintMask & 2) { - pipe->destColorPtr[1] = cResult1; + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; } - if (state->overprintMask & 4) { - pipe->destColorPtr[2] = cResult2; + if (x0 > x1) { + return; } - if (state->overprintMask & 8) { - pipe->destColorPtr[3] = cResult3; + updateModX(x0); + updateModY(y); + lastX = x0; + + destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += 4; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = destColorPtr[0]; + cDest1 = destColorPtr[1]; + cDest2 = destColorPtr[2]; + cDest3 = destColorPtr[3]; + aDest = *destAlphaPtr; + + //----- overprint + if (state->overprintMask & 1) { + cSrc0 = cSrcPtr[0]; + } else { + cSrc0 = div255(aDest * cDest0); + } + if (state->overprintMask & 2) { + cSrc1 = cSrcPtr[1]; + } else { + cSrc1 = div255(aDest * cDest1); + } + if (state->overprintMask & 4) { + cSrc2 = cSrcPtr[2]; + } else { + cSrc2 = div255(aDest * cDest2); + } + if (state->overprintMask & 8) { + cSrc3 = cSrcPtr[3]; + } else { + cSrc3 = div255(aDest * cDest3); + } + + //----- source alpha + aSrc = shape; + + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; + + //----- result color + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + cResult3 = 0; + } else { + cResult0 = state->cmykTransferC[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrc0) / alphaI)]; + cResult1 = state->cmykTransferM[(Guchar)(((alphaI - aSrc) * cDest1 + + aSrc * cSrc1) / alphaI)]; + cResult2 = state->cmykTransferY[(Guchar)(((alphaI - aSrc) * cDest2 + + aSrc * cSrc2) / alphaI)]; + cResult3 = state->cmykTransferK[(Guchar)(((alphaI - aSrc) * cDest3 + + aSrc * cSrc3) / alphaI)]; + } + + //----- write destination pixel + destColorPtr[0] = cResult0; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult2; + destColorPtr[3] = cResult3; + destColorPtr += 4; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; } - pipe->destColorPtr += 4; - *pipe->destAlphaPtr++ = aResult; - ++pipe->x; + updateModX(lastX); } #endif -inline void Splash::pipeSetXY(SplashPipe *pipe, int x, int y) { - pipe->x = x; - pipe->y = y; - if (state->softMask) { - pipe->softMaskPtr = - &state->softMask->data[y * state->softMask->rowSize + x]; +// special case: +// !pipe->pattern && !pipe->noTransparency && !state->softMask && +// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// !pipe->nonIsolatedGroup && +// bitmap->mode == splashModeMono1 && !bitmap->alpha +void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, cDest0, cResult0; + SplashColorPtr destColorPtr; + Guchar destColorMask; + int cSrcStride, x, lastX; + + if (cSrcPtr) { + cSrcStride = 1; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; } - switch (bitmap->mode) { - case splashModeMono1: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + (x >> 3)]; - pipe->destColorMask = 0x80 >> (x & 7); - break; - case splashModeMono8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + x]; - break; - case splashModeRGB8: - case splashModeBGR8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x]; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x]; - break; -#endif + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; } - if (bitmap->alpha) { - pipe->destAlphaPtr = &bitmap->alpha[y * bitmap->width + x]; - } else { - pipe->destAlphaPtr = NULL; + if (x0 > x1) { + return; } - if (state->inNonIsolatedGroup && alpha0Bitmap->alpha) { - pipe->alpha0Ptr = - &alpha0Bitmap->alpha[(alpha0Y + y) * alpha0Bitmap->width + - (alpha0X + x)]; - } else { - pipe->alpha0Ptr = NULL; + updateModX(x0); + updateModY(y); + lastX = x0; + + destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)]; + destColorMask = 0x80 >> (x0 & 7); + + for (x = x0; x <= x1; ++x) { + + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00; + + //----- source alpha + aSrc = div255(pipe->aInput * shape); + + //----- result color + // note: aDest = alphaI = aResult = 0xff + cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest0 + + aSrc * cSrcPtr[0])]; + + //----- write destination pixel + if (state->screen->test(x, y, cResult0)) { + *destColorPtr |= destColorMask; + } else { + *destColorPtr &= ~destColorMask; + } + destColorPtr += destColorMask & 1; + destColorMask = (destColorMask << 7) | (destColorMask >> 1); + + cSrcPtr += cSrcStride; + ++shapePtr; } + + updateModX(lastX); } -inline void Splash::pipeIncX(SplashPipe *pipe) { - ++pipe->x; - if (state->softMask) { - ++pipe->softMaskPtr; +// special case: +// !pipe->pattern && !pipe->noTransparency && !state->softMask && +// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// !pipe->nonIsolatedGroup && +// bitmap->mode == splashModeMono8 && bitmap->alpha +void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult, cDest0, cResult0; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; + + if (cSrcPtr) { + cSrcStride = 1; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; } - switch (bitmap->mode) { - case splashModeMono1: - if (!(pipe->destColorMask >>= 1)) { - pipe->destColorMask = 0x80; - ++pipe->destColorPtr; + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; } - break; - case splashModeMono8: - ++pipe->destColorPtr; - break; - case splashModeRGB8: - case splashModeBGR8: - pipe->destColorPtr += 3; - break; -#if SPLASH_CMYK - case splashModeCMYK8: - pipe->destColorPtr += 4; - break; -#endif - } - if (pipe->destAlphaPtr) { - ++pipe->destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; } - if (pipe->alpha0Ptr) { - ++pipe->alpha0Ptr; + if (x0 > x1) { + return; } -} + updateModX(x0); + updateModY(y); + lastX = x0; + + destColorPtr = &bitmap->data[y * bitmap->rowSize + x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- shape + shape = *shapePtr; + if (!shape) { + ++destColorPtr; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = *destColorPtr; + aDest = *destAlphaPtr; + + //----- source alpha + aSrc = div255(pipe->aInput * shape); -inline void Splash::drawPixel(SplashPipe *pipe, int x, int y, GBool noClip) { - if (noClip || state->clip->test(x, y)) { - pipeSetXY(pipe, x, y); - (this->*pipe->run)(pipe); - updateModX(x); - updateModY(y); + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; + + //----- result color + if (alphaI == 0) { + cResult0 = 0; + } else { + cResult0 = state->grayTransfer[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrcPtr[0]) / alphaI)]; + } + + //----- write destination pixel + *destColorPtr++ = cResult0; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; } -} -inline void Splash::drawAAPixelInit() { - aaBufY = -1; + updateModX(lastX); } -inline void Splash::drawAAPixel(SplashPipe *pipe, int x, int y) { -#if splashAASize == 4 - static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4 }; - int w; -#else - int xx, yy; -#endif - SplashColorPtr p; - int x0, x1, t; +// special case: +// !pipe->pattern && !pipe->noTransparency && !state->softMask && +// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// !pipe->nonIsolatedGroup && +// bitmap->mode == splashModeRGB8 && bitmap->alpha +void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar cDest0, cDest1, cDest2; + Guchar cResult0, cResult1, cResult2; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; - if (x < 0 || x >= bitmap->width || - y < state->clip->getYMinI() || y > state->clip->getYMaxI()) { + if (cSrcPtr) { + cSrcStride = 3; + } else { + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; + } + cSrcPtr += cSrcStride; + ++shapePtr; + } + if (x0 > x1) { return; } + updateModX(x0); + updateModY(y); + lastX = x0; - // update aaBuf - if (y != aaBufY) { - memset(aaBuf->getDataPtr(), 0xff, - aaBuf->getRowSize() * aaBuf->getHeight()); - x0 = 0; - x1 = bitmap->width - 1; - state->clip->clipAALine(aaBuf, &x0, &x1, y); - aaBufY = y; - } - - // compute the shape value -#if splashAASize == 4 - p = aaBuf->getDataPtr() + (x >> 1); - w = aaBuf->getRowSize(); - if (x & 1) { - t = bitCount4[*p & 0x0f] + bitCount4[p[w] & 0x0f] + - bitCount4[p[2*w] & 0x0f] + bitCount4[p[3*w] & 0x0f]; + destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += 3; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = destColorPtr[0]; + cDest1 = destColorPtr[1]; + cDest2 = destColorPtr[2]; + aDest = *destAlphaPtr; + + //----- source alpha + aSrc = div255(pipe->aInput * shape); + + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; + + //----- result color + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrcPtr[0]) / alphaI)]; + cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 + + aSrc * cSrcPtr[1]) / alphaI)]; + cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 + + aSrc * cSrcPtr[2]) / alphaI)]; + } + + //----- write destination pixel + destColorPtr[0] = cResult0; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult2; + destColorPtr += 3; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; + } + + updateModX(lastX); +} + +// special case: +// !pipe->pattern && !pipe->noTransparency && !state->softMask && +// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// !pipe->nonIsolatedGroup && +// bitmap->mode == splashModeBGR8 && bitmap->alpha +void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar cDest0, cDest1, cDest2; + Guchar cResult0, cResult1, cResult2; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; + + if (cSrcPtr) { + cSrcStride = 3; } else { - t = bitCount4[*p >> 4] + bitCount4[p[w] >> 4] + - bitCount4[p[2*w] >> 4] + bitCount4[p[3*w] >> 4]; + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; } -#else - t = 0; - for (yy = 0; yy < splashAASize; ++yy) { - for (xx = 0; xx < splashAASize; ++xx) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + - ((x * splashAASize + xx) >> 3); - t += (*p >> (7 - ((x * splashAASize + xx) & 7))) & 1; + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; } + cSrcPtr += cSrcStride; + ++shapePtr; } -#endif + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; + + destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; + + for (x = x0; x <= x1; ++x) { + + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += 3; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = destColorPtr[2]; + cDest1 = destColorPtr[1]; + cDest2 = destColorPtr[0]; + aDest = *destAlphaPtr; + + //----- source alpha + aSrc = div255(pipe->aInput * shape); + + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; + + //----- result color + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrcPtr[0]) / alphaI)]; + cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 + + aSrc * cSrcPtr[1]) / alphaI)]; + cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 + + aSrc * cSrcPtr[2]) / alphaI)]; + } - // draw the pixel - if (t != 0) { - pipeSetXY(pipe, x, y); - pipe->shape = div255(aaGamma[t] * pipe->shape); - (this->*pipe->run)(pipe); - updateModX(x); - updateModY(y); + //----- write destination pixel + destColorPtr[0] = cResult2; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult0; + destColorPtr += 3; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; } + + updateModX(lastX); } -inline void Splash::drawSpan(SplashPipe *pipe, int x0, int x1, int y, - GBool noClip) { - int x; +#if SPLASH_CMYK +// special case: +// !pipe->pattern && !pipe->noTransparency && !state->softMask && +// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc && +// !pipe->nonIsolatedGroup && +// bitmap->mode == splashModeCMYK8 && bitmap->alpha +void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr) { + Guchar shape, aSrc, aDest, alphaI, aResult; + Guchar cSrc0, cSrc1, cSrc2, cSrc3; + Guchar cDest0, cDest1, cDest2, cDest3; + Guchar cResult0, cResult1, cResult2, cResult3; + SplashColorPtr destColorPtr; + Guchar *destAlphaPtr; + int cSrcStride, x, lastX; - if (noClip) { - pipeSetXY(pipe, x0, y); - for (x = x0; x <= x1; ++x) { - (this->*pipe->run)(pipe); - } - updateModX(x0); - updateModX(x1); - updateModY(y); + if (cSrcPtr) { + cSrcStride = 4; } else { - if (x0 < state->clip->getXMinI()) { - x0 = state->clip->getXMinI(); - } - if (x1 > state->clip->getXMaxI()) { - x1 = state->clip->getXMaxI(); - } - pipeSetXY(pipe, x0, y); - for (x = x0; x <= x1; ++x) { - if (state->clip->test(x, y)) { - (this->*pipe->run)(pipe); - updateModX(x); - updateModY(y); - } else { - pipeIncX(pipe); - } + cSrcPtr = pipe->cSrcVal; + cSrcStride = 0; + } + for (; x0 <= x1; ++x0) { + if (*shapePtr) { + break; } + cSrcPtr += cSrcStride; + ++shapePtr; } -} + if (x0 > x1) { + return; + } + updateModX(x0); + updateModY(y); + lastX = x0; -inline void Splash::drawAALine(SplashPipe *pipe, int x0, int x1, int y) { -#if splashAASize == 4 - static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4 }; - SplashColorPtr p0, p1, p2, p3; - int t; -#else - SplashColorPtr p; - int xx, yy, t; -#endif - int x; + destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x0]; + destAlphaPtr = &bitmap->alpha[y * bitmap->width + x0]; -#if splashAASize == 4 - p0 = aaBuf->getDataPtr() + (x0 >> 1); - p1 = p0 + aaBuf->getRowSize(); - p2 = p1 + aaBuf->getRowSize(); - p3 = p2 + aaBuf->getRowSize(); -#endif - pipeSetXY(pipe, x0, y); for (x = x0; x <= x1; ++x) { - // compute the shape value -#if splashAASize == 4 - if (x & 1) { - t = bitCount4[*p0 & 0x0f] + bitCount4[*p1 & 0x0f] + - bitCount4[*p2 & 0x0f] + bitCount4[*p3 & 0x0f]; - ++p0; ++p1; ++p2; ++p3; + //----- shape + shape = *shapePtr; + if (!shape) { + destColorPtr += 4; + ++destAlphaPtr; + cSrcPtr += cSrcStride; + ++shapePtr; + continue; + } + lastX = x; + + //----- read destination pixel + cDest0 = destColorPtr[0]; + cDest1 = destColorPtr[1]; + cDest2 = destColorPtr[2]; + cDest3 = destColorPtr[3]; + aDest = *destAlphaPtr; + + //----- overprint + if (state->overprintMask & 1) { + cSrc0 = cSrcPtr[0]; } else { - t = bitCount4[*p0 >> 4] + bitCount4[*p1 >> 4] + - bitCount4[*p2 >> 4] + bitCount4[*p3 >> 4]; + cSrc0 = div255(aDest * cDest0); } -#else - t = 0; - for (yy = 0; yy < splashAASize; ++yy) { - for (xx = 0; xx < splashAASize; ++xx) { - p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + - ((x * splashAASize + xx) >> 3); - t += (*p >> (7 - ((x * splashAASize + xx) & 7))) & 1; - } + if (state->overprintMask & 2) { + cSrc1 = cSrcPtr[1]; + } else { + cSrc1 = div255(aDest * cDest1); } -#endif + if (state->overprintMask & 4) { + cSrc2 = cSrcPtr[2]; + } else { + cSrc2 = div255(aDest * cDest2); + } + if (state->overprintMask & 8) { + cSrc3 = cSrcPtr[3]; + } else { + cSrc3 = div255(aDest * cDest3); + } + + //----- source alpha + aSrc = div255(pipe->aInput * shape); + + //----- result alpha and non-isolated group element correction + aResult = aSrc + aDest - div255(aSrc * aDest); + alphaI = aResult; - if (t != 0) { - pipe->shape = aaGamma[t]; - (this->*pipe->run)(pipe); - updateModX(x); - updateModY(y); + //----- result color + if (alphaI == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + cResult3 = 0; } else { - pipeIncX(pipe); + cResult0 = state->cmykTransferC[(Guchar)(((alphaI - aSrc) * cDest0 + + aSrc * cSrc0) / alphaI)]; + cResult1 = state->cmykTransferM[(Guchar)(((alphaI - aSrc) * cDest1 + + aSrc * cSrc1) / alphaI)]; + cResult2 = state->cmykTransferY[(Guchar)(((alphaI - aSrc) * cDest2 + + aSrc * cSrc2) / alphaI)]; + cResult3 = state->cmykTransferK[(Guchar)(((alphaI - aSrc) * cDest3 + + aSrc * cSrc3) / alphaI)]; } + + //----- write destination pixel + destColorPtr[0] = cResult0; + destColorPtr[1] = cResult1; + destColorPtr[2] = cResult2; + destColorPtr[3] = cResult3; + destColorPtr += 4; + *destAlphaPtr++ = aResult; + + cSrcPtr += cSrcStride; + ++shapePtr; } + + updateModX(lastX); } +#endif + //------------------------------------------------------------------------ @@ -1238,21 +1934,18 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, int i; bitmap = bitmapA; + bitmapComps = splashColorModeNComps[bitmap->mode]; vectorAntialias = vectorAntialiasA; inShading = gFalse; state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, screenParams); + scanBuf = (Guchar *)gmalloc(bitmap->width); if (vectorAntialias) { - aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize, - 1, splashModeMono1, gFalse); - for (i = 0; i <= splashAASize * splashAASize; ++i) { + for (i = 0; i <= 255; ++i) { aaGamma[i] = (Guchar)splashRound( - splashPow((SplashCoord)i / - (SplashCoord)(splashAASize * splashAASize), - splashAAGamma) * 255); + splashPow((SplashCoord)i / (SplashCoord)255, + splashAAGamma) * 255); } - } else { - aaBuf = NULL; } minLineWidth = 0; clearModRegion(); @@ -1264,21 +1957,18 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, int i; bitmap = bitmapA; + bitmapComps = splashColorModeNComps[bitmap->mode]; vectorAntialias = vectorAntialiasA; inShading = gFalse; state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, screenA); + scanBuf = (Guchar *)gmalloc(bitmap->width); if (vectorAntialias) { - aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize, - 1, splashModeMono1, gFalse); - for (i = 0; i <= splashAASize * splashAASize; ++i) { + for (i = 0; i <= 255; ++i) { aaGamma[i] = (Guchar)splashRound( - splashPow((SplashCoord)i / - (SplashCoord)(splashAASize * splashAASize), - splashAAGamma) * 255); + splashPow((SplashCoord)i / (SplashCoord)255, + splashAAGamma) * 255); } - } else { - aaBuf = NULL; } minLineWidth = 0; clearModRegion(); @@ -1290,9 +1980,7 @@ Splash::~Splash() { restoreState(); } delete state; - if (vectorAntialias) { - delete aaBuf; - } + gfree(scanBuf); } //------------------------------------------------------------------------ @@ -1375,6 +2063,10 @@ GBool Splash::getInNonIsolatedGroup() { return state->inNonIsolatedGroup; } +GBool Splash::getInKnockoutGroup() { + return state->inKnockoutGroup; +} + //------------------------------------------------------------------------ // state write //------------------------------------------------------------------------ @@ -1442,28 +2134,30 @@ void Splash::setStrokeAdjust(GBool strokeAdjust) { void Splash::clipResetToRect(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1) { - state->clip->resetToRect(x0, y0, x1, y1); + state->clipResetToRect(x0, y0, x1, y1); } SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1) { - return state->clip->clipToRect(x0, y0, x1, y1); + return state->clipToRect(x0, y0, x1, y1); } SplashError Splash::clipToPath(SplashPath *path, GBool eo) { - return state->clip->clipToPath(path, state->matrix, state->flatness, eo); + return state->clipToPath(path, eo); } void Splash::setSoftMask(SplashBitmap *softMask) { state->setSoftMask(softMask); } -void Splash::setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA, - int alpha0XA, int alpha0YA) { - alpha0Bitmap = alpha0BitmapA; - alpha0X = alpha0XA; - alpha0Y = alpha0YA; - state->inNonIsolatedGroup = gTrue; +void Splash::setInTransparencyGroup(SplashBitmap *groupBackBitmapA, + int groupBackXA, int groupBackYA, + GBool nonIsolated, GBool knockout) { + groupBackBitmap = groupBackBitmapA; + groupBackX = groupBackXA; + groupBackY = groupBackYA; + state->inNonIsolatedGroup = nonIsolated; + state->inKnockoutGroup = knockout; } void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue, @@ -1539,9 +2233,9 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) { for (y = 0; y < bitmap->height; ++y) { p = row; for (x = 0; x < bitmap->width; ++x) { - *p++ = color[2]; - *p++ = color[1]; *p++ = color[0]; + *p++ = color[1]; + *p++ = color[2]; } row += bitmap->rowSize; } @@ -1560,9 +2254,9 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) { for (y = 0; y < bitmap->height; ++y) { p = row; for (x = 0; x < bitmap->width; ++x) { - *p++ = color[0]; - *p++ = color[1]; *p++ = color[2]; + *p++ = color[1]; + *p++ = color[0]; } row += bitmap->rowSize; } @@ -1606,7 +2300,7 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) { SplashError Splash::stroke(SplashPath *path) { SplashPath *path2, *dPath; - SplashCoord d1, d2, t1, t2, w; + SplashCoord t0, t1, t2, t3, w, w2; if (debugMode) { printf("stroke [dash:%d] [width:%.2f]:\n", @@ -1628,31 +2322,41 @@ SplashError Splash::stroke(SplashPath *path) { } } - // transform a unit square, and take the half the max of the two - // diagonals; the product of this number and the line width is the - // (approximate) transformed line width - t1 = state->matrix[0] + state->matrix[2]; - t2 = state->matrix[1] + state->matrix[3]; - d1 = t1 * t1 + t2 * t2; - t1 = state->matrix[0] - state->matrix[2]; - t2 = state->matrix[1] - state->matrix[3]; - d2 = t1 * t1 + t2 * t2; - if (d2 > d1) { - d1 = d2; - } - d1 *= 0.5; - if (d1 > 0 && - d1 * state->lineWidth * state->lineWidth < minLineWidth * minLineWidth) { - w = minLineWidth / splashSqrt(d1); - strokeWide(path2, w); + // Compute an approximation of the transformed line width. + // Given a CTM of [m0 m1], + // [m2 m3] + // if |m0|*|m3| >= |m1|*|m2| then use min{|m0|,|m3|}, else + // use min{|m1|,|m2|}. + // This handles the common cases -- [s 0 ] and [0 s] -- + // [0 +/-s] [+/-s 0] + // well, and still does something reasonable for the uncommon + // case transforms. + t0 = splashAbs(state->matrix[0]); + t1 = splashAbs(state->matrix[1]); + t2 = splashAbs(state->matrix[2]); + t3 = splashAbs(state->matrix[3]); + if (t0 * t3 >= t1 * t2) { + w = (t0 < t3) ? t0 : t3; + } else { + w = (t1 < t2) ? t1 : t2; + } + w2 = w * state->lineWidth; + // if there is a min line width set, and the transformed line width + // is smaller, use the min line width + if (w > 0 && w2 < minLineWidth) { + strokeWide(path2, minLineWidth / w); } else if (bitmap->mode == splashModeMono1) { - // this gets close to Adobe's behavior in mono mode - if (d1 <= 2) { + // in monochrome mode, use 0-width lines for any transformed line + // width <= 1 -- lines less than 1 pixel wide look too fat without + // antialiasing + if (w2 < 1.001) { strokeNarrow(path2); } else { strokeWide(path2, state->lineWidth); } } else { + // in gray and color modes, only use 0-width lines if the line + // width is explicitly set to 0 if (state->lineWidth == 0) { strokeNarrow(path2); } else { @@ -1678,9 +2382,9 @@ void Splash::strokeNarrow(SplashPath *path) { xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse); - pipeInit(&pipe, 0, 0, state->strokePattern, NULL, + pipeInit(&pipe, state->strokePattern, (Guchar)splashRound(state->strokeAlpha * 255), - gFalse, gFalse); + gTrue, gFalse); for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) { if (seg->y0 <= seg->y1) { @@ -1695,22 +2399,25 @@ void Splash::strokeNarrow(SplashPath *path) { x1 = splashFloor(seg->x0); } if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, - x0 <= x1 ? x1 : x0, y1)) + x0 <= x1 ? x1 : x0, y1, + state->strokeAdjust)) != splashClipAllOutside) { if (y0 == y1) { if (x0 <= x1) { - drawSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside); + drawStrokeSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside); } else { - drawSpan(&pipe, x1, x0, y0, clipRes == splashClipAllInside); + drawStrokeSpan(&pipe, x1, x0, y0, clipRes == splashClipAllInside); } } else { dxdy = seg->dxdy; - if (y0 < state->clip->getYMinI()) { - y0 = state->clip->getYMinI(); + y = state->clip->getYMinI(state->strokeAdjust); + if (y0 < y) { + y0 = y; x0 = splashFloor(seg->x0 + ((SplashCoord)y0 - seg->y0) * dxdy); } - if (y1 > state->clip->getYMaxI()) { - y1 = state->clip->getYMaxI(); + y = state->clip->getYMaxI(state->strokeAdjust); + if (y1 > y) { + y1 = y; x1 = splashFloor(seg->x0 + ((SplashCoord)y1 - seg->y0) * dxdy); } if (x0 <= x1) { @@ -1723,9 +2430,10 @@ void Splash::strokeNarrow(SplashPath *path) { xb = x1 + 1; } if (xa == xb) { - drawPixel(&pipe, xa, y, clipRes == splashClipAllInside); + drawStrokeSpan(&pipe, xa, xa, y, clipRes == splashClipAllInside); } else { - drawSpan(&pipe, xa, xb - 1, y, clipRes == splashClipAllInside); + drawStrokeSpan(&pipe, xa, xb - 1, y, + clipRes == splashClipAllInside); } xa = xb; } @@ -1739,9 +2447,10 @@ void Splash::strokeNarrow(SplashPath *path) { xb = x1 - 1; } if (xa == xb) { - drawPixel(&pipe, xa, y, clipRes == splashClipAllInside); + drawStrokeSpan(&pipe, xa, xa, y, clipRes == splashClipAllInside); } else { - drawSpan(&pipe, xb + 1, xa, y, clipRes == splashClipAllInside); + drawStrokeSpan(&pipe, xb + 1, xa, y, + clipRes == splashClipAllInside); } xa = xb; } @@ -1762,6 +2471,32 @@ void Splash::strokeNarrow(SplashPath *path) { delete xPath; } +void Splash::drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, + GBool noClip) { + int x; + + x = state->clip->getXMinI(state->strokeAdjust); + if (x > x0) { + x0 = x; + } + x = state->clip->getXMaxI(state->strokeAdjust); + if (x < x1) { + x1 = x; + } + if (x0 > x1) { + return; + } + for (x = x0; x <= x1; ++x) { + scanBuf[x] = 0xff; + } + if (!noClip) { + if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1, state->strokeAdjust)) { + return; + } + } + (this->*pipe->run)(pipe, x0, x1, y, scanBuf + x0, NULL); +} + void Splash::strokeWide(SplashPath *path, SplashCoord w) { SplashPath *path2; @@ -2012,10 +2747,11 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, SplashPattern *pattern, SplashCoord alpha) { SplashPipe pipe; + SplashPath *path2; SplashXPath *xPath; SplashXPathScanner *scanner; - int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; - SplashClipResult clipRes, clipRes2; + int xMin, yMin, xMax, yMax, x, y, t; + SplashClipResult clipRes; if (path->length == 0) { return splashErrEmptyPath; @@ -2025,85 +2761,68 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, return splashOk; } - // add stroke adjustment hints for filled rectangles -- this only - // applies to paths that consist of a single subpath - // (this appears to match Acrobat's behavior) - if (state->strokeAdjust && !path->hints) { - int n; - n = path->getLength(); - if (n == 4 && - !(path->flags[0] & splashPathClosed) && - !(path->flags[1] & splashPathLast) && - !(path->flags[2] & splashPathLast)) { - path->close(gTrue); - path->addStrokeAdjustHint(0, 2, 0, 4); - path->addStrokeAdjustHint(1, 3, 0, 4); - } else if (n == 5 && - (path->flags[0] & splashPathClosed) && - !(path->flags[1] & splashPathLast) && - !(path->flags[2] & splashPathLast) && - !(path->flags[3] & splashPathLast)) { - path->addStrokeAdjustHint(0, 2, 0, 4); - path->addStrokeAdjustHint(1, 3, 0, 4); - } - } + path2 = tweakFillPath(path); - xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue); - if (vectorAntialias && !inShading) { - xPath->aaScale(); - } - xPath->sort(); - yMinI = state->clip->getYMinI(); - yMaxI = state->clip->getYMaxI(); - if (vectorAntialias && !inShading) { - yMinI = yMinI * splashAASize; - yMaxI = (yMaxI + 1) * splashAASize - 1; + xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue); + if (path2 != path) { + delete path2; } - scanner = new SplashXPathScanner(xPath, eo, yMinI, yMaxI); - - // get the min and max x and y values - if (vectorAntialias && !inShading) { - scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI); - } else { - scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); + xMin = xPath->getXMin(); + yMin = xPath->getYMin(); + xMax = xPath->getXMax(); + yMax = xPath->getYMax(); + if (xMin > xMax || yMin > yMax) { + delete xPath; + return splashOk; } + scanner = new SplashXPathScanner(xPath, eo, yMin, yMax); // check clipping - if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) + if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax, + state->strokeAdjust)) != splashClipAllOutside) { - if (scanner->hasPartialClip()) { - clipRes = splashClipPartial; + + if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) { + xMin = t; + } + if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) { + xMax = t; + } + if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) { + yMin = t; + } + if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) { + yMax = t; + } + if (xMin > xMax || yMin > yMax) { + delete scanner; + delete xPath; + return splashOk; } - pipeInit(&pipe, 0, yMinI, pattern, NULL, (Guchar)splashRound(alpha * 255), - vectorAntialias && !inShading, gFalse); + pipeInit(&pipe, pattern, (Guchar)splashRound(alpha * 255), + gTrue, gFalse); // draw the spans if (vectorAntialias && !inShading) { - for (y = yMinI; y <= yMaxI; ++y) { - scanner->renderAALine(aaBuf, &x0, &x1, y); + for (y = yMin; y <= yMax; ++y) { + scanner->getSpan(scanBuf, y, xMin, xMax); if (clipRes != splashClipAllInside) { - state->clip->clipAALine(aaBuf, &x0, &x1, y); + state->clip->clipSpan(scanBuf, y, xMin, xMax, state->strokeAdjust); + } + for (x = xMin; x <= xMax; ++x) { + scanBuf[x] = aaGamma[scanBuf[x]]; } - drawAALine(&pipe, x0, x1, y); + (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); } } else { - for (y = yMinI; y <= yMaxI; ++y) { - while (scanner->getNextSpan(y, &x0, &x1)) { - if (clipRes == splashClipAllInside) { - drawSpan(&pipe, x0, x1, y, gTrue); - } else { - // limit the x range - if (x0 < state->clip->getXMinI()) { - x0 = state->clip->getXMinI(); - } - if (x1 > state->clip->getXMaxI()) { - x1 = state->clip->getXMaxI(); - } - clipRes2 = state->clip->testSpan(x0, x1, y); - drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); - } + for (y = yMin; y <= yMax; ++y) { + scanner->getSpanBinary(scanBuf, y, xMin, xMax); + if (clipRes != splashClipAllInside) { + state->clip->clipSpanBinary(scanBuf, y, xMin, xMax, + state->strokeAdjust); } + (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); } } } @@ -2114,6 +2833,110 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, return splashOk; } +// Applies various tweaks to a fill path: +// (1) add stroke adjust hints to a filled rectangle +// (2) applies a minimum width to a zero-width filled rectangle (so +// stroke adjustment works correctly +// (3) convert a degenerate fill ('moveto lineto fill' and 'moveto +// lineto closepath fill') to a minimum-width filled rectangle +// +// These tweaks only apply to paths with a single subpath. +// +// Returns either the unchanged input path or a new path (in which +// case the returned path must be deleted by the caller). +SplashPath *Splash::tweakFillPath(SplashPath *path) { + SplashPath *path2; + SplashCoord xx0, yy0, xx1, yy1, dx, dy, d, wx, wy, w; + int n; + + if (!state->strokeAdjust || path->hints) { + return path; + } + + n = path->getLength(); + if (!((n == 2) || + (n == 3 && + path->flags[1] == 0) || + (n == 4 && + path->flags[1] == 0 && + path->flags[2] == 0) || + (n == 5 && + path->flags[1] == 0 && + path->flags[2] == 0 && + path->flags[3] == 0))) { + return path; + } + + path2 = path; + + // degenerate fill (2 or 3 points) or rectangle of (nearly) zero + // width --> replace with a min-width rectangle and hint + if (n == 2 || + (n == 3 && (path->flags[0] & splashPathClosed)) || + (n == 3 && (splashAbs(path->pts[0].x - path->pts[2].x) < 0.001 && + splashAbs(path->pts[0].y - path->pts[2].y) < 0.001)) || + ((n == 4 || + (n == 5 && (path->flags[0] & splashPathClosed))) && + ((splashAbs(path->pts[0].x - path->pts[1].x) < 0.001 && + splashAbs(path->pts[0].y - path->pts[1].y) < 0.001 && + splashAbs(path->pts[2].x - path->pts[3].x) < 0.001 && + splashAbs(path->pts[2].y - path->pts[3].y) < 0.001) || + (splashAbs(path->pts[0].x - path->pts[3].x) < 0.001 && + splashAbs(path->pts[0].y - path->pts[3].y) < 0.001 && + splashAbs(path->pts[1].x - path->pts[2].x) < 0.001 && + splashAbs(path->pts[1].y - path->pts[2].y) < 0.001)))) { + wx = state->matrix[0] + state->matrix[2]; + wy = state->matrix[1] + state->matrix[3]; + w = sqrt(wx*wx + wy*wy); + if (w < 0.001) { + w = 0; + } else { + // min width is 0.1 -- this constant is minWidth * sqrt(2) + w = (SplashCoord)0.1414 / w; + } + xx0 = path->pts[0].x; + yy0 = path->pts[0].y; + if (n <= 3) { + xx1 = path->pts[1].x; + yy1 = path->pts[1].y; + } else { + xx1 = path->pts[2].x; + yy1 = path->pts[2].y; + } + dx = xx1 - xx0; + dy = yy1 - yy0; + d = sqrt(dx * dx + dy * dy); + if (d < 0.001) { + d = 0; + } else { + d = w / d; + } + dx *= d; + dy *= d; + path2 = new SplashPath(); + path2->moveTo(xx0 + dy, yy0 - dx); + path2->lineTo(xx1 + dy, yy1 - dx); + path2->lineTo(xx1 - dy, yy1 + dx); + path2->lineTo(xx0 - dy, yy0 + dx); + path2->close(gTrue); + path2->addStrokeAdjustHint(0, 2, 0, 4); + path2->addStrokeAdjustHint(1, 3, 0, 4); + + // unclosed rectangle --> close and hint + } else if (n == 4 && !(path->flags[0] & splashPathClosed)) { + path2->close(gTrue); + path2->addStrokeAdjustHint(0, 2, 0, 4); + path2->addStrokeAdjustHint(1, 3, 0, 4); + + // closed rectangle --> hint + } else if (n == 5 && (path->flags[0] & splashPathClosed)) { + path2->addStrokeAdjustHint(0, 2, 0, 4); + path2->addStrokeAdjustHint(1, 3, 0, 4); + } + + return path2; +} + GBool Splash::pathAllOutside(SplashPath *path) { SplashCoord xMin1, yMin1, xMax1, yMax1; SplashCoord xMin2, yMin2, xMax2, yMax2; @@ -2177,7 +3000,8 @@ GBool Splash::pathAllOutside(SplashPath *path) { xMaxI = splashFloor(xMax2); yMaxI = splashFloor(yMax2); - return state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI) == + return state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI, + state->strokeAdjust) == splashClipAllOutside; } @@ -2185,49 +3009,63 @@ SplashError Splash::xorFill(SplashPath *path, GBool eo) { SplashPipe pipe; SplashXPath *xPath; SplashXPathScanner *scanner; - int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; - SplashClipResult clipRes, clipRes2; + int xMin, yMin, xMax, yMax, y, t; + SplashClipResult clipRes; SplashBlendFunc origBlendFunc; if (path->length == 0) { return splashErrEmptyPath; } + if (pathAllOutside(path)) { + opClipRes = splashClipAllOutside; + return splashOk; + } xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue); - xPath->sort(); - scanner = new SplashXPathScanner(xPath, eo, state->clip->getYMinI(), - state->clip->getYMaxI()); - - // get the min and max x and y values - scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); + xMin = xPath->getXMin(); + yMin = xPath->getYMin(); + xMax = xPath->getXMax(); + yMax = xPath->getYMax(); + if (xMin > xMax || yMin > yMax) { + delete xPath; + return splashOk; + } + scanner = new SplashXPathScanner(xPath, eo, yMin, yMax); // check clipping - if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) + if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax, + state->strokeAdjust)) != splashClipAllOutside) { - if (scanner->hasPartialClip()) { - clipRes = splashClipPartial; + + if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) { + xMin = t; + } + if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) { + xMax = t; + } + if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) { + yMin = t; + } + if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) { + yMax = t; + } + if (xMin > xMax || yMin > yMax) { + delete scanner; + delete xPath; + return splashOk; } origBlendFunc = state->blendFunc; state->blendFunc = &blendXor; - pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 255, gFalse, gFalse); + pipeInit(&pipe, state->fillPattern, 255, gTrue, gFalse); // draw the spans - for (y = yMinI; y <= yMaxI; ++y) { - while (scanner->getNextSpan(y, &x0, &x1)) { - if (clipRes == splashClipAllInside) { - drawSpan(&pipe, x0, x1, y, gTrue); - } else { - // limit the x range - if (x0 < state->clip->getXMinI()) { - x0 = state->clip->getXMinI(); - } - if (x1 > state->clip->getXMaxI()) { - x1 = state->clip->getXMaxI(); - } - clipRes2 = state->clip->testSpan(x0, x1, y); - drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); - } + for (y = yMin; y <= yMax; ++y) { + scanner->getSpanBinary(scanBuf, y, xMin, xMax); + if (clipRes != splashClipAllInside) { + state->clip->clipSpanBinary(scanBuf, y, xMin, xMax, + state->strokeAdjust); } + (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); } state->blendFunc = origBlendFunc; } @@ -2278,105 +3116,86 @@ SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y, SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { SplashPipe pipe; SplashClipResult clipRes; - GBool noClip; - int alpha0; Guchar alpha; Guchar *p; - int x1, y1, xx, xx1, yy; - - if ((clipRes = state->clip->testRect(x0 - glyph->x, - y0 - glyph->y, - x0 - glyph->x + glyph->w - 1, - y0 - glyph->y + glyph->h - 1)) + int xMin, yMin, xMax, yMax; + int x, y, xg, yg, xx, t; + + xg = x0 - glyph->x; + yg = y0 - glyph->y; + xMin = xg; + xMax = xg + glyph->w - 1; + yMin = yg; + yMax = yg + glyph->h - 1; + if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax, + state->strokeAdjust)) != splashClipAllOutside) { - noClip = clipRes == splashClipAllInside; - - if (noClip) { + pipeInit(&pipe, state->fillPattern, + (Guchar)splashRound(state->fillAlpha * 255), + gTrue, gFalse); + if (clipRes == splashClipAllInside) { if (glyph->aa) { - pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse); p = glyph->data; - for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { - pipeSetXY(&pipe, x0 - glyph->x, y1); - for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { - alpha = *p++; - if (alpha != 0) { - pipe.shape = alpha; - (this->*pipe.run)(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - } + for (y = yMin; y <= yMax; ++y) { + (this->*pipe.run)(&pipe, xMin, xMax, y, + glyph->data + (y - yMin) * glyph->w, NULL); } } else { - pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gFalse, gFalse); p = glyph->data; - for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { - pipeSetXY(&pipe, x0 - glyph->x, y1); - for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { - alpha0 = *p++; - for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { - if (alpha0 & 0x80) { - (this->*pipe.run)(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - alpha0 <<= 1; + for (y = yMin; y <= yMax; ++y) { + for (x = xMin; x <= xMax; x += 8) { + alpha = *p++; + for (xx = 0; xx < 8 && x + xx <= xMax; ++xx) { + scanBuf[x + xx] = (alpha & 0x80) ? 0xff : 0x00; + alpha <<= 1; } } + (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); } } } else { - if (glyph->aa) { - pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse); - p = glyph->data; - for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { - pipeSetXY(&pipe, x0 - glyph->x, y1); - for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { - if (state->clip->test(x1, y1)) { - alpha = *p++; - if (alpha != 0) { - pipe.shape = alpha; - (this->*pipe.run)(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - } else { - pipeIncX(&pipe); - ++p; - } + if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) { + xMin = t; + } + if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) { + xMax = t; + } + if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) { + yMin = t; + } + if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) { + yMax = t; + } + if (xMin <= xMax && yMin <= yMax) { + if (glyph->aa) { + for (y = yMin; y <= yMax; ++y) { + p = glyph->data + (y - yg) * glyph->w + (xMin - xg); + memcpy(scanBuf + xMin, p, xMax - xMin + 1); + state->clip->clipSpan(scanBuf, y, xMin, xMax, + state->strokeAdjust); + (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); } - } - } else { - pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gFalse, gFalse); - p = glyph->data; - for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { - pipeSetXY(&pipe, x0 - glyph->x, y1); - for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { - alpha0 = *p++; - for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { - if (state->clip->test(x1, y1)) { - if (alpha0 & 0x80) { - (this->*pipe.run)(&pipe); - updateModX(x1); - updateModY(y1); - } else { - pipeIncX(&pipe); - } - } else { - pipeIncX(&pipe); + } else { + for (y = yMin; y <= yMax; ++y) { + p = glyph->data + (y - yg) * ((glyph->w + 7) >> 3) + + ((xMin - xg) >> 3); + alpha = *p++; + xx = (xMin - xg) & 7; + alpha <<= xx; + for (x = xMin; xx < 8 && x <= xMax; ++x, ++xx) { + scanBuf[x] = (alpha & 0x80) ? 255 : 0; + alpha <<= 1; + } + for (; x <= xMax; x += 8) { + alpha = *p++; + for (xx = 0; xx < 8 && x + xx <= xMax; ++xx) { + scanBuf[x + xx] = (alpha & 0x80) ? 255 : 0; + alpha <<= 1; } - alpha0 <<= 1; } + state->clip->clipSpanBinary(scanBuf, y, xMin, xMax, + state->strokeAdjust); + (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL); } } } @@ -2387,12 +3206,28 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { return splashOk; } +void Splash::getImageBounds(SplashCoord xyMin, SplashCoord xyMax, + int *xyMinI, int *xyMaxI) { + if (state->strokeAdjust) { + splashStrokeAdjust(xyMin, xyMax, xyMinI, xyMaxI); + } else { + *xyMinI = splashFloor(xyMin); + *xyMaxI = splashFloor(xyMax); + if (*xyMaxI <= *xyMinI) { + *xyMaxI = *xyMinI + 1; + } + } +} + +// The glyphMode flag is not currently used, but may be useful if the +// stroke adjustment behavior is changed. SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, int w, int h, SplashCoord *mat, - GBool glyphMode) { + GBool glyphMode, GBool interpolate) { SplashBitmap *scaledMask; SplashClipResult clipRes; GBool minorAxisZero; + SplashCoord wSize, hSize, t0, t1; int x0, y0, x1, y1, scaledWidth, scaledHeight; if (debugMode) { @@ -2406,68 +3241,269 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, return splashErrSingularMatrix; } - minorAxisZero = mat[1] == 0 && mat[2] == 0; + minorAxisZero = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; + + // rough estimate of size of scaled mask + t0 = splashAbs(mat[0]); + t1 = splashAbs(mat[1]); + wSize = t0 > t1 ? t0 : t1; + t0 = splashAbs(mat[2]); + t1 = splashAbs(mat[3]); + hSize = t0 > t1 ? t0 : t1; + + // stream-mode upscaling -- this is slower, so we only use it if the + // upscaled mask is large (in which case clipping should remove many + // pixels) + if (wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) { + upscaleMask(src, srcData, w, h, mat, glyphMode, interpolate); // scaling only - if (mat[0] > 0 && minorAxisZero && mat[3] > 0) { - x0 = imgCoordMungeLowerC(mat[4], glyphMode); - y0 = imgCoordMungeLowerC(mat[5], glyphMode); - x1 = imgCoordMungeUpperC(mat[0] + mat[4], glyphMode); - y1 = imgCoordMungeUpperC(mat[3] + mat[5], glyphMode); - // make sure narrow images cover at least one pixel - if (x0 == x1) { - ++x1; - } - if (y0 == y1) { - ++y1; - } - clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1); + } else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) { + getImageBounds(mat[4], mat[0] + mat[4], &x0, &x1); + getImageBounds(mat[5], mat[3] + mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); opClipRes = clipRes; if (clipRes != splashClipAllOutside) { scaledWidth = x1 - x0; scaledHeight = y1 - y0; - scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight); + scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight, + interpolate); blitMask(scaledMask, x0, y0, clipRes); delete scaledMask; } // scaling plus vertical flip } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) { - x0 = imgCoordMungeLowerC(mat[4], glyphMode); - y0 = imgCoordMungeLowerC(mat[3] + mat[5], glyphMode); - x1 = imgCoordMungeUpperC(mat[0] + mat[4], glyphMode); - y1 = imgCoordMungeUpperC(mat[5], glyphMode); - // make sure narrow images cover at least one pixel - if (x0 == x1) { - ++x1; - } - if (y0 == y1) { - ++y1; - } - clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1); + getImageBounds(mat[4], mat[0] + mat[4], &x0, &x1); + getImageBounds(mat[3] + mat[5], mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); + opClipRes = clipRes; + if (clipRes != splashClipAllOutside) { + scaledWidth = x1 - x0; + scaledHeight = y1 - y0; + scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight, + interpolate); + vertFlipImage(scaledMask, scaledWidth, scaledHeight, 1); + blitMask(scaledMask, x0, y0, clipRes); + delete scaledMask; + } + + // scaling plus horizontal flip + } else if (mat[0] < 0 && minorAxisZero && mat[3] > 0) { + getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1); + getImageBounds(mat[5], mat[3] + mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); + opClipRes = clipRes; + if (clipRes != splashClipAllOutside) { + scaledWidth = x1 - x0; + scaledHeight = y1 - y0; + scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight, + interpolate); + horizFlipImage(scaledMask, scaledWidth, scaledHeight, 1); + blitMask(scaledMask, x0, y0, clipRes); + delete scaledMask; + } + + // scaling plus horizontal and vertical flips + } else if (mat[0] < 0 && minorAxisZero && mat[3] < 0) { + getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1); + getImageBounds(mat[3] + mat[5], mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); opClipRes = clipRes; if (clipRes != splashClipAllOutside) { scaledWidth = x1 - x0; scaledHeight = y1 - y0; - scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight); + scaledMask = scaleMask(src, srcData, w, h, scaledWidth, scaledHeight, + interpolate); vertFlipImage(scaledMask, scaledWidth, scaledHeight, 1); + horizFlipImage(scaledMask, scaledWidth, scaledHeight, 1); blitMask(scaledMask, x0, y0, clipRes); delete scaledMask; } // all other cases } else { - arbitraryTransformMask(src, srcData, w, h, mat, glyphMode); + arbitraryTransformMask(src, srcData, w, h, mat, glyphMode, interpolate); } return splashOk; } +// The glyphMode flag is not currently used, but may be useful if the +// stroke adjustment behavior is changed. +void Splash::upscaleMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool glyphMode, + GBool interpolate) { + SplashClipResult clipRes; + SplashPipe pipe; + Guchar *unscaledImage, *p; + SplashCoord xMin, yMin, xMax, yMax, t; + SplashCoord mi0, mi1, mi2, mi3, mi4, mi5, det; + SplashCoord ix, iy, sx, sy, pix0, pix1; + int xMinI, yMinI, xMaxI, yMaxI, x, y, x0, y0, x1, y1, tt; + + // compute the bbox of the target quadrilateral + xMin = xMax = mat[4]; + t = mat[2] + mat[4]; + if (t < xMin) { + xMin = t; + } else if (t > xMax) { + xMax = t; + } + t = mat[0] + mat[2] + mat[4]; + if (t < xMin) { + xMin = t; + } else if (t > xMax) { + xMax = t; + } + t = mat[0] + mat[4]; + if (t < xMin) { + xMin = t; + } else if (t > xMax) { + xMax = t; + } + getImageBounds(xMin, xMax, &xMinI, &xMaxI); + yMin = yMax = mat[5]; + t = mat[3] + mat[5]; + if (t < yMin) { + yMin = t; + } else if (t > yMax) { + yMax = t; + } + t = mat[1] + mat[3] + mat[5]; + if (t < yMin) { + yMin = t; + } else if (t > yMax) { + yMax = t; + } + t = mat[1] + mat[5]; + if (t < yMin) { + yMin = t; + } else if (t > yMax) { + yMax = t; + } + getImageBounds(yMin, yMax, &yMinI, &yMaxI); + + // clipping + clipRes = state->clip->testRect(xMinI, yMinI, xMaxI - 1, yMaxI - 1, + state->strokeAdjust); + opClipRes = clipRes; + if (clipRes == splashClipAllOutside) { + return; + } + if (clipRes != splashClipAllInside) { + if ((tt = state->clip->getXMinI(state->strokeAdjust)) > xMinI) { + xMinI = tt; + } + if ((tt = state->clip->getXMaxI(state->strokeAdjust) + 1) < xMaxI) { + xMaxI = tt; + } + if ((tt = state->clip->getYMinI(state->strokeAdjust)) > yMinI) { + yMinI = tt; + } + if ((tt = state->clip->getYMaxI(state->strokeAdjust) + 1) < yMaxI) { + yMaxI = tt; + } + } + + // invert the matrix + det = mat[0] * mat[3] - mat[1] * mat[2]; + if (splashAbs(det) < 1e-6) { + // this should be caught by the singular matrix check in fillImageMask + return; + } + det = (SplashCoord)1 / det; + mi0 = det * mat[3] * srcWidth; + mi1 = -det * mat[1] * srcHeight; + mi2 = -det * mat[2] * srcWidth; + mi3 = det * mat[0] * srcHeight; + mi4 = det * (mat[2] * mat[5] - mat[3] * mat[4]) * srcWidth; + mi5 = -det * (mat[0] * mat[5] - mat[1] * mat[4]) * srcHeight; + + // grab the image + unscaledImage = (Guchar *)gmallocn(srcWidth, srcHeight); + for (y = 0, p = unscaledImage; y < srcHeight; ++y, p += srcWidth) { + (*src)(srcData, p); + for (x = 0; x < srcWidth; ++x) { + p[x] *= 255; + } + } + + // draw it + pipeInit(&pipe, state->fillPattern, + (Guchar)splashRound(state->fillAlpha * 255), + gTrue, gFalse); + for (y = yMinI; y < yMaxI; ++y) { + for (x = xMinI; x < xMaxI; ++x) { + ix = ((SplashCoord)x + 0.5) * mi0 + ((SplashCoord)y + 0.5) * mi2 + mi4; + iy = ((SplashCoord)x + 0.5) * mi1 + ((SplashCoord)y + 0.5) * mi3 + mi5; + if (interpolate) { + if (ix >= 0 && ix < srcWidth && iy >= 0 && iy < srcHeight) { + x0 = splashFloor(ix - 0.5); + x1 = x0 + 1; + sx = (ix - 0.5) - x0; + y0 = splashFloor(iy - 0.5); + y1 = y0 + 1; + sy = (iy - 0.5) - y0; + if (x0 < 0) { + x0 = 0; + } + if (x1 >= srcWidth) { + x1 = srcWidth - 1; + } + if (y0 < 0) { + y0 = 0; + } + if (y1 >= srcHeight) { + y1 = srcHeight - 1; + } + pix0 = ((SplashCoord)1 - sx) * unscaledImage[y0 * srcWidth + x0] + + sx * unscaledImage[y0 * srcWidth + x1]; + pix1 = ((SplashCoord)1 - sx) * unscaledImage[y1 * srcWidth + x0] + + sx * unscaledImage[y1 * srcWidth + x1]; + scanBuf[x] = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0 + + sy * pix1); + } else { + scanBuf[x] = 0; + } + } else { + x0 = splashFloor(ix); + y0 = splashFloor(iy); + if (x0 >= 0 && x0 < srcWidth && y0 >= 0 && y0 < srcHeight) { + scanBuf[x] = unscaledImage[y0 * srcWidth + x0]; + } else { + scanBuf[x] = 0; + } + } + } + if (clipRes != splashClipAllInside) { + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, y, xMinI, xMaxI - 1, + state->strokeAdjust); + } else { + state->clip->clipSpanBinary(scanBuf, y, xMinI, xMaxI - 1, + state->strokeAdjust); + } + } + (this->*pipe.run)(&pipe, xMinI, xMaxI - 1, y, scanBuf + xMinI, NULL); + } + + gfree(unscaledImage); +} + +// The glyphMode flag is not currently used, but may be useful if the +// stroke adjustment behavior is changed. void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, int srcWidth, int srcHeight, - SplashCoord *mat, GBool glyphMode) { + SplashCoord *mat, GBool glyphMode, + GBool interpolate) { SplashBitmap *scaledMask; - SplashClipResult clipRes, clipRes2; + SplashClipResult clipRes; SplashPipe pipe; int scaledWidth, scaledHeight, t0, t1; SplashCoord r00, r01, r10, r11, det, ir00, ir01, ir10, ir11; @@ -2484,29 +3520,26 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, vx[3] = mat[0] + mat[4]; vy[3] = mat[1] + mat[5]; // clipping - xMin = imgCoordMungeLowerC(vx[0], glyphMode); - xMax = imgCoordMungeUpperC(vx[0], glyphMode); - yMin = imgCoordMungeLowerC(vy[0], glyphMode); - yMax = imgCoordMungeUpperC(vy[0], glyphMode); + xMin = splashRound(vx[0]); + xMax = splashRound(vx[0]); + yMin = splashRound(vy[0]); + yMax = splashRound(vy[0]); for (i = 1; i < 4; ++i) { - t0 = imgCoordMungeLowerC(vx[i], glyphMode); + t0 = splashRound(vx[i]); if (t0 < xMin) { xMin = t0; - } - t0 = imgCoordMungeUpperC(vx[i], glyphMode); - if (t0 > xMax) { + } else if (t0 > xMax) { xMax = t0; } - t1 = imgCoordMungeLowerC(vy[i], glyphMode); + t1 = splashRound(vy[i]); if (t1 < yMin) { yMin = t1; - } - t1 = imgCoordMungeUpperC(vy[i], glyphMode); - if (t1 > yMax) { + } else if (t1 > yMax) { yMax = t1; } } - clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1); + clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1, + state->strokeAdjust); opClipRes = clipRes; if (clipRes == splashClipAllOutside) { return; @@ -2514,33 +3547,25 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, // compute the scale factors if (mat[0] >= 0) { - t0 = imgCoordMungeUpperC(mat[0] + mat[4], glyphMode) - - imgCoordMungeLowerC(mat[4], glyphMode); + t0 = splashRound(mat[0] + mat[4]) - splashRound(mat[4]); } else { - t0 = imgCoordMungeUpperC(mat[4], glyphMode) - - imgCoordMungeLowerC(mat[0] + mat[4], glyphMode); + t0 = splashRound(mat[4]) - splashRound(mat[0] + mat[4]); } if (mat[1] >= 0) { - t1 = imgCoordMungeUpperC(mat[1] + mat[5], glyphMode) - - imgCoordMungeLowerC(mat[5], glyphMode); + t1 = splashRound(mat[1] + mat[5]) - splashRound(mat[5]); } else { - t1 = imgCoordMungeUpperC(mat[5], glyphMode) - - imgCoordMungeLowerC(mat[1] + mat[5], glyphMode); + t1 = splashRound(mat[5]) - splashRound(mat[1] + mat[5]); } scaledWidth = t0 > t1 ? t0 : t1; if (mat[2] >= 0) { - t0 = imgCoordMungeUpperC(mat[2] + mat[4], glyphMode) - - imgCoordMungeLowerC(mat[4], glyphMode); + t0 = splashRound(mat[2] + mat[4]) - splashRound(mat[4]); } else { - t0 = imgCoordMungeUpperC(mat[4], glyphMode) - - imgCoordMungeLowerC(mat[2] + mat[4], glyphMode); + t0 = splashRound(mat[4]) - splashRound(mat[2] + mat[4]); } if (mat[3] >= 0) { - t1 = imgCoordMungeUpperC(mat[3] + mat[5], glyphMode) - - imgCoordMungeLowerC(mat[5], glyphMode); + t1 = splashRound(mat[3] + mat[5]) - splashRound(mat[5]); } else { - t1 = imgCoordMungeUpperC(mat[5], glyphMode) - - imgCoordMungeLowerC(mat[3] + mat[5], glyphMode); + t1 = splashRound(mat[5]) - splashRound(mat[3] + mat[5]); } scaledHeight = t0 > t1 ? t0 : t1; if (scaledWidth == 0) { @@ -2567,19 +3592,28 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, // scale the input image scaledMask = scaleMask(src, srcData, srcWidth, srcHeight, - scaledWidth, scaledHeight); + scaledWidth, scaledHeight, interpolate); // construct the three sections - i = (vy[2] <= vy[3]) ? 2 : 3; - if (vy[1] <= vy[i]) { + i = 0; + if (vy[1] < vy[i]) { i = 1; } - if (vy[0] < vy[i] || (i != 3 && vy[0] == vy[i])) { - i = 0; + if (vy[2] < vy[i]) { + i = 2; } - if (vy[i] == vy[(i+1) & 3]) { - section[0].y0 = imgCoordMungeLowerC(vy[i], glyphMode); - section[0].y1 = imgCoordMungeUpperC(vy[(i+2) & 3], glyphMode) - 1; + if (vy[3] < vy[i]) { + i = 3; + } + // NB: if using fixed point, 0.000001 will be truncated to zero, + // so these two comparisons must be <=, not < + if (splashAbs(vy[i] - vy[(i-1) & 3]) <= 0.000001 && + vy[(i-1) & 3] < vy[(i+1) & 3]) { + i = (i-1) & 3; + } + if (splashAbs(vy[i] - vy[(i+1) & 3]) <= 0.000001) { + section[0].y0 = splashRound(vy[i]); + section[0].y1 = splashRound(vy[(i+2) & 3]) - 1; if (vx[i] < vx[(i+1) & 3]) { section[0].ia0 = i; section[0].ia1 = (i+3) & 3; @@ -2593,8 +3627,8 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, } nSections = 1; } else { - section[0].y0 = imgCoordMungeLowerC(vy[i], glyphMode); - section[2].y1 = imgCoordMungeUpperC(vy[(i+2) & 3], glyphMode) - 1; + section[0].y0 = splashRound(vy[i]); + section[2].y1 = splashRound(vy[(i+2) & 3]) - 1; section[0].ia0 = section[0].ib0 = i; section[2].ia1 = section[2].ib1 = (i+2) & 3; if (vx[(i+1) & 3] < vx[(i+3) & 3]) { @@ -2605,8 +3639,8 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, section[0].ib1 = section[2].ib0 = (i+1) & 3; } if (vy[(i+1) & 3] < vy[(i+3) & 3]) { - section[1].y0 = imgCoordMungeLowerC(vy[(i+1) & 3], glyphMode); - section[2].y0 = imgCoordMungeUpperC(vy[(i+3) & 3], glyphMode); + section[1].y0 = splashRound(vy[(i+1) & 3]); + section[2].y0 = splashRound(vy[(i+3) & 3]); if (vx[(i+1) & 3] < vx[(i+3) & 3]) { section[1].ia0 = (i+1) & 3; section[1].ia1 = (i+2) & 3; @@ -2619,8 +3653,8 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, section[1].ib1 = (i+2) & 3; } } else { - section[1].y0 = imgCoordMungeLowerC(vy[(i+3) & 3], glyphMode); - section[2].y0 = imgCoordMungeUpperC(vy[(i+1) & 3], glyphMode); + section[1].y0 = splashRound(vy[(i+3) & 3]); + section[2].y0 = splashRound(vy[(i+1) & 3]); if (vx[(i+1) & 3] < vx[(i+3) & 3]) { section[1].ia0 = i; section[1].ia1 = (i+1) & 3; @@ -2653,11 +3687,9 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, } // initialize the pixel pipe - pipeInit(&pipe, 0, 0, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse); - if (vectorAntialias) { - drawAAPixelInit(); - } + pipeInit(&pipe, state->fillPattern, + (Guchar)splashRound(state->fillAlpha * 255), + gTrue, gFalse); // make sure narrow images cover at least one pixel if (nSections == 1) { @@ -2675,23 +3707,30 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, // scan all pixels inside the target region for (i = 0; i < nSections; ++i) { for (y = section[i].y0; y <= section[i].y1; ++y) { - xa = imgCoordMungeLowerC(section[i].xa0 + - ((SplashCoord)y + 0.5 - section[i].ya0) * - section[i].dxdya, - glyphMode); - xb = imgCoordMungeUpperC(section[i].xb0 + - ((SplashCoord)y + 0.5 - section[i].yb0) * - section[i].dxdyb, - glyphMode); + xa = splashRound(section[i].xa0 + + ((SplashCoord)y + 0.5 - section[i].ya0) * + section[i].dxdya); + xb = splashRound(section[i].xb0 + + ((SplashCoord)y + 0.5 - section[i].yb0) * + section[i].dxdyb); + if (xa > xb) { + continue; + } // make sure narrow images cover at least one pixel if (xa == xb) { ++xb; } - if (clipRes != splashClipAllInside) { - clipRes2 = state->clip->testSpan(xa, xb - 1, y); - } else { - clipRes2 = clipRes; + // check the scanBuf bounds + if (xa >= bitmap->width || xb < 0) { + continue; + } + if (xa < 0) { + xa = 0; } + if (xb > bitmap->width) { + xb = bitmap->width; + } + // get the scan line for (x = xa; x < xb; ++x) { // map (x+0.5, y+0.5) back to the scaled image xx = splashFloor(((SplashCoord)x + 0.5 - mat[4]) * ir00 + @@ -2710,13 +3749,19 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, } else if (yy >= scaledHeight) { yy = scaledHeight - 1; } - pipe.shape = scaledMask->data[yy * scaledWidth + xx]; - if (vectorAntialias && clipRes2 != splashClipAllInside) { - drawAAPixel(&pipe, x, y); + scanBuf[x] = scaledMask->data[yy * scaledWidth + xx]; + } + // clip the scan line + if (clipRes != splashClipAllInside) { + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, y, xa, xb - 1, state->strokeAdjust); } else { - drawPixel(&pipe, x, y, clipRes2 == splashClipAllInside); + state->clip->clipSpanBinary(scanBuf, y, xa, xb - 1, + state->strokeAdjust); } } + // draw the scan line + (this->*pipe.run)(&pipe, xa, xb - 1, y, scanBuf + xa, NULL); } } @@ -2726,7 +3771,8 @@ void Splash::arbitraryTransformMask(SplashImageMaskSource src, void *srcData, // Scale an image mask into a SplashBitmap. SplashBitmap *Splash::scaleMask(SplashImageMaskSource src, void *srcData, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight) { + int scaledWidth, int scaledHeight, + GBool interpolate) { SplashBitmap *dest; dest = new SplashBitmap(scaledWidth, scaledHeight, 1, splashModeMono8, @@ -2744,8 +3790,13 @@ SplashBitmap *Splash::scaleMask(SplashImageMaskSource src, void *srcData, scaleMaskYuXd(src, srcData, srcWidth, srcHeight, scaledWidth, scaledHeight, dest); } else { - scaleMaskYuXu(src, srcData, srcWidth, srcHeight, - scaledWidth, scaledHeight, dest); + if (interpolate) { + scaleMaskYuXuI(src, srcData, srcWidth, srcHeight, + scaledWidth, scaledHeight, dest); + } else { + scaleMaskYuXu(src, srcData, srcWidth, srcHeight, + scaledWidth, scaledHeight, dest); + } } } return dest; @@ -3057,60 +4108,158 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData, gfree(lineBuf); } +void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest) { + Guchar *lineBuf0, *lineBuf1, *tBuf; + Guchar pix; + SplashCoord yr, xr, ys, xs, ySrc, xSrc; + int ySrc0, ySrc1, yBuf, xSrc0, xSrc1, y, x; + Guchar *destPtr; + + // ratios + yr = (SplashCoord)srcHeight / (SplashCoord)scaledHeight; + xr = (SplashCoord)srcWidth / (SplashCoord)scaledWidth; + + // allocate buffers + lineBuf0 = (Guchar *)gmalloc(scaledWidth); + lineBuf1 = (Guchar *)gmalloc(scaledWidth); + + // read first two rows + (*src)(srcData, lineBuf0); + if (srcHeight > 1) { + (*src)(srcData, lineBuf1); + yBuf = 1; + } else { + memcpy(lineBuf1, lineBuf0, srcWidth); + yBuf = 0; + } + + // interpolate first two rows + for (x = scaledWidth - 1; x >= 0; --x) { + xSrc = xr * x; + xSrc0 = splashFloor(xSrc + xr * 0.5 - 0.5); + xSrc1 = xSrc0 + 1; + xs = ((SplashCoord)xSrc1 + 0.5) - (xSrc + xr * 0.5); + if (xSrc0 < 0) { + xSrc0 = 0; + } + if (xSrc1 >= srcWidth) { + xSrc1 = srcWidth - 1; + } + lineBuf0[x] = (Guchar)(int) + ((xs * lineBuf0[xSrc0] + + ((SplashCoord)1 - xs) * lineBuf0[xSrc1]) * 255); + lineBuf1[x] = (Guchar)(int) + ((xs * lineBuf1[xSrc0] + + ((SplashCoord)1 - xs) * lineBuf1[xSrc1]) * 255); + } + + destPtr = dest->data; + for (y = 0; y < scaledHeight; ++y) { + + // compute vertical interpolation parameters + ySrc = yr * y; + ySrc0 = splashFloor(ySrc + yr * 0.5 - 0.5); + ySrc1 = ySrc0 + 1; + ys = ((SplashCoord)ySrc1 + 0.5) - (ySrc + yr * 0.5); + if (ySrc0 < 0) { + ySrc0 = 0; + ys = 1; + } + if (ySrc1 >= srcHeight) { + ySrc1 = srcHeight - 1; + ys = 0; + } + + // read another row (if necessary) + if (ySrc1 > yBuf) { + tBuf = lineBuf0; + lineBuf0 = lineBuf1; + lineBuf1 = tBuf; + (*src)(srcData, lineBuf1); + + // interpolate the row + for (x = scaledWidth - 1; x >= 0; --x) { + xSrc = xr * x; + xSrc0 = splashFloor(xSrc + xr * 0.5 - 0.5); + xSrc1 = xSrc0 + 1; + xs = ((SplashCoord)xSrc1 + 0.5) - (xSrc + xr * 0.5); + if (xSrc0 < 0) { + xSrc0 = 0; + } + if (xSrc1 >= srcWidth) { + xSrc1 = srcWidth - 1; + } + lineBuf1[x] = (Guchar)(int) + ((xs * lineBuf1[xSrc0] + + ((SplashCoord)1 - xs) * lineBuf1[xSrc1]) * 255); + } + + ++yBuf; + } + + // do the vertical interpolation + for (x = 0; x < scaledWidth; ++x) { + + pix = (Guchar)(int)(ys * lineBuf0[x] + + ((SplashCoord)1 - ys) * lineBuf1[x]); + + // store the pixel + *destPtr++ = pix; + } + } + + gfree(lineBuf1); + gfree(lineBuf0); +} + void Splash::blitMask(SplashBitmap *src, int xDest, int yDest, SplashClipResult clipRes) { SplashPipe pipe; - Guchar *p; - int w, h, x, y; + int w, h, x0, x1, y0, y1, y, t; w = src->getWidth(); h = src->getHeight(); - if (vectorAntialias && clipRes != splashClipAllInside) { - pipeInit(&pipe, xDest, yDest, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse); - drawAAPixelInit(); - p = src->getDataPtr(); + pipeInit(&pipe, state->fillPattern, + (Guchar)splashRound(state->fillAlpha * 255), + gTrue, gFalse); + if (clipRes == splashClipAllInside) { for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - pipe.shape = *p++; - drawAAPixel(&pipe, xDest + x, yDest + y); - } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + src->getDataPtr() + y * w, NULL); } } else { - pipeInit(&pipe, xDest, yDest, state->fillPattern, NULL, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse); - p = src->getDataPtr(); - if (clipRes == splashClipAllInside) { - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - if (*p) { - pipe.shape = *p; - (this->*pipe.run)(&pipe); - } else { - pipeIncX(&pipe); - } - ++p; - } - } - updateModX(xDest); - updateModX(xDest + w - 1); - updateModY(yDest); - updateModY(yDest + h - 1); - } else { - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - if (*p && state->clip->test(xDest + x, yDest + y)) { - pipe.shape = *p; - (this->*pipe.run)(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); - } - ++p; + x0 = xDest; + if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) { + x0 = t; + } + x1 = xDest + w; + if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) { + x1 = t; + } + y0 = yDest; + if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) { + y0 = t; + } + y1 = yDest + h; + if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) { + y1 = t; + } + if (x0 < x1 && y0 < y1) { + for (y = y0; y < y1; ++y) { + memcpy(scanBuf + x0, + src->getDataPtr() + (y - yDest) * w + (x0 - xDest), + x1 - x0); + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, y, x0, x1 - 1, + state->strokeAdjust); + } else { + state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1, + state->strokeAdjust); } + (this->*pipe.run)(&pipe, x0, x1 - 1, y, scanBuf + x0, NULL); } } } @@ -3118,11 +4267,13 @@ void Splash::blitMask(SplashBitmap *src, int xDest, int yDest, SplashError Splash::drawImage(SplashImageSource src, void *srcData, SplashColorMode srcMode, GBool srcAlpha, - int w, int h, SplashCoord *mat) { + int w, int h, SplashCoord *mat, + GBool interpolate) { GBool ok; SplashBitmap *scaledImg; SplashClipResult clipRes; GBool minorAxisZero; + SplashCoord wSize, hSize, t0, t1; int x0, y0, x1, y1, scaledWidth, scaledHeight; int nComps; @@ -3142,11 +4293,8 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, nComps = 1; break; case splashModeRGB8: - ok = srcMode == splashModeRGB8; - nComps = 3; - break; case splashModeBGR8: - ok = srcMode == splashModeBGR8; + ok = srcMode == splashModeRGB8; nComps = 3; break; #if SPLASH_CMYK @@ -3168,60 +4316,87 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, return splashErrSingularMatrix; } - minorAxisZero = mat[1] == 0 && mat[2] == 0; + minorAxisZero = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; + + // rough estimate of size of scaled image + t0 = splashAbs(mat[0]); + t1 = splashAbs(mat[1]); + wSize = t0 > t1 ? t0 : t1; + t0 = splashAbs(mat[2]); + t1 = splashAbs(mat[3]); + hSize = t0 > t1 ? t0 : t1; + + // stream-mode upscaling -- this is slower, so we only use it if the + // upscaled image is large (in which case clipping should remove + // many pixels) + if (wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) { + upscaleImage(src, srcData, srcMode, nComps, srcAlpha, + w, h, mat, interpolate); // scaling only - if (mat[0] > 0 && minorAxisZero && mat[3] > 0) { - x0 = imgCoordMungeLower(mat[4]); - y0 = imgCoordMungeLower(mat[5]); - x1 = imgCoordMungeUpper(mat[0] + mat[4]); - y1 = imgCoordMungeUpper(mat[3] + mat[5]); - // make sure narrow images cover at least one pixel - if (x0 == x1) { - ++x1; - } - if (y0 == y1) { - ++y1; - } - clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1); + } else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) { + getImageBounds(mat[4], mat[0] + mat[4], &x0, &x1); + getImageBounds(mat[5], mat[3] + mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); opClipRes = clipRes; if (clipRes != splashClipAllOutside) { scaledWidth = x1 - x0; scaledHeight = y1 - y0; scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, w, h, - scaledWidth, scaledHeight); + scaledWidth, scaledHeight, interpolate); blitImage(scaledImg, srcAlpha, x0, y0, clipRes); delete scaledImg; } // scaling plus vertical flip } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) { - x0 = imgCoordMungeLower(mat[4]); - y0 = imgCoordMungeLower(mat[3] + mat[5]); - x1 = imgCoordMungeUpper(mat[0] + mat[4]); - y1 = imgCoordMungeUpper(mat[5]); - if (x0 == x1) { - if (mat[4] + mat[0] * 0.5 < x0) { - --x0; - } else { - ++x1; - } + getImageBounds(mat[4], mat[0] + mat[4], &x0, &x1); + getImageBounds(mat[3] + mat[5], mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); + opClipRes = clipRes; + if (clipRes != splashClipAllOutside) { + scaledWidth = x1 - x0; + scaledHeight = y1 - y0; + scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, w, h, + scaledWidth, scaledHeight, interpolate); + vertFlipImage(scaledImg, scaledWidth, scaledHeight, nComps); + blitImage(scaledImg, srcAlpha, x0, y0, clipRes); + delete scaledImg; } - if (y0 == y1) { - if (mat[5] + mat[1] * 0.5 < y0) { - --y0; - } else { - ++y1; - } + + // scaling plus horizontal flip + } else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) { + getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1); + getImageBounds(mat[5], mat[3] + mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); + opClipRes = clipRes; + if (clipRes != splashClipAllOutside) { + scaledWidth = x1 - x0; + scaledHeight = y1 - y0; + scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, w, h, + scaledWidth, scaledHeight, interpolate); + horizFlipImage(scaledImg, scaledWidth, scaledHeight, nComps); + blitImage(scaledImg, srcAlpha, x0, y0, clipRes); + delete scaledImg; } - clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1); + + // scaling plus horizontal and vertical flips + } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) { + getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1); + getImageBounds(mat[3] + mat[5], mat[5], &y0, &y1); + clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1, + state->strokeAdjust); opClipRes = clipRes; if (clipRes != splashClipAllOutside) { scaledWidth = x1 - x0; scaledHeight = y1 - y0; scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, w, h, - scaledWidth, scaledHeight); + scaledWidth, scaledHeight, interpolate); vertFlipImage(scaledImg, scaledWidth, scaledHeight, nComps); + horizFlipImage(scaledImg, scaledWidth, scaledHeight, nComps); blitImage(scaledImg, srcAlpha, x0, y0, clipRes); delete scaledImg; } @@ -3229,21 +4404,227 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, // all other cases } else { arbitraryTransformImage(src, srcData, srcMode, nComps, srcAlpha, - w, h, mat); + w, h, mat, interpolate); } return splashOk; } +void Splash::upscaleImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + SplashCoord *mat, GBool interpolate) { + SplashClipResult clipRes; + SplashPipe pipe; + SplashColorPtr unscaledImage, pixelBuf, p, q, q00, q01, q10, q11; + Guchar *unscaledAlpha, *alphaPtr; + SplashCoord xMin, yMin, xMax, yMax, t; + SplashCoord mi0, mi1, mi2, mi3, mi4, mi5, det; + SplashCoord ix, iy, sx, sy, pix0, pix1; + int rowSize, xMinI, yMinI, xMaxI, yMaxI, x, y, x0, y0, x1, y1, tt, i; + + // compute the bbox of the target quadrilateral + xMin = xMax = mat[4]; + t = mat[2] + mat[4]; + if (t < xMin) { + xMin = t; + } else if (t > xMax) { + xMax = t; + } + t = mat[0] + mat[2] + mat[4]; + if (t < xMin) { + xMin = t; + } else if (t > xMax) { + xMax = t; + } + t = mat[0] + mat[4]; + if (t < xMin) { + xMin = t; + } else if (t > xMax) { + xMax = t; + } + getImageBounds(xMin, xMax, &xMinI, &xMaxI); + yMin = yMax = mat[5]; + t = mat[3] + mat[5]; + if (t < yMin) { + yMin = t; + } else if (t > yMax) { + yMax = t; + } + t = mat[1] + mat[3] + mat[5]; + if (t < yMin) { + yMin = t; + } else if (t > yMax) { + yMax = t; + } + t = mat[1] + mat[5]; + if (t < yMin) { + yMin = t; + } else if (t > yMax) { + yMax = t; + } + getImageBounds(yMin, yMax, &yMinI, &yMaxI); + + // clipping + clipRes = state->clip->testRect(xMinI, yMinI, xMaxI - 1, yMaxI - 1, + state->strokeAdjust); + opClipRes = clipRes; + if (clipRes == splashClipAllOutside) { + return; + } + if (clipRes != splashClipAllInside) { + if ((tt = state->clip->getXMinI(state->strokeAdjust)) > xMinI) { + xMinI = tt; + } + if ((tt = state->clip->getXMaxI(state->strokeAdjust) + 1) < xMaxI) { + xMaxI = tt; + } + if ((tt = state->clip->getYMinI(state->strokeAdjust)) > yMinI) { + yMinI = tt; + } + if ((tt = state->clip->getYMaxI(state->strokeAdjust) + 1) < yMaxI) { + yMaxI = tt; + } + } + + // invert the matrix + det = mat[0] * mat[3] - mat[1] * mat[2]; + if (splashAbs(det) < 1e-6) { + // this should be caught by the singular matrix check in fillImageMask + return; + } + det = (SplashCoord)1 / det; + mi0 = det * mat[3] * srcWidth; + mi1 = -det * mat[1] * srcHeight; + mi2 = -det * mat[2] * srcWidth; + mi3 = det * mat[0] * srcHeight; + mi4 = det * (mat[2] * mat[5] - mat[3] * mat[4]) * srcWidth; + mi5 = -det * (mat[0] * mat[5] - mat[1] * mat[4]) * srcHeight; + + // grab the image + if (srcWidth > INT_MAX / nComps) { + rowSize = -1; + } else { + rowSize = srcWidth * nComps; + } + unscaledImage = (SplashColorPtr)gmallocn(srcHeight, rowSize); + if (srcAlpha) { + unscaledAlpha = (Guchar *)gmallocn(srcHeight, srcWidth); + for (y = 0, p = unscaledImage, alphaPtr = unscaledAlpha; + y < srcHeight; + ++y, p += rowSize, alphaPtr += srcWidth) { + (*src)(srcData, p, alphaPtr); + } + } else { + unscaledAlpha = NULL; + for (y = 0, p = unscaledImage; y < srcHeight; ++y, p += srcWidth * nComps) { + (*src)(srcData, p, NULL); + } + } + + // draw it + pixelBuf = (SplashColorPtr)gmallocn(xMaxI - xMinI, nComps); + pipeInit(&pipe, NULL, + (Guchar)splashRound(state->fillAlpha * 255), + gTrue, gFalse); + for (y = yMinI; y < yMaxI; ++y) { + p = pixelBuf; + for (x = xMinI; x < xMaxI; ++x) { + ix = ((SplashCoord)x + 0.5) * mi0 + ((SplashCoord)y + 0.5) * mi2 + mi4; + iy = ((SplashCoord)x + 0.5) * mi1 + ((SplashCoord)y + 0.5) * mi3 + mi5; + if (interpolate) { + if (ix >= 0 && ix < srcWidth && iy >= 0 && iy < srcHeight) { + x0 = splashFloor(ix - 0.5); + x1 = x0 + 1; + sx = (ix - 0.5) - x0; + y0 = splashFloor(iy - 0.5); + y1 = y0 + 1; + sy = (iy - 0.5) - y0; + if (x0 < 0) { + x0 = 0; + } + if (x1 >= srcWidth) { + x1 = srcWidth - 1; + } + if (y0 < 0) { + y0 = 0; + } + if (y1 >= srcHeight) { + y1 = srcHeight - 1; + } + q00 = &unscaledImage[(y0 * srcWidth + x0) * nComps]; + q01 = &unscaledImage[(y0 * srcWidth + x1) * nComps]; + q10 = &unscaledImage[(y1 * srcWidth + x0) * nComps]; + q11 = &unscaledImage[(y1 * srcWidth + x1) * nComps]; + for (i = 0; i < nComps; ++i) { + pix0 = ((SplashCoord)1 - sx) * *q00++ + sx * *q01++; + pix1 = ((SplashCoord)1 - sx) * *q10++ + sx * *q11++; + *p++ = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0 + + sy * pix1); + } + if (srcAlpha) { + pix0 = ((SplashCoord)1 - sx) * unscaledAlpha[y0 * srcWidth + x0] + + sx * unscaledAlpha[y0 * srcWidth + x1]; + pix1 = ((SplashCoord)1 - sx) * unscaledAlpha[y1 * srcWidth + x0] + + sx * unscaledAlpha[y1 * srcWidth + x1]; + scanBuf[x] = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0 + + sy * pix1); + } else { + scanBuf[x] = 0xff; + } + } else { + for (i = 0; i < nComps; ++i) { + *p++ = 0; + } + scanBuf[x] = 0; + } + } else { + x0 = splashFloor(ix); + y0 = splashFloor(iy); + if (x0 >= 0 && x0 < srcWidth && y0 >= 0 && y0 < srcHeight) { + q = &unscaledImage[(y0 * srcWidth + x0) * nComps]; + for (i = 0; i < nComps; ++i) { + *p++ = *q++; + } + if (srcAlpha) { + scanBuf[x] = unscaledAlpha[y0 * srcWidth + x0]; + } else { + scanBuf[x] = 0xff; + } + } else { + for (i = 0; i < nComps; ++i) { + *p++ = 0; + } + scanBuf[x] = 0; + } + } + } + if (clipRes != splashClipAllInside) { + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, y, xMinI, xMaxI - 1, + state->strokeAdjust); + } else { + state->clip->clipSpanBinary(scanBuf, y, xMinI, xMaxI - 1, + state->strokeAdjust); + } + } + (this->*pipe.run)(&pipe, xMinI, xMaxI - 1, y, scanBuf + xMinI, pixelBuf); + } + + gfree(pixelBuf); + gfree(unscaledImage); + gfree(unscaledAlpha); +} + void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight, - SplashCoord *mat) { + SplashCoord *mat, GBool interpolate) { SplashBitmap *scaledImg; - SplashClipResult clipRes, clipRes2; + SplashClipResult clipRes; SplashPipe pipe; - SplashColor pixel; + SplashColorPtr pixelBuf; int scaledWidth, scaledHeight, t0, t1; SplashCoord r00, r01, r10, r11, det, ir00, ir01, ir10, ir11; SplashCoord vx[4], vy[4]; @@ -3259,29 +4640,26 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, vx[3] = mat[0] + mat[4]; vy[3] = mat[1] + mat[5]; // clipping - xMin = imgCoordMungeLower(vx[0]); - xMax = imgCoordMungeUpper(vx[0]); - yMin = imgCoordMungeLower(vy[0]); - yMax = imgCoordMungeUpper(vy[0]); + xMin = splashRound(vx[0]); + xMax = splashRound(vx[0]); + yMin = splashRound(vy[0]); + yMax = splashRound(vy[0]); for (i = 1; i < 4; ++i) { - t0 = imgCoordMungeLower(vx[i]); + t0 = splashRound(vx[i]); if (t0 < xMin) { xMin = t0; - } - t0 = imgCoordMungeUpper(vx[i]); - if (t0 > xMax) { + } else if (t0 > xMax) { xMax = t0; } - t1 = imgCoordMungeLower(vy[i]); + t1 = splashRound(vy[i]); if (t1 < yMin) { yMin = t1; - } - t1 = imgCoordMungeUpper(vy[i]); - if (t1 > yMax) { + } else if (t1 > yMax) { yMax = t1; } } - clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1); + clipRes = state->clip->testRect(xMin, yMin, xMax - 1, yMax - 1, + state->strokeAdjust); opClipRes = clipRes; if (clipRes == splashClipAllOutside) { return; @@ -3289,25 +4667,25 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, // compute the scale factors if (mat[0] >= 0) { - t0 = imgCoordMungeUpper(mat[0] + mat[4]) - imgCoordMungeLower(mat[4]); + t0 = splashRound(mat[0] + mat[4]) - splashRound(mat[4]); } else { - t0 = imgCoordMungeUpper(mat[4]) - imgCoordMungeLower(mat[0] + mat[4]); + t0 = splashRound(mat[4]) - splashRound(mat[0] + mat[4]); } if (mat[1] >= 0) { - t1 = imgCoordMungeUpper(mat[1] + mat[5]) - imgCoordMungeLower(mat[5]); + t1 = splashRound(mat[1] + mat[5]) - splashRound(mat[5]); } else { - t1 = imgCoordMungeUpper(mat[5]) - imgCoordMungeLower(mat[1] + mat[5]); + t1 = splashRound(mat[5]) - splashRound(mat[1] + mat[5]); } scaledWidth = t0 > t1 ? t0 : t1; if (mat[2] >= 0) { - t0 = imgCoordMungeUpper(mat[2] + mat[4]) - imgCoordMungeLower(mat[4]); + t0 = splashRound(mat[2] + mat[4]) - splashRound(mat[4]); } else { - t0 = imgCoordMungeUpper(mat[4]) - imgCoordMungeLower(mat[2] + mat[4]); + t0 = splashRound(mat[4]) - splashRound(mat[2] + mat[4]); } if (mat[3] >= 0) { - t1 = imgCoordMungeUpper(mat[3] + mat[5]) - imgCoordMungeLower(mat[5]); + t1 = splashRound(mat[3] + mat[5]) - splashRound(mat[5]); } else { - t1 = imgCoordMungeUpper(mat[5]) - imgCoordMungeLower(mat[3] + mat[5]); + t1 = splashRound(mat[5]) - splashRound(mat[3] + mat[5]); } scaledHeight = t0 > t1 ? t0 : t1; if (scaledWidth == 0) { @@ -3334,7 +4712,8 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, // scale the input image scaledImg = scaleImage(src, srcData, srcMode, nComps, srcAlpha, - srcWidth, srcHeight, scaledWidth, scaledHeight); + srcWidth, srcHeight, scaledWidth, scaledHeight, + interpolate); // construct the three sections i = 0; @@ -3354,8 +4733,8 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, i = (i-1) & 3; } if (splashAbs(vy[i] - vy[(i+1) & 3]) <= 0.000001) { - section[0].y0 = imgCoordMungeLower(vy[i]); - section[0].y1 = imgCoordMungeUpper(vy[(i+2) & 3]) - 1; + section[0].y0 = splashRound(vy[i]); + section[0].y1 = splashRound(vy[(i+2) & 3]) - 1; if (vx[i] < vx[(i+1) & 3]) { section[0].ia0 = i; section[0].ia1 = (i+3) & 3; @@ -3369,8 +4748,8 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, } nSections = 1; } else { - section[0].y0 = imgCoordMungeLower(vy[i]); - section[2].y1 = imgCoordMungeUpper(vy[(i+2) & 3]) - 1; + section[0].y0 = splashRound(vy[i]); + section[2].y1 = splashRound(vy[(i+2) & 3]) - 1; section[0].ia0 = section[0].ib0 = i; section[2].ia1 = section[2].ib1 = (i+2) & 3; if (vx[(i+1) & 3] < vx[(i+3) & 3]) { @@ -3381,8 +4760,8 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, section[0].ib1 = section[2].ib0 = (i+1) & 3; } if (vy[(i+1) & 3] < vy[(i+3) & 3]) { - section[1].y0 = imgCoordMungeLower(vy[(i+1) & 3]); - section[2].y0 = imgCoordMungeUpper(vy[(i+3) & 3]); + section[1].y0 = splashRound(vy[(i+1) & 3]); + section[2].y0 = splashRound(vy[(i+3) & 3]); if (vx[(i+1) & 3] < vx[(i+3) & 3]) { section[1].ia0 = (i+1) & 3; section[1].ia1 = (i+2) & 3; @@ -3395,8 +4774,8 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, section[1].ib1 = (i+2) & 3; } } else { - section[1].y0 = imgCoordMungeLower(vy[(i+3) & 3]); - section[2].y0 = imgCoordMungeUpper(vy[(i+1) & 3]); + section[1].y0 = splashRound(vy[(i+3) & 3]); + section[2].y0 = splashRound(vy[(i+1) & 3]); if (vx[(i+1) & 3] < vx[(i+3) & 3]) { section[1].ia0 = i; section[1].ia1 = (i+1) & 3; @@ -3429,13 +4808,9 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, } // initialize the pixel pipe - pipeInit(&pipe, 0, 0, NULL, pixel, + pipeInit(&pipe, NULL, (Guchar)splashRound(state->fillAlpha * 255), - srcAlpha || (vectorAntialias && clipRes != splashClipAllInside), - gFalse); - if (vectorAntialias) { - drawAAPixelInit(); - } + gTrue, gFalse); // make sure narrow images cover at least one pixel if (nSections == 1) { @@ -3450,24 +4825,46 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, } } + pixelBuf = (SplashColorPtr)gmallocn(xMax - xMin + 1, bitmapComps); + // scan all pixels inside the target region for (i = 0; i < nSections; ++i) { for (y = section[i].y0; y <= section[i].y1; ++y) { - xa = imgCoordMungeLower(section[i].xa0 + - ((SplashCoord)y + 0.5 - section[i].ya0) * - section[i].dxdya); - xb = imgCoordMungeUpper(section[i].xb0 + - ((SplashCoord)y + 0.5 - section[i].yb0) * - section[i].dxdyb); + xa = splashRound(section[i].xa0 + + ((SplashCoord)y + 0.5 - section[i].ya0) * + section[i].dxdya); + xb = splashRound(section[i].xb0 + + ((SplashCoord)y + 0.5 - section[i].yb0) * + section[i].dxdyb); + if (xa > xb) { + continue; + } // make sure narrow images cover at least one pixel if (xa == xb) { ++xb; } + // check the scanBuf bounds + if (xa >= bitmap->width || xb < 0) { + continue; + } + if (xa < 0) { + xa = 0; + } + if (xb > bitmap->width) { + xb = bitmap->width; + } + // clip the scan line + memset(scanBuf + xa, 0xff, xb - xa); if (clipRes != splashClipAllInside) { - clipRes2 = state->clip->testSpan(xa, xb - 1, y); - } else { - clipRes2 = clipRes; + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, y, xa, xb - 1, + state->strokeAdjust); + } else { + state->clip->clipSpanBinary(scanBuf, y, xa, xb - 1, + state->strokeAdjust); + } } + // draw the scan line for (x = xa; x < xb; ++x) { // map (x+0.5, y+0.5) back to the scaled image xx = splashFloor(((SplashCoord)x + 0.5 - mat[4]) * ir00 + @@ -3486,21 +4883,19 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, } else if (yy >= scaledHeight) { yy = scaledHeight - 1; } - scaledImg->getPixel(xx, yy, pixel); + // get the color + scaledImg->getPixel(xx, yy, pixelBuf + (x - xa) * bitmapComps); + // apply alpha if (srcAlpha) { - pipe.shape = scaledImg->alpha[yy * scaledWidth + xx]; - } else { - pipe.shape = 255; - } - if (vectorAntialias && clipRes2 != splashClipAllInside) { - drawAAPixel(&pipe, x, y); - } else { - drawPixel(&pipe, x, y, clipRes2 == splashClipAllInside); + scanBuf[x] = div255(scanBuf[x] * + scaledImg->alpha[yy * scaledWidth + xx]); } } + (this->*pipe.run)(&pipe, xa, xb - 1, y, scanBuf + xa, pixelBuf); } } + gfree(pixelBuf); delete scaledImg; } @@ -3508,7 +4903,8 @@ void Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, SplashBitmap *Splash::scaleImage(SplashImageSource src, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight) { + int scaledWidth, int scaledHeight, + GBool interpolate) { SplashBitmap *dest; dest = new SplashBitmap(scaledWidth, scaledHeight, 1, srcMode, srcAlpha); @@ -3525,8 +4921,13 @@ SplashBitmap *Splash::scaleImage(SplashImageSource src, void *srcData, scaleImageYuXd(src, srcData, srcMode, nComps, srcAlpha, srcWidth, srcHeight, scaledWidth, scaledHeight, dest); } else { - scaleImageYuXu(src, srcData, srcMode, nComps, srcAlpha, - srcWidth, srcHeight, scaledWidth, scaledHeight, dest); + if (interpolate) { + scaleImageYuXuI(src, srcData, srcMode, nComps, srcAlpha, + srcWidth, srcHeight, scaledWidth, scaledHeight, dest); + } else { + scaleImageYuXu(src, srcData, srcMode, nComps, srcAlpha, + srcWidth, srcHeight, scaledWidth, scaledHeight, dest); + } } } return dest; @@ -3654,27 +5055,6 @@ void Splash::scaleImageYdXd(SplashImageSource src, void *srcData, *destPtr++ = (Guchar)pix2; break; - case splashModeBGR8: - - // compute the final pixel - pix0 = pix1 = pix2 = 0; - for (i = 0; i < xStep; ++i) { - pix0 += pixBuf[xx]; - pix1 += pixBuf[xx+1]; - pix2 += pixBuf[xx+2]; - xx += 3; - } - // pix / xStep * yStep - pix0 = (pix0 * d) >> 23; - pix1 = (pix1 * d) >> 23; - pix2 = (pix2 * d) >> 23; - - // store the pixel - *destPtr++ = (Guchar)pix2; - *destPtr++ = (Guchar)pix1; - *destPtr++ = (Guchar)pix0; - break; - #if SPLASH_CMYK case splashModeCMYK8: @@ -3703,6 +5083,7 @@ void Splash::scaleImageYdXd(SplashImageSource src, void *srcData, case splashModeMono1: // mono1 is not allowed + case splashModeBGR8: // bgr8 is not allowed default: break; } @@ -3812,8 +5193,6 @@ void Splash::scaleImageYdXu(SplashImageSource src, void *srcData, // store the pixel switch (srcMode) { - case splashModeMono1: // mono1 is not allowed - break; case splashModeMono8: for (i = 0; i < xStep; ++i) { *destPtr++ = (Guchar)pix[0]; @@ -3826,13 +5205,6 @@ void Splash::scaleImageYdXu(SplashImageSource src, void *srcData, *destPtr++ = (Guchar)pix[2]; } break; - case splashModeBGR8: - for (i = 0; i < xStep; ++i) { - *destPtr++ = (Guchar)pix[2]; - *destPtr++ = (Guchar)pix[1]; - *destPtr++ = (Guchar)pix[0]; - } - break; #if SPLASH_CMYK case splashModeCMYK8: for (i = 0; i < xStep; ++i) { @@ -3843,6 +5215,10 @@ void Splash::scaleImageYdXu(SplashImageSource src, void *srcData, } break; #endif + case splashModeMono1: // mono1 is not allowed + case splashModeBGR8: // BGR8 is not allowed + default: + break; } // process alpha @@ -3942,8 +5318,6 @@ void Splash::scaleImageYuXd(SplashImageSource src, void *srcData, // store the pixel switch (srcMode) { - case splashModeMono1: // mono1 is not allowed - break; case splashModeMono8: for (i = 0; i < yStep; ++i) { destPtr = destPtr0 + (i * scaledWidth + x) * nComps; @@ -3958,14 +5332,6 @@ void Splash::scaleImageYuXd(SplashImageSource src, void *srcData, *destPtr++ = (Guchar)pix[2]; } break; - case splashModeBGR8: - for (i = 0; i < yStep; ++i) { - destPtr = destPtr0 + (i * scaledWidth + x) * nComps; - *destPtr++ = (Guchar)pix[2]; - *destPtr++ = (Guchar)pix[1]; - *destPtr++ = (Guchar)pix[0]; - } - break; #if SPLASH_CMYK case splashModeCMYK8: for (i = 0; i < yStep; ++i) { @@ -3977,6 +5343,10 @@ void Splash::scaleImageYuXd(SplashImageSource src, void *srcData, } break; #endif + case splashModeMono1: // mono1 is not allowed + case splashModeBGR8: // BGR8 is not allowed + default: + break; } // process alpha @@ -4071,8 +5441,6 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData, // store the pixel switch (srcMode) { - case splashModeMono1: // mono1 is not allowed - break; case splashModeMono8: for (i = 0; i < yStep; ++i) { for (j = 0; j < xStep; ++j) { @@ -4091,16 +5459,6 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData, } } break; - case splashModeBGR8: - for (i = 0; i < yStep; ++i) { - for (j = 0; j < xStep; ++j) { - destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps; - *destPtr++ = (Guchar)pix[2]; - *destPtr++ = (Guchar)pix[1]; - *destPtr++ = (Guchar)pix[0]; - } - } - break; #if SPLASH_CMYK case splashModeCMYK8: for (i = 0; i < yStep; ++i) { @@ -4114,6 +5472,10 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData, } break; #endif + case splashModeMono1: // mono1 is not allowed + case splashModeBGR8: // BGR8 is not allowed + default: + break; } // process alpha @@ -4140,6 +5502,177 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData, gfree(lineBuf); } +void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest) { + Guchar *lineBuf0, *lineBuf1, *alphaLineBuf0, *alphaLineBuf1, *tBuf; + Guchar pix[splashMaxColorComps]; + SplashCoord yr, xr, ys, xs, ySrc, xSrc; + int ySrc0, ySrc1, yBuf, xSrc0, xSrc1, y, x, i; + Guchar *destPtr, *destAlphaPtr; + + // ratios + yr = (SplashCoord)srcHeight / (SplashCoord)scaledHeight; + xr = (SplashCoord)srcWidth / (SplashCoord)scaledWidth; + + // allocate buffers + lineBuf0 = (Guchar *)gmallocn(scaledWidth, nComps); + lineBuf1 = (Guchar *)gmallocn(scaledWidth, nComps); + if (srcAlpha) { + alphaLineBuf0 = (Guchar *)gmalloc(scaledWidth); + alphaLineBuf1 = (Guchar *)gmalloc(scaledWidth); + } else { + alphaLineBuf0 = NULL; + alphaLineBuf1 = NULL; + } + + // read first two rows + (*src)(srcData, lineBuf0, alphaLineBuf0); + if (srcHeight > 1) { + (*src)(srcData, lineBuf1, alphaLineBuf1); + yBuf = 1; + } else { + memcpy(lineBuf1, lineBuf0, srcWidth * nComps); + if (srcAlpha) { + memcpy(alphaLineBuf1, alphaLineBuf0, srcWidth); + } + yBuf = 0; + } + + // interpolate first two rows + for (x = scaledWidth - 1; x >= 0; --x) { + xSrc = xr * x; + xSrc0 = splashFloor(xSrc + xr * 0.5 - 0.5); + xSrc1 = xSrc0 + 1; + xs = ((SplashCoord)xSrc1 + 0.5) - (xSrc + xr * 0.5); + if (xSrc0 < 0) { + xSrc0 = 0; + } + if (xSrc1 >= srcWidth) { + xSrc1 = srcWidth - 1; + } + for (i = 0; i < nComps; ++i) { + lineBuf0[x*nComps+i] = (Guchar)(int) + (xs * lineBuf0[xSrc0*nComps+i] + + ((SplashCoord)1 - xs) * lineBuf0[xSrc1*nComps+i]); + lineBuf1[x*nComps+i] = (Guchar)(int) + (xs * lineBuf1[xSrc0*nComps+i] + + ((SplashCoord)1 - xs) * lineBuf1[xSrc1*nComps+i]); + } + if (srcAlpha) { + alphaLineBuf0[x] = (Guchar)(int) + (xs * alphaLineBuf0[xSrc0] + + ((SplashCoord)1 - xs) * alphaLineBuf0[xSrc1]); + alphaLineBuf1[x] = (Guchar)(int) + (xs * alphaLineBuf1[xSrc0] + + ((SplashCoord)1 - xs) * alphaLineBuf1[xSrc1]); + } + } + + destPtr = dest->data; + destAlphaPtr = dest->alpha; + for (y = 0; y < scaledHeight; ++y) { + + // compute vertical interpolation parameters + ySrc = yr * y; + ySrc0 = splashFloor(ySrc + yr * 0.5 - 0.5); + ySrc1 = ySrc0 + 1; + ys = ((SplashCoord)ySrc1 + 0.5) - (ySrc + yr * 0.5); + if (ySrc0 < 0) { + ySrc0 = 0; + ys = 1; + } + if (ySrc1 >= srcHeight) { + ySrc1 = srcHeight - 1; + ys = 0; + } + + // read another row (if necessary) + if (ySrc1 > yBuf) { + tBuf = lineBuf0; + lineBuf0 = lineBuf1; + lineBuf1 = tBuf; + tBuf = alphaLineBuf0; + alphaLineBuf0 = alphaLineBuf1; + alphaLineBuf1 = tBuf; + (*src)(srcData, lineBuf1, alphaLineBuf1); + + // interpolate the row + for (x = scaledWidth - 1; x >= 0; --x) { + xSrc = xr * x; + xSrc0 = splashFloor(xSrc + xr * 0.5 - 0.5); + xSrc1 = xSrc0 + 1; + xs = ((SplashCoord)xSrc1 + 0.5) - (xSrc + xr * 0.5); + if (xSrc0 < 0) { + xSrc0 = 0; + } + if (xSrc1 >= srcWidth) { + xSrc1 = srcWidth - 1; + } + for (i = 0; i < nComps; ++i) { + lineBuf1[x*nComps+i] = + (Guchar)(int)(xs * lineBuf1[xSrc0*nComps+i] + + ((SplashCoord)1 - xs) * lineBuf1[xSrc1*nComps+i]); + } + if (srcAlpha) { + alphaLineBuf1[x] = + (Guchar)(int)(xs * alphaLineBuf1[xSrc0] + + ((SplashCoord)1 - xs) * alphaLineBuf1[xSrc1]); + } + } + + ++yBuf; + } + + // do the vertical interpolation + for (x = 0; x < scaledWidth; ++x) { + + for (i = 0; i < nComps; ++i) { + pix[i] = (Guchar)(int)(ys * lineBuf0[x*nComps+i] + + ((SplashCoord)1 - ys) * lineBuf1[x*nComps+i]); + } + + // store the pixel + switch (srcMode) { + case splashModeMono8: + *destPtr++ = pix[0]; + break; + case splashModeRGB8: + *destPtr++ = pix[0]; + *destPtr++ = pix[1]; + *destPtr++ = pix[2]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + *destPtr++ = pix[0]; + *destPtr++ = pix[1]; + *destPtr++ = pix[2]; + *destPtr++ = pix[3]; + break; +#endif + case splashModeMono1: // mono1 is not allowed + case splashModeBGR8: // BGR8 is not allowed + default: + break; + } + + // process alpha + if (srcAlpha) { + *destAlphaPtr++ = (Guchar)(int) + (ys * alphaLineBuf0[x] + + ((SplashCoord)1 - ys) * alphaLineBuf1[x]); + } + } + } + + gfree(alphaLineBuf1); + gfree(alphaLineBuf0); + gfree(lineBuf1); + gfree(lineBuf0); +} + void Splash::vertFlipImage(SplashBitmap *img, int width, int height, int nComps) { Guchar *lineBuf; @@ -4167,12 +5700,43 @@ void Splash::vertFlipImage(SplashBitmap *img, int width, int height, gfree(lineBuf); } +void Splash::horizFlipImage(SplashBitmap *img, int width, int height, + int nComps) { + Guchar *lineBuf; + SplashColorPtr p0, p1, p2; + int w, x, y, i; + + w = width * nComps; + lineBuf = (Guchar *)gmalloc(w); + for (y = 0, p0 = img->data; y < height; ++y, p0 += img->rowSize) { + memcpy(lineBuf, p0, w); + p1 = p0; + p2 = lineBuf + (w - nComps); + for (x = 0; x < width; ++x) { + for (i = 0; i < nComps; ++i) { + p1[i] = p2[i]; + } + p1 += nComps; + p2 -= nComps; + } + } + if (img->alpha) { + for (y = 0, p0 = img->alpha; y < height; ++y, p0 += width) { + memcpy(lineBuf, p0, width); + p1 = p0; + p2 = lineBuf + (width - 1); + for (x = 0; x < width; ++x) { + *p1++ = *p2--; + } + } + } + gfree(lineBuf); +} + void Splash::blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, SplashClipResult clipRes) { SplashPipe pipe; - SplashColor pixel; - Guchar *ap; - int w, h, x0, y0, x1, y1, x, y; + int w, h, x0, y0, x1, y1, y; // split the image into clipped and unclipped regions w = src->getWidth(); @@ -4200,8 +5764,8 @@ void Splash::blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, x1 = x0; } if ((y1 = splashFloor(state->clip->getYMax()) - yDest) > h) { - y1 = h; - } + y1 = h; + } if (y1 < y0) { y1 = y0; } @@ -4210,31 +5774,24 @@ void Splash::blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, // draw the unclipped region if (x0 < w && y0 < h && x0 < x1 && y0 < y1) { - pipeInit(&pipe, xDest + x0, yDest + y0, NULL, pixel, - (Guchar)splashRound(state->fillAlpha * 255), srcAlpha, gFalse); + pipeInit(&pipe, NULL, + (Guchar)splashRound(state->fillAlpha * 255), + srcAlpha, gFalse); if (srcAlpha) { for (y = y0; y < y1; ++y) { - pipeSetXY(&pipe, xDest + x0, yDest + y); - ap = src->getAlphaPtr() + y * w + x0; - for (x = x0; x < x1; ++x) { - src->getPixel(x, y, pixel); - pipe.shape = *ap++; - (this->*pipe.run)(&pipe); - } + (this->*pipe.run)(&pipe, xDest + x0, xDest + x1 - 1, yDest + y, + src->getAlphaPtr() + y * w + x0, + src->getDataPtr() + y * src->getRowSize() + + x0 * bitmapComps); } } else { for (y = y0; y < y1; ++y) { - pipeSetXY(&pipe, xDest + x0, yDest + y); - for (x = x0; x < x1; ++x) { - src->getPixel(x, y, pixel); - (this->*pipe.run)(&pipe); - } + (this->*pipe.run)(&pipe, xDest + x0, xDest + x1 - 1, yDest + y, + NULL, + src->getDataPtr() + y * src->getRowSize() + + x0 * bitmapComps); } } - updateModX(xDest + x0); - updateModX(xDest + x1 - 1); - updateModY(yDest + y0); - updateModY(yDest + y1 - 1); } // draw the clipped regions @@ -4257,66 +5814,62 @@ void Splash::blitImageClipped(SplashBitmap *src, GBool srcAlpha, int xSrc, int ySrc, int xDest, int yDest, int w, int h) { SplashPipe pipe; - SplashColor pixel; - Guchar *ap; - int x, y; + int y; - if (vectorAntialias) { - pipeInit(&pipe, xDest, yDest, NULL, pixel, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse); - drawAAPixelInit(); - if (srcAlpha) { - for (y = 0; y < h; ++y) { - ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - pipe.shape = *ap++; - drawAAPixel(&pipe, xDest + x, yDest + y); - } - } - } else { - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - pipe.shape = 255; - drawAAPixel(&pipe, xDest + x, yDest + y); - } + if (xDest < 0) { + xSrc -= xDest; + w += xDest; + xDest = 0; + } + if (xDest + w > bitmap->width) { + w = bitmap->width - xDest; + } + if (yDest < 0) { + ySrc -= yDest; + h += yDest; + yDest = 0; + } + if (yDest + h > bitmap->height) { + h = bitmap->height - yDest; + } + if (w <= 0 || h <= 0) { + return; + } + + pipeInit(&pipe, NULL, + (Guchar)splashRound(state->fillAlpha * 255), + gTrue, gFalse); + if (srcAlpha) { + for (y = 0; y < h; ++y) { + memcpy(scanBuf + xDest, + src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc, + w); + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, yDest + y, xDest, xDest + w - 1, + state->strokeAdjust); + } else { + state->clip->clipSpanBinary(scanBuf, yDest + y, xDest, xDest + w - 1, + state->strokeAdjust); } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + scanBuf + xDest, + src->getDataPtr() + (ySrc + y) * src->getRowSize() + + xSrc * bitmapComps); } } else { - pipeInit(&pipe, xDest, yDest, NULL, pixel, - (Guchar)splashRound(state->fillAlpha * 255), srcAlpha, gFalse); - if (srcAlpha) { - for (y = 0; y < h; ++y) { - ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc; - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - if (state->clip->test(xDest + x, yDest + y)) { - src->getPixel(xSrc + x, ySrc + y, pixel); - pipe.shape = *ap++; - (this->*pipe.run)(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); - ++ap; - } - } - } - } else { - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - if (state->clip->test(xDest + x, yDest + y)) { - src->getPixel(xSrc + x, ySrc + y, pixel); - (this->*pipe.run)(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); - } - } + for (y = 0; y < h; ++y) { + memset(scanBuf + xDest, 0xff, w); + if (vectorAntialias) { + state->clip->clipSpan(scanBuf, yDest + y, xDest, xDest + w - 1, + state->strokeAdjust); + } else { + state->clip->clipSpanBinary(scanBuf, yDest + y, xDest, xDest + w - 1, + state->strokeAdjust); } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + scanBuf + xDest, + src->getDataPtr() + (ySrc + y) * src->getRowSize() + + xSrc * bitmapComps); } } } @@ -4325,82 +5878,82 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, int xDest, int yDest, int w, int h, GBool noClip, GBool nonIsolated) { SplashPipe pipe; - SplashColor pixel; - Guchar alpha; - Guchar *ap; - int x, y; + int x0, x1, y0, y1, y, t; if (src->mode != bitmap->mode) { return splashErrModeMismatch; } - if (src->alpha) { - pipeInit(&pipe, xDest, yDest, NULL, pixel, - (Guchar)splashRound(state->fillAlpha * 255), gTrue, nonIsolated); - if (noClip) { + pipeInit(&pipe, NULL, + (Guchar)splashRound(state->fillAlpha * 255), + !noClip || src->alpha != NULL, nonIsolated); + if (noClip) { + if (src->alpha) { for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - alpha = *ap++; - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same - pipe.shape = alpha; - (this->*pipe.run)(&pipe); - } + // this uses shape instead of alpha, which isn't technically + // correct, but works out the same + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + src->getAlphaPtr() + + (ySrc + y) * src->getWidth() + xSrc, + src->getDataPtr() + (ySrc + y) * src->getRowSize() + + xSrc * bitmapComps); } - updateModX(xDest); - updateModX(xDest + w - 1); - updateModY(yDest); - updateModY(yDest + h - 1); } else { for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc; - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - alpha = *ap++; - if (state->clip->test(xDest + x, yDest + y)) { - // this uses shape instead of alpha, which isn't technically - // correct, but works out the same - pipe.shape = alpha; - (this->*pipe.run)(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); - } - } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + NULL, + src->getDataPtr() + (ySrc + y) * src->getRowSize() + + xSrc * bitmapComps); } } } else { - pipeInit(&pipe, xDest, yDest, NULL, pixel, - (Guchar)splashRound(state->fillAlpha * 255), gFalse, nonIsolated); - if (noClip) { - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - (this->*pipe.run)(&pipe); + x0 = xDest; + if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) { + x0 = t; + } + x1 = xDest + w; + if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) { + x1 = t; + } + y0 = yDest; + if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) { + y0 = t; + } + y1 = yDest + h; + if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) { + y1 = t; + } + if (x0 < x1 && y0 < y1) { + if (src->alpha) { + for (y = y0; y < y1; ++y) { + memcpy(scanBuf + x0, + src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() + + (xSrc + x0 - xDest), + x1 - x0); + if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1, + state->strokeAdjust)) { + continue; + } + // this uses shape instead of alpha, which isn't technically + // correct, but works out the same + (this->*pipe.run)(&pipe, x0, x1 - 1, y, + scanBuf + x0, + src->getDataPtr() + + (ySrc + y - yDest) * src->getRowSize() + + (xSrc + x0 - xDest) * bitmapComps); } - } - updateModX(xDest); - updateModX(xDest + w - 1); - updateModY(yDest); - updateModY(yDest + h - 1); - } else { - for (y = 0; y < h; ++y) { - pipeSetXY(&pipe, xDest, yDest + y); - for (x = 0; x < w; ++x) { - src->getPixel(xSrc + x, ySrc + y, pixel); - if (state->clip->test(xDest + x, yDest + y)) { - (this->*pipe.run)(&pipe); - updateModX(xDest + x); - updateModY(yDest + y); - } else { - pipeIncX(&pipe); + } else { + for (y = y0; y < y1; ++y) { + memset(scanBuf + x0, 0xff, x1 - x0); + if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1, + state->strokeAdjust)) { + continue; } + (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y, + scanBuf + x0, + src->getDataPtr() + + (ySrc + y - yDest) * src->getRowSize() + + (xSrc - xDest) * bitmapComps); } } } @@ -4535,9 +6088,7 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, for (y = 0; y < h; ++y) { p = &bitmap->data[(yDest + y) * bitmap->rowSize + xDest]; q = &src->data[(ySrc + y) * src->rowSize + xSrc]; - for (x = 0; x < w; ++x) { - *p++ = *q++; - } + memcpy(p, q, w); } break; case splashModeRGB8: @@ -4545,11 +6096,7 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, for (y = 0; y < h; ++y) { p = &bitmap->data[(yDest + y) * bitmap->rowSize + 3 * xDest]; q = &src->data[(ySrc + y) * src->rowSize + 3 * xSrc]; - for (x = 0; x < w; ++x) { - *p++ = *q++; - *p++ = *q++; - *p++ = *q++; - } + memcpy(p, q, 3 * w); } break; #if SPLASH_CMYK @@ -4557,12 +6104,7 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, for (y = 0; y < h; ++y) { p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest]; q = &src->data[(ySrc + y) * src->rowSize + 4 * xSrc]; - for (x = 0; x < w; ++x) { - *p++ = *q++; - *p++ = *q++; - *p++ = *q++; - *p++ = *q++; - } + memcpy(p, q, 4 * w); } break; #endif @@ -4571,9 +6113,7 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, if (bitmap->alpha) { for (y = 0; y < h; ++y) { q = &bitmap->alpha[(yDest + y) * bitmap->width + xDest]; - for (x = 0; x < w; ++x) { - *q++ = 0x00; - } + memset(q, 0, w); } } @@ -5002,11 +6542,9 @@ void Splash::dumpXPath(SplashXPath *path) { int i; for (i = 0; i < path->length; ++i) { - printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f %s%s%s\n", + printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f count=%d\n", i, (double)path->segs[i].x0, (double)path->segs[i].y0, (double)path->segs[i].x1, (double)path->segs[i].y1, - (path->segs[i].flags & splashXPathHoriz) ? "H" : " ", - (path->segs[i].flags & splashXPathVert) ? "V" : " ", - (path->segs[i].flags & splashXPathFlip) ? "P" : " "); + path->segs[i].count); } } diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/Splash.h b/Build/source/libs/xpdf/xpdf-3.04/splash/Splash.h index 30761fb02a8..7409e0cd6b4 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/Splash.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/Splash.h @@ -2,6 +2,8 @@ // // Splash.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASH_H @@ -97,6 +99,7 @@ public: SplashClip *getClip(); SplashBitmap *getSoftMask(); GBool getInNonIsolatedGroup(); + GBool getInKnockoutGroup(); //----- state write @@ -125,8 +128,9 @@ public: // NB: uses untransformed coordinates. SplashError clipToPath(SplashPath *path, GBool eo); void setSoftMask(SplashBitmap *softMask); - void setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA, - int alpha0XA, int alpha0YA); + void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, + int groupBackXA, int groupBackYA, + GBool nonIsolated, GBool knockout); void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); void setOverprintMask(Guint overprintMask); @@ -172,7 +176,7 @@ public: // top line. SplashError fillImageMask(SplashImageMaskSource src, void *srcData, int w, int h, SplashCoord *mat, - GBool glyphMode); + GBool glyphMode, GBool interpolate); // Draw an image. This will read <h> lines of <w> pixels from // <src>, starting with the top line. These pixels are assumed to @@ -182,16 +186,16 @@ public: // are supported: // source target // ------ ------ - // Mono1 Mono1 // Mono8 Mono1 -- with dithering // Mono8 Mono8 // RGB8 RGB8 - // BGR8 BGR8 + // BGR8 RGB8 // CMYK8 CMYK8 // The matrix behaves as for fillImageMask. SplashError drawImage(SplashImageSource src, void *srcData, SplashColorMode srcMode, GBool srcAlpha, - int w, int h, SplashCoord *mat); + int w, int h, SplashCoord *mat, + GBool interpolate); // Composite a rectangular region from <src> onto this Splash // object. @@ -245,37 +249,53 @@ public: private: - void pipeInit(SplashPipe *pipe, int x, int y, - SplashPattern *pattern, SplashColorPtr cSrc, + void pipeInit(SplashPipe *pipe, SplashPattern *pattern, Guchar aInput, GBool usesShape, GBool nonIsolatedGroup); - void pipeRun(SplashPipe *pipe); - void pipeRunSimpleMono1(SplashPipe *pipe); - void pipeRunSimpleMono8(SplashPipe *pipe); - void pipeRunSimpleRGB8(SplashPipe *pipe); - void pipeRunSimpleBGR8(SplashPipe *pipe); + void pipeRun(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); +#if SPLASH_CMYK + void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); +#endif + void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunSimpleCMYK8(SplashPipe *pipe); + void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void pipeRunAAMono1(SplashPipe *pipe); - void pipeRunAAMono8(SplashPipe *pipe); - void pipeRunAARGB8(SplashPipe *pipe); - void pipeRunAABGR8(SplashPipe *pipe); + void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunAACMYK8(SplashPipe *pipe); + void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void pipeSetXY(SplashPipe *pipe, int x, int y); - void pipeIncX(SplashPipe *pipe); - void drawPixel(SplashPipe *pipe, int x, int y, GBool noClip); - void drawAAPixelInit(); - void drawAAPixel(SplashPipe *pipe, int x, int y); - void drawSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); - void drawAALine(SplashPipe *pipe, int x0, int x1, int y); void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, SplashCoord *xo, SplashCoord *yo); void updateModX(int x); void updateModY(int y); void strokeNarrow(SplashPath *path); + void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); void strokeWide(SplashPath *path, SplashCoord w); SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix, SplashCoord flatness); @@ -288,14 +308,23 @@ private: SplashPath *makeDashedPath(SplashPath *xPath); SplashError fillWithPattern(SplashPath *path, GBool eo, SplashPattern *pattern, SplashCoord alpha); + SplashPath *tweakFillPath(SplashPath *path); GBool pathAllOutside(SplashPath *path); SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); + void getImageBounds(SplashCoord xyMin, SplashCoord xyMax, + int *xyMinI, int *xyMaxI); + void upscaleMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool glyphMode, + GBool interpolate); void arbitraryTransformMask(SplashImageMaskSource src, void *srcData, int srcWidth, int srcHeight, - SplashCoord *mat, GBool glyphMode); + SplashCoord *mat, GBool glyphMode, + GBool interpolate); SplashBitmap *scaleMask(SplashImageMaskSource src, void *srcData, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight); + int scaledWidth, int scaledHeight, + GBool interpolate); void scaleMaskYdXd(SplashImageMaskSource src, void *srcData, int srcWidth, int srcHeight, int scaledWidth, int scaledHeight, @@ -312,17 +341,26 @@ private: int srcWidth, int srcHeight, int scaledWidth, int scaledHeight, SplashBitmap *dest); + void scaleMaskYuXuI(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); void blitMask(SplashBitmap *src, int xDest, int yDest, SplashClipResult clipRes); + void upscaleImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + SplashCoord *mat, GBool interpolate); void arbitraryTransformImage(SplashImageSource src, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight, - SplashCoord *mat); + SplashCoord *mat, GBool interpolate); SplashBitmap *scaleImage(SplashImageSource src, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight); + int scaledWidth, int scaledHeight, + GBool interpolate); void scaleImageYdXd(SplashImageSource src, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight, @@ -343,8 +381,15 @@ private: GBool srcAlpha, int srcWidth, int srcHeight, int scaledWidth, int scaledHeight, SplashBitmap *dest); + void scaleImageYuXuI(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); void vertFlipImage(SplashBitmap *img, int width, int height, int nComps); + void horizFlipImage(SplashBitmap *img, int width, int height, + int nComps); void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, SplashClipResult clipRes); void blitImageClipped(SplashBitmap *src, GBool srcAlpha, @@ -359,13 +404,13 @@ private: static int pipeNonIsoGroupCorrection[]; SplashBitmap *bitmap; + int bitmapComps; SplashState *state; - SplashBitmap *aaBuf; - int aaBufY; - SplashBitmap *alpha0Bitmap; // for non-isolated groups, this is the - // bitmap containing the alpha0 values - int alpha0X, alpha0Y; // offset within alpha0Bitmap - Guchar aaGamma[splashAASize * splashAASize + 1]; + Guchar *scanBuf; + SplashBitmap // for transparency groups, this is the bitmap + *groupBackBitmap; // containing the alpha0/color0 values + int groupBackX, groupBackY; // offset within groupBackBitmap + Guchar aaGamma[256]; SplashCoord minLineWidth; int modXMin, modYMin, modXMax, modYMax; SplashClipResult opClipRes; diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashBitmap.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashBitmap.cc index 9fc7b04df18..3606a917beb 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashBitmap.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashBitmap.cc @@ -2,6 +2,8 @@ // // SplashBitmap.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashBitmap.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashBitmap.h index 78f37d6e62b..3dfc939ccc5 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashBitmap.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashBitmap.h @@ -2,6 +2,8 @@ // // SplashBitmap.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHBITMAP_H diff --git a/Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.cc new file mode 100644 index 00000000000..6865c574f4e --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.cc @@ -0,0 +1,520 @@ +//======================================================================== +// +// SplashClip.cc +// +// Copyright 2003-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <string.h> +#include "gmem.h" +#include "SplashErrorCodes.h" +#include "SplashPath.h" +#include "SplashXPath.h" +#include "SplashXPathScanner.h" +#include "SplashClip.h" + +//------------------------------------------------------------------------ + +// Compute x * y / 255, where x and y are in [0, 255]. +static inline Guchar mul255(Guchar x, Guchar y) { + int z; + + z = (int)x * (int)y; + return (Guchar)((z + (z >> 8) + 0x80) >> 8); +} + +//------------------------------------------------------------------------ +// SplashClip +//------------------------------------------------------------------------ + +SplashClip::SplashClip(int hardXMinA, int hardYMinA, + int hardXMaxA, int hardYMaxA) { + int w; + + hardXMin = hardXMinA; + hardYMin = hardYMinA; + hardXMax = hardXMaxA; + hardYMax = hardYMaxA; + xMin = hardXMin; + yMin = hardYMin; + xMax = hardXMax; + yMax = hardYMax; + intBoundsValid = gFalse; + paths = NULL; + eo = NULL; + scanners = NULL; + length = size = 0; + if ((w = hardXMax + 1) <= 0) { + w = 1; + } + buf = (Guchar *)gmalloc(w); +} + +SplashClip::SplashClip(SplashClip *clip) { + int w, i; + + hardXMin = clip->hardXMin; + hardYMin = clip->hardYMin; + hardXMax = clip->hardXMax; + hardYMax = clip->hardYMax; + xMin = clip->xMin; + yMin = clip->yMin; + xMax = clip->xMax; + yMax = clip->yMax; + xMinI = clip->xMinI; + yMinI = clip->yMinI; + xMaxI = clip->xMaxI; + yMaxI = clip->yMaxI; + intBoundsValid = clip->intBoundsValid; + intBoundsStrokeAdjust = clip->intBoundsStrokeAdjust; + length = clip->length; + size = clip->size; + paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *)); + eo = (Guchar *)gmallocn(size, sizeof(Guchar)); + scanners = (SplashXPathScanner **) + gmallocn(size, sizeof(SplashXPathScanner *)); + for (i = 0; i < length; ++i) { + paths[i] = clip->paths[i]->copy(); + eo[i] = clip->eo[i]; + scanners[i] = new SplashXPathScanner(paths[i], eo[i], yMinI, yMaxI); + } + if ((w = splashCeil(xMax)) <= 0) { + w = 1; + } + buf = (Guchar *)gmalloc(w); +} + +SplashClip::~SplashClip() { + int i; + + for (i = 0; i < length; ++i) { + delete paths[i]; + delete scanners[i]; + } + gfree(paths); + gfree(eo); + gfree(scanners); + gfree(buf); +} + +void SplashClip::grow(int nPaths) { + if (length + nPaths > size) { + if (size == 0) { + size = 32; + } + while (size < length + nPaths) { + size *= 2; + } + paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *)); + eo = (Guchar *)greallocn(eo, size, sizeof(Guchar)); + scanners = (SplashXPathScanner **) + greallocn(scanners, size, sizeof(SplashXPathScanner *)); + } +} + +void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + int w, i; + + for (i = 0; i < length; ++i) { + delete paths[i]; + delete scanners[i]; + } + gfree(paths); + gfree(eo); + gfree(scanners); + gfree(buf); + paths = NULL; + eo = NULL; + scanners = NULL; + length = size = 0; + + if (x0 < x1) { + xMin = x0; + xMax = x1; + } else { + xMin = x1; + xMax = x0; + } + if (y0 < y1) { + yMin = y0; + yMax = y1; + } else { + yMin = y1; + yMax = y0; + } + intBoundsValid = gFalse; + if ((w = splashCeil(xMax)) <= 0) { + w = 1; + } + buf = (Guchar *)gmalloc(w); +} + +SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + if (x0 < x1) { + if (x0 > xMin) { + xMin = x0; + intBoundsValid = gFalse; + } + if (x1 < xMax) { + xMax = x1; + intBoundsValid = gFalse; + } + } else { + if (x1 > xMin) { + xMin = x1; + intBoundsValid = gFalse; + } + if (x0 < xMax) { + xMax = x0; + intBoundsValid = gFalse; + } + } + if (y0 < y1) { + if (y0 > yMin) { + yMin = y0; + intBoundsValid = gFalse; + } + if (y1 < yMax) { + yMax = y1; + intBoundsValid = gFalse; + } + } else { + if (y1 > yMin) { + yMin = y1; + intBoundsValid = gFalse; + } + if (y0 < yMax) { + yMax = y0; + intBoundsValid = gFalse; + } + } + return splashOk; +} + +SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness, GBool eoA) { + SplashXPath *xPath; + SplashCoord t; + + xPath = new SplashXPath(path, matrix, flatness, gTrue); + + // check for an empty path + if (xPath->length == 0) { + xMin = yMin = 1; + xMax = yMax = 0; + intBoundsValid = gFalse; + delete xPath; + return splashOk; + } + + // check for a rectangle + if (xPath->length == 4 && + xPath->segs[0].y0 == xPath->segs[0].y1 && + xPath->segs[1].x0 == xPath->segs[1].x1 && + xPath->segs[2].x0 == xPath->segs[2].x1 && + xPath->segs[3].y0 == xPath->segs[3].y1) { + clipToRect(xPath->segs[1].x0, xPath->segs[0].y0, + xPath->segs[2].x0, xPath->segs[3].y0); + delete xPath; + return splashOk; + } + if (xPath->length == 4 && + xPath->segs[0].x0 == xPath->segs[0].x1 && + xPath->segs[1].y0 == xPath->segs[1].y1 && + xPath->segs[2].x0 == xPath->segs[2].x1 && + xPath->segs[3].y0 == xPath->segs[3].y1) { + clipToRect(xPath->segs[0].x0, xPath->segs[1].y0, + xPath->segs[2].x0, xPath->segs[3].y0); + delete xPath; + return splashOk; + } + if (xPath->length == 4 && + xPath->segs[0].x0 == xPath->segs[0].x1 && + xPath->segs[1].x0 == xPath->segs[1].x1 && + xPath->segs[2].y0 == xPath->segs[2].y1 && + xPath->segs[3].y0 == xPath->segs[3].y1) { + clipToRect(xPath->segs[0].x0, xPath->segs[2].y0, + xPath->segs[1].x0, xPath->segs[3].y0); + delete xPath; + return splashOk; + } + + grow(1); + paths[length] = xPath; + eo[length] = (Guchar)eoA; + if ((t = xPath->getXMin()) > xMin) { + xMin = t; + } + if ((t = xPath->getYMin()) > yMin) { + yMin = t; + } + if ((t = xPath->getXMax() + 1) < xMax) { + xMax = t; + } + if ((t = xPath->getYMax() + 1) < yMax) { + yMax = t; + } + intBoundsValid = gFalse; + scanners[length] = new SplashXPathScanner(xPath, eoA, splashFloor(yMin), + splashCeil(yMax) - 1); + ++length; + + return splashOk; +} + +SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin, + int rectXMax, int rectYMax, + GBool strokeAdjust) { + // In general, this function tests the rectangle: + // x = [rectXMin, rectXMax + 1) (note: coords are ints) + // y = [rectYMin, rectYMax + 1) + // against the clipping region: + // x = [xMin, xMax) (note: coords are fp) + // y = [yMin, yMax) + + if (strokeAdjust && length == 0) { + // special case for stroke adjustment with a simple clipping + // rectangle -- the clipping region is: + // x = [xMinI, xMaxI + 1) + // y = [yMinI, yMaxI + 1) + updateIntBounds(strokeAdjust); + if (xMinI > xMaxI || yMinI > yMaxI) { + return splashClipAllOutside; + } + if (rectXMax + 1 <= xMinI || + rectXMin >= xMaxI + 1 || + rectYMax + 1 <= yMinI || + rectYMin >= yMaxI + 1) { + return splashClipAllOutside; + } + if (rectXMin >= xMinI && + rectXMax <= xMaxI && + rectYMin >= yMinI && + rectYMax <= yMaxI) { + return splashClipAllInside; + } + } else { + if (xMin >= xMax || yMin >= yMax) { + return splashClipAllOutside; + } + if ((SplashCoord)(rectXMax + 1) <= xMin || + (SplashCoord)rectXMin >= xMax || + (SplashCoord)(rectYMax + 1) <= yMin || + (SplashCoord)rectYMin >= yMax) { + return splashClipAllOutside; + } + if (length == 0 && + (SplashCoord)rectXMin >= xMin && + (SplashCoord)(rectXMax + 1) <= xMax && + (SplashCoord)rectYMin >= yMin && + (SplashCoord)(rectYMax + 1) <= yMax) { + return splashClipAllInside; + } + } + return splashClipPartial; +} + +void SplashClip::clipSpan(Guchar *line, int y, int x0, int x1, + GBool strokeAdjust) { + SplashCoord d; + int x0a, x1a, x, i; + + updateIntBounds(strokeAdjust); + + //--- clip to the integer rectangle + + if (y < yMinI || y > yMaxI || + x1 < xMinI || x0 > xMaxI) { + memset(line + x0, 0, x1 - x0 + 1); + return; + } + + if (x0 > xMinI) { + x0a = x0; + } else { + x0a = xMinI; + memset(line + x0, 0, x0a - x0); + } + + if (x1 < xMaxI) { + x1a = x1; + } else { + x1a = xMaxI; + memset(line + x1a + 1, 0, x1 - x1a); + } + + if (x0a > x1a) { + return; + } + + //--- clip to the floating point rectangle + // (if stroke adjustment is disabled) + + if (!strokeAdjust) { + + // clip left edge (xMin) + if (x0a == xMinI) { + d = (SplashCoord)(xMinI + 1) - xMin; + line[x0a] = (Guchar)(int)((SplashCoord)line[x0a] * d); + } + + // clip right edge (xMax) + if (x1a == xMaxI) { + d = xMax - (SplashCoord)xMaxI; + line[x1a] = (Guchar)(int)((SplashCoord)line[x1a] * d); + } + + // clip top edge (yMin) + if (y == yMinI) { + d = (SplashCoord)(yMinI + 1) - yMin; + for (x = x0a; x <= x1a; ++x) { + line[x] = (Guchar)(int)((SplashCoord)line[x] * d); + } + } + + // clip bottom edge (yMax) + if (y == yMaxI) { + d = yMax - (SplashCoord)yMaxI; + for (x = x0a; x <= x1a; ++x) { + line[x] = (Guchar)(int)((SplashCoord)line[x] * d); + } + } + } + + if (length == 0) { + return; + } + + //--- clip to the paths + + for (i = 0; i < length; ++i) { + scanners[i]->getSpan(buf, y, x0a, x1a); + for (x = x0a; x <= x1a; ++x) { + line[x] = mul255(line[x], buf[x]); + } + } +} + +GBool SplashClip::clipSpanBinary(Guchar *line, int y, int x0, int x1, + GBool strokeAdjust) { + int x0a, x1a, x0b, x1b, x, i; + Guchar any; + + updateIntBounds(strokeAdjust); + + if (y < yMinI || y > yMaxI || + x1 < xMinI || x0 > xMaxI) { + if (x0 <= x1) { + memset(line + x0, 0, x1 - x0 + 1); + } + return gFalse; + } + + if (x0 > xMinI) { + x0a = x0; + } else { + x0a = xMinI; + memset(line + x0, 0, x0a - x0); + } + + if (x1 < xMaxI) { + x1a = x1; + } else { + x1a = xMaxI; + memset(line + x1a + 1, 0, x1 - x1a); + } + + if (x0a > x1a) { + return gFalse; + } + + if (length == 0) { + for (x = x0a; x <= x1a; ++x) { + if (line[x]) { + return gTrue; + } + } + return gFalse; + } + + any = 0; + for (i = 0; i < length; ++i) { + scanners[i]->getSpanBinary(buf, y, x0a, x1a); + for (x0b = x0a; x0b <= x1a && !buf[x0b]; ++x0b) ; + if (x0a < x0b) { + memset(line + x0a, 0, x0b - x0a); + } + for (x1b = x1a; x1b >= x0b && !buf[x1b]; --x1b) ; + if (x1b < x1a) { + memset(line + x1b + 1, 0, x1a - x1b); + } + for (x = x0b; x <= x1b; ++x) { + line[x] &= buf[x]; + any |= line[x]; + } + } + + return any != 0; +} + +int SplashClip::getXMinI(GBool strokeAdjust) { + updateIntBounds(strokeAdjust); + return xMinI; +} + +int SplashClip::getXMaxI(GBool strokeAdjust) { + updateIntBounds(strokeAdjust); + return xMaxI; +} + +int SplashClip::getYMinI(GBool strokeAdjust) { + updateIntBounds(strokeAdjust); + return yMinI; +} + +int SplashClip::getYMaxI(GBool strokeAdjust) { + updateIntBounds(strokeAdjust); + return yMaxI; +} + +void SplashClip::updateIntBounds(GBool strokeAdjust) { + if (intBoundsValid && strokeAdjust == intBoundsStrokeAdjust) { + return; + } + if (strokeAdjust && length == 0) { + splashStrokeAdjust(xMin, xMax, &xMinI, &xMaxI); + splashStrokeAdjust(yMin, yMax, &yMinI, &yMaxI); + } else { + xMinI = splashFloor(xMin); + yMinI = splashFloor(yMin); + xMaxI = splashCeil(xMax); + yMaxI = splashCeil(yMax); + } + if (xMinI < hardXMin) { + xMinI = hardXMin; + } + if (yMinI < hardYMin) { + yMinI = hardYMin; + } + if (xMaxI > hardXMax) { + xMaxI = hardXMax; + } + if (yMaxI > hardYMax) { + yMaxI = hardYMax; + } + // the clipping code uses [xMinI, xMaxI] instead of [xMinI, xMaxI) + --xMaxI; + --yMaxI; + intBoundsValid = gTrue; + intBoundsStrokeAdjust = strokeAdjust; +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.h index 6f580f8e546..42986222976 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashClip.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashClip.h @@ -2,6 +2,8 @@ // // SplashClip.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHCLIP_H @@ -37,9 +39,8 @@ class SplashClip { public: // Create a clip, for the given rectangle. - SplashClip(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - GBool antialiasA); + SplashClip(int hardXMinA, int hardYMinA, + int hardXMaxA, int hardYMaxA); // Copy a clip. SplashClip *copy() { return new SplashClip(this); } @@ -56,10 +57,7 @@ public: // Interesect the clip with <path>. SplashError clipToPath(SplashPath *path, SplashCoord *matrix, - SplashCoord flatness, GBool eo); - - // Returns true if (<x>,<y>) is inside the clip. - GBool test(int x, int y); + SplashCoord flatness, GBool eoA); // Tests a rectangle against the clipping region. Returns one of: // - splashClipAllInside if the entire rectangle is inside the @@ -71,15 +69,19 @@ public: // - splashClipPartial if the rectangle is part inside and part // outside the clipping region SplashClipResult testRect(int rectXMin, int rectYMin, - int rectXMax, int rectYMax); + int rectXMax, int rectYMax, + GBool strokeAdjust); - // Similar to testRect, but tests a horizontal span. - SplashClipResult testSpan(int spanXMin, int spanXMax, int spanY); + // Clip a scan line. Modifies line[] by multiplying with clipping + // shape values for one scan line: ([x0, x1], y). + void clipSpan(Guchar *line, int y, int x0, int x1, + GBool strokeAdjust); - // Clips an anti-aliased line by setting pixels to zero. On entry, - // all non-zero pixels are between <x0> and <x1>. This function - // will update <x0> and <x1>. - void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y); + // Like clipSpan(), but uses the values 0 and 255 only. + // Returns true if there are any non-zero values in the result + // (i.e., returns false if the entire line is clipped out). + GBool clipSpanBinary(Guchar *line, int y, int x0, int x1, + GBool strokeAdjust); // Get the rectangle part of the clip region. SplashCoord getXMin() { return xMin; } @@ -88,10 +90,10 @@ public: SplashCoord getYMax() { return yMax; } // Get the rectangle part of the clip region, in integer coordinates. - int getXMinI() { return xMinI; } - int getXMaxI() { return xMaxI; } - int getYMinI() { return yMinI; } - int getYMaxI() { return yMaxI; } + int getXMinI(GBool strokeAdjust); + int getXMaxI(GBool strokeAdjust); + int getYMinI(GBool strokeAdjust); + int getYMaxI(GBool strokeAdjust); // Get the number of arbitrary paths used by the clip region. int getNumPaths() { return length; } @@ -100,14 +102,25 @@ private: SplashClip(SplashClip *clip); void grow(int nPaths); + void updateIntBounds(GBool strokeAdjust); + + int hardXMin, hardYMin, // coordinates cannot fall outside of + hardXMax, hardYMax; // [hardXMin, hardXMax), [hardYMin, hardYMax) + + SplashCoord xMin, yMin, // current clip bounding rectangle + xMax, yMax; // (these coordinates may be adjusted if + // stroke adjustment is enabled) - GBool antialias; - SplashCoord xMin, yMin, xMax, yMax; int xMinI, yMinI, xMaxI, yMaxI; + GBool intBoundsValid; // true if xMinI, etc. are valid + GBool intBoundsStrokeAdjust; // value of strokeAdjust used to compute + // xMinI, etc. + SplashXPath **paths; - Guchar *flags; + Guchar *eo; SplashXPathScanner **scanners; int length, size; + Guchar *buf; }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashErrorCodes.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashErrorCodes.h index 2a70d4b77d6..ebe6091faa2 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashErrorCodes.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashErrorCodes.h @@ -2,6 +2,8 @@ // // SplashErrorCodes.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHERRORCODES_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFont.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFont.cc index 218f13e1c3c..6fc6b946b65 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFont.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFont.cc @@ -2,6 +2,8 @@ // // SplashFTFont.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -242,23 +244,24 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac, return gFalse; } - flags = 0; - if (aa) { - flags |= FT_LOAD_NO_BITMAP; - } + // Set up the load flags: + // * disable bitmaps because they look ugly when scaled, rotated, + // etc. + // * disable autohinting because it can fail badly with font subsets + // that use invalid glyph names (the FreeType autohinter depends + // on the glyph name to figure out how to autohint the glyph) + // * but enable light autohinting for Type 1 fonts because regular + // hinting looks pretty bad, and the invalid glyph name issue + // seems to be very rare (Type 1 fonts are mostly used for + // substitution, in which case the full font is being used, which + // means we have the glyph names) + flags = FT_LOAD_NO_BITMAP; if (ff->engine->flags & splashFTNoHinting) { flags |= FT_LOAD_NO_HINTING; - } else if (ff->trueType) { - // FT2's autohinting doesn't always work very well (especially with - // font subsets), so turn it off if anti-aliasing is enabled; if - // anti-aliasing is disabled, this seems to be a tossup - some fonts - // look better with hinting, some without, so leave hinting on - if (aa) { - flags |= FT_LOAD_NO_AUTOHINT; - } - } else if (ff->type1) { - // Type 1 fonts seem to look better with 'light' hinting mode + } else if (ff->useLightHinting) { flags |= FT_LOAD_TARGET_LIGHT; + } else { + flags |= FT_LOAD_NO_AUTOHINT; } if (FT_Load_Glyph(ff->face, gid, flags)) { return gFalse; diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFont.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFont.h index 8e31d145965..560b74c3bfe 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFont.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFont.h @@ -2,6 +2,8 @@ // // SplashFTFont.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFTFONT_H diff --git a/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.cc new file mode 100644 index 00000000000..3ba033c9db3 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.cc @@ -0,0 +1,385 @@ +//======================================================================== +// +// SplashFTFontEngine.cc +// +// Copyright 2003-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdio.h> +#ifndef _WIN32 +# include <unistd.h> +#endif +#include "gmem.h" +#include "GString.h" +#include "gfile.h" +#include "FoFiTrueType.h" +#include "FoFiType1C.h" +#include "SplashFTFontFile.h" +#include "SplashFTFontEngine.h" +#include FT_MODULE_H +#ifdef FT_CFF_DRIVER_H +# include FT_CFF_DRIVER_H +#endif + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ + +static void fileWrite(void *stream, const char *data, int len) { + fwrite(data, 1, len, (FILE *)stream); +} + +#if LOAD_FONTS_FROM_MEM +static void gstringWrite(void *stream, const char *data, int len) { + ((GString *)stream)->append(data, len); +} +#endif + +//------------------------------------------------------------------------ +// SplashFTFontEngine +//------------------------------------------------------------------------ + +SplashFTFontEngine::SplashFTFontEngine(GBool aaA, Guint flagsA, + FT_Library libA) { + FT_Int major, minor, patch; + + aa = aaA; + flags = flagsA; + lib = libA; + + // as of FT 2.1.8, CID fonts are indexed by CID instead of GID + FT_Library_Version(lib, &major, &minor, &patch); + useCIDs = major > 2 || + (major == 2 && (minor > 1 || (minor == 1 && patch > 7))); +} + +SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA, Guint flagsA) { + FT_Library libA; + + if (FT_Init_FreeType(&libA)) { + return NULL; + } + return new SplashFTFontEngine(aaA, flagsA, libA); +} + +SplashFTFontEngine::~SplashFTFontEngine() { + FT_Done_FreeType(lib); +} + +SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, + GBool deleteFile, +#endif + const char **enc) { + return SplashFTFontFile::loadType1Font(this, idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + enc, gTrue); +} + +SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, + GBool deleteFile, +#endif + const char **enc) { + return SplashFTFontFile::loadType1Font(this, idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + enc, gFalse); +} + +SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, + GBool deleteFile, +#endif + const char **enc) { + FoFiTrueType *ff; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf2; +#else + GString *tmpFileName; + FILE *tmpFile; +#endif + SplashFontFile *ret; + +#if LOAD_FONTS_FROM_MEM + if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), + 0, gTrue))) { +#else + if (!(ff = FoFiTrueType::load(fileName, 0, gTrue))) { +#endif + return NULL; + } + if (ff->isHeadlessCFF()) { +#if LOAD_FONTS_FROM_MEM + fontBuf2 = new GString(); + ff->convertToType1(NULL, enc, gFalse, &gstringWrite, fontBuf2); + delete ff; + ret = SplashFTFontFile::loadType1Font(this, idA, fontBuf2, enc, + gFalse); + if (ret) { + delete fontBuf; + } else { + delete fontBuf2; + } +#else + tmpFileName = NULL; + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + delete ff; + return NULL; + } + ff->convertToType1(NULL, enc, gFalse, &fileWrite, tmpFile); + delete ff; + fclose(tmpFile); + ret = SplashFTFontFile::loadType1Font(this, idA, tmpFileName->getCString(), + gTrue, enc, gFalse); + if (ret) { + if (deleteFile) { + unlink(fileName); + } + } else { + unlink(tmpFileName->getCString()); + } + delete tmpFileName; +#endif + } else { + delete ff; + ret = SplashFTFontFile::loadType1Font(this, idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + enc, gFalse); + } + return ret; +} + +SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf +#else + char *fileName, + GBool deleteFile +#endif + ) { + FoFiType1C *ff; + int *cidToGIDMap; + int nCIDs; + SplashFontFile *ret; + + // check for a CFF font + if (useCIDs) { + cidToGIDMap = NULL; + nCIDs = 0; +#if LOAD_FONTS_FROM_MEM + } else if ((ff = FoFiType1C::make(fontBuf->getCString(), + fontBuf->getLength()))) { +#else + } else if ((ff = FoFiType1C::load(fileName))) { +#endif + cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); + delete ff; + } else { + cidToGIDMap = NULL; + nCIDs = 0; + } + ret = SplashFTFontFile::loadCIDFont(this, idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + cidToGIDMap, nCIDs); + if (!ret) { + gfree(cidToGIDMap); + } + return ret; +} + +SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, + GBool deleteFile, +#endif + int *codeToGID, + int codeToGIDLen) { + FoFiTrueType *ff; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf2; +#else + GString *tmpFileName; + FILE *tmpFile; +#endif + char *cffStart; + int cffLength; + int *cidToGIDMap; + int nCIDs; + SplashFontFile *ret; + +#if LOAD_FONTS_FROM_MEM + if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), + 0, gTrue))) { +#else + if (!(ff = FoFiTrueType::load(fileName, 0, gTrue))) { +#endif + return NULL; + } + cidToGIDMap = NULL; + nCIDs = 0; + if (ff->isHeadlessCFF()) { + if (!ff->getCFFBlock(&cffStart, &cffLength)) { + return NULL; + } +#if LOAD_FONTS_FROM_MEM + fontBuf2 = new GString(cffStart, cffLength); + if (!useCIDs) { + cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); + } + ret = SplashFTFontFile::loadCIDFont(this, idA, fontBuf2, + cidToGIDMap, nCIDs); + if (ret) { + delete fontBuf; + } else { + delete fontBuf2; + } +#else + tmpFileName = NULL; + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + delete ff; + return NULL; + } + fwrite(cffStart, 1, cffLength, tmpFile); + fclose(tmpFile); + if (!useCIDs) { + cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); + } + ret = SplashFTFontFile::loadCIDFont(this, idA, + tmpFileName->getCString(), gTrue, + cidToGIDMap, nCIDs); + if (ret) { + if (deleteFile) { + unlink(fileName); + } + } else { + unlink(tmpFileName->getCString()); + } + delete tmpFileName; +#endif + } else { + if (!codeToGID && !useCIDs && ff->isOpenTypeCFF()) { + cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); + } + ret = SplashFTFontFile::loadCIDFont(this, idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + codeToGID ? codeToGID : cidToGIDMap, + codeToGID ? codeToGIDLen : nCIDs); + } + delete ff; + if (!ret) { + gfree(cidToGIDMap); + } + return ret; +} + +SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, + GBool deleteFile, +#endif + int fontNum, + int *codeToGID, + int codeToGIDLen) { + FoFiTrueType *ff; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf2; +#else + GString *tmpFileName; + FILE *tmpFile; +#endif + SplashFontFile *ret; + +#if LOAD_FONTS_FROM_MEM + if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), + fontNum))) { +#else + if (!(ff = FoFiTrueType::load(fileName, fontNum))) { +#endif + return NULL; + } +#if LOAD_FONTS_FROM_MEM + fontBuf2 = new GString; + ff->writeTTF(&gstringWrite, fontBuf2); +#else + tmpFileName = NULL; + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + delete ff; + return NULL; + } + ff->writeTTF(&fileWrite, tmpFile); + fclose(tmpFile); +#endif + delete ff; + ret = SplashFTFontFile::loadTrueTypeFont(this, idA, +#if LOAD_FONTS_FROM_MEM + fontBuf2, +#else + tmpFileName->getCString(), gTrue, +#endif + 0, codeToGID, codeToGIDLen); +#if LOAD_FONTS_FROM_MEM + if (ret) { + delete fontBuf; + } else { + delete fontBuf2; + } +#else + if (ret) { + if (deleteFile) { + unlink(fileName); + } + } else { + unlink(tmpFileName->getCString()); + } + delete tmpFileName; +#endif + return ret; +} + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.h index 900bff24426..37e882007fe 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontEngine.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontEngine.h @@ -2,6 +2,8 @@ // // SplashFTFontEngine.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFTFONTENGINE_H @@ -18,6 +20,7 @@ #include <ft2build.h> #include FT_FREETYPE_H #include "gtypes.h" +class GString; class SplashFontFile; class SplashFontFileID; @@ -34,19 +37,48 @@ public: ~SplashFTFontEngine(); // Load fonts. - SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName, - GBool deleteFile, const char **enc); - SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile, const char **enc); - SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile, const char **enc); - SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile); - SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile, + SplashFontFile *loadType1Font(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + const char **enc); + SplashFontFile *loadType1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + const char **enc); + SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + const char **enc); + SplashFontFile *loadCIDFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf +#else + char *fileName, GBool deleteFile +#endif + ); + SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif int *codeToGID, int codeToGIDLen); - SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName, - int fontNum, GBool deleteFile, + SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + int fontNum, int *codeToGID, int codeToGIDLen); private: diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontFile.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontFile.cc index 5761117f6d8..5b01fcf490c 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontFile.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontFile.cc @@ -2,6 +2,8 @@ // // SplashFTFontFile.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -13,6 +15,7 @@ #endif #include "gmem.h" +#include "GString.h" #include "SplashFTFontEngine.h" #include "SplashFTFont.h" #include "SplashFTFontFile.h" @@ -23,15 +26,25 @@ SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA, SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else char *fileNameA, GBool deleteFileA, - const char **encA) { +#endif + const char **encA, + GBool useLightHintingA) { FT_Face faceA; int *codeToGIDA; const char *name; int i; +#if LOAD_FONTS_FROM_MEM + if (FT_New_Memory_Face(engineA->lib, (FT_Byte *)fontBufA->getCString(), + fontBufA->getLength(), 0, &faceA)) { +#else if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) { +#endif return NULL; } codeToGIDA = (int *)gmallocn(256, sizeof(int)); @@ -42,59 +55,101 @@ SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA, } } - return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA, - faceA, codeToGIDA, 256, gFalse, gTrue); + return new SplashFTFontFile(engineA, idA, +#if LOAD_FONTS_FROM_MEM + fontBufA, +#else + fileNameA, deleteFileA, +#endif + faceA, codeToGIDA, 256, + gFalse, useLightHintingA); } SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA, SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else char *fileNameA, GBool deleteFileA, +#endif int *codeToGIDA, int codeToGIDLenA) { FT_Face faceA; +#if LOAD_FONTS_FROM_MEM + if (FT_New_Memory_Face(engineA->lib, (FT_Byte *)fontBufA->getCString(), + fontBufA->getLength(), 0, &faceA)) { +#else if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) { +#endif return NULL; } - return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA, + return new SplashFTFontFile(engineA, idA, +#if LOAD_FONTS_FROM_MEM + fontBufA, +#else + fileNameA, deleteFileA, +#endif faceA, codeToGIDA, codeToGIDLenA, gFalse, gFalse); } SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA, SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else char *fileNameA, - int fontNum, GBool deleteFileA, +#endif + int fontNum, int *codeToGIDA, int codeToGIDLenA) { FT_Face faceA; +#if LOAD_FONTS_FROM_MEM + if (FT_New_Memory_Face(engineA->lib, (FT_Byte *)fontBufA->getCString(), + fontBufA->getLength(), fontNum, &faceA)) { +#else if (FT_New_Face(engineA->lib, fileNameA, fontNum, &faceA)) { +#endif return NULL; } - return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA, + return new SplashFTFontFile(engineA, idA, +#if LOAD_FONTS_FROM_MEM + fontBufA, +#else + fileNameA, deleteFileA, +#endif faceA, codeToGIDA, codeToGIDLenA, gTrue, gFalse); } SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA, SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else char *fileNameA, GBool deleteFileA, +#endif FT_Face faceA, int *codeToGIDA, int codeToGIDLenA, - GBool trueTypeA, GBool type1A): + GBool trueTypeA, GBool useLightHintingA): +#if LOAD_FONTS_FROM_MEM + SplashFontFile(idA, fontBufA) +#else SplashFontFile(idA, fileNameA, deleteFileA) +#endif { engine = engineA; face = faceA; codeToGID = codeToGIDA; codeToGIDLen = codeToGIDLenA; trueType = trueTypeA; - type1 = type1A; + useLightHinting = useLightHintingA; } SplashFTFontFile::~SplashFTFontFile() { diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontFile.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontFile.h index 0f45e4f778c..21fa517a594 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFTFontFile.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFTFontFile.h @@ -2,6 +2,8 @@ // // SplashFTFontFile.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFTFONTFILE_H @@ -30,17 +32,31 @@ class SplashFTFontFile: public SplashFontFile { public: static SplashFontFile *loadType1Font(SplashFTFontEngine *engineA, - SplashFontFileID *idA, char *fileNameA, - GBool deleteFileA, const char **encA); + SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else + char *fileNameA, GBool deleteFileA, +#endif + const char **encA, + GBool useLightHintingA); static SplashFontFile *loadCIDFont(SplashFTFontEngine *engineA, - SplashFontFileID *idA, char *fileNameA, - GBool deleteFileA, + SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else + char *fileNameA, GBool deleteFileA, +#endif int *codeToGIDA, int codeToGIDLenA); static SplashFontFile *loadTrueTypeFont(SplashFTFontEngine *engineA, SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else char *fileNameA, - int fontNum, GBool deleteFileA, +#endif + int fontNum, int *codeToGIDA, int codeToGIDLenA); @@ -55,17 +71,21 @@ private: SplashFTFontFile(SplashFTFontEngine *engineA, SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA, +#else char *fileNameA, GBool deleteFileA, +#endif FT_Face faceA, int *codeToGIDA, int codeToGIDLenA, - GBool trueTypeA, GBool type1A); + GBool trueTypeA, GBool useLightHintingA); SplashFTFontEngine *engine; FT_Face face; int *codeToGID; int codeToGIDLen; GBool trueType; - GBool type1; + GBool useLightHinting; friend class SplashFTFont; }; diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFont.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFont.cc index 6ab2ecf5c62..37a320050be 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFont.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFont.cc @@ -2,6 +2,8 @@ // // SplashFont.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFont.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFont.h index 60a2db763f4..3d151122a14 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFont.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFont.h @@ -2,6 +2,8 @@ // // SplashFont.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFONT_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontEngine.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontEngine.cc index 5f5ad46569e..d4673a7a7c4 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontEngine.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontEngine.cc @@ -2,6 +2,8 @@ // // SplashFontEngine.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -10,19 +12,14 @@ #pragma implementation #endif -#if HAVE_T1LIB_H -#include <t1lib.h> -#endif - #include <stdlib.h> #include <stdio.h> -#ifndef WIN32 +#ifndef _WIN32 # include <unistd.h> #endif #include "gmem.h" #include "GString.h" #include "SplashMath.h" -#include "SplashT1FontEngine.h" #include "SplashFTFontEngine.h" #include "SplashFontFile.h" #include "SplashFontFileID.h" @@ -40,9 +37,6 @@ extern "C" int unlink(char *filename); //------------------------------------------------------------------------ SplashFontEngine::SplashFontEngine( -#if HAVE_T1LIB_H - GBool enableT1lib, -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H GBool enableFreeType, Guint freeTypeFlags, @@ -54,13 +48,6 @@ SplashFontEngine::SplashFontEngine( fontCache[i] = NULL; } -#if HAVE_T1LIB_H - if (enableT1lib) { - t1Engine = SplashT1FontEngine::init(aa); - } else { - t1Engine = NULL; - } -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (enableFreeType) { ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags); @@ -79,11 +66,6 @@ SplashFontEngine::~SplashFontEngine() { } } -#if HAVE_T1LIB_H - if (t1Engine) { - delete t1Engine; - } -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (ftEngine) { delete ftEngine; @@ -107,24 +89,29 @@ SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) { } SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else char *fileName, GBool deleteFile, +#endif const char **enc) { SplashFontFile *fontFile; fontFile = NULL; -#if HAVE_T1LIB_H - if (!fontFile && t1Engine) { - fontFile = t1Engine->loadType1Font(idA, fileName, deleteFile, enc); - } -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (!fontFile && ftEngine) { - fontFile = ftEngine->loadType1Font(idA, fileName, deleteFile, enc); + fontFile = ftEngine->loadType1Font(idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + enc); } #endif -#ifndef WIN32 +#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) // delete the (temporary) font file -- with Unix hard link // semantics, this will remove the last link; otherwise it will // return an error, leaving the file to be deleted later (if @@ -138,24 +125,29 @@ SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA, } SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else char *fileName, GBool deleteFile, +#endif const char **enc) { SplashFontFile *fontFile; fontFile = NULL; -#if HAVE_T1LIB_H - if (!fontFile && t1Engine) { - fontFile = t1Engine->loadType1CFont(idA, fileName, deleteFile, enc); - } -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (!fontFile && ftEngine) { - fontFile = ftEngine->loadType1CFont(idA, fileName, deleteFile, enc); + fontFile = ftEngine->loadType1CFont(idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + enc); } #endif -#ifndef WIN32 +#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) // delete the (temporary) font file -- with Unix hard link // semantics, this will remove the last link; otherwise it will // return an error, leaving the file to be deleted later (if @@ -169,19 +161,29 @@ SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA, } SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else char *fileName, GBool deleteFile, +#endif const char **enc) { SplashFontFile *fontFile; fontFile = NULL; #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (!fontFile && ftEngine) { - fontFile = ftEngine->loadOpenTypeT1CFont(idA, fileName, deleteFile, enc); + fontFile = ftEngine->loadOpenTypeT1CFont(idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + enc); } #endif -#ifndef WIN32 +#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) // delete the (temporary) font file -- with Unix hard link // semantics, this will remove the last link; otherwise it will // return an error, leaving the file to be deleted later (if @@ -195,18 +197,29 @@ SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, } SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf +#else char *fileName, - GBool deleteFile) { + GBool deleteFile +#endif + ) { SplashFontFile *fontFile; fontFile = NULL; #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (!fontFile && ftEngine) { - fontFile = ftEngine->loadCIDFont(idA, fileName, deleteFile); + fontFile = ftEngine->loadCIDFont(idA, +#if LOAD_FONTS_FROM_MEM + fontBuf +#else + fileName, deleteFile +#endif + ); } #endif -#ifndef WIN32 +#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) // delete the (temporary) font file -- with Unix hard link // semantics, this will remove the last link; otherwise it will // return an error, leaving the file to be deleted later (if @@ -220,8 +233,12 @@ SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA, } SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else char *fileName, GBool deleteFile, +#endif int *codeToGID, int codeToGIDLen) { SplashFontFile *fontFile; @@ -229,12 +246,17 @@ SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, fontFile = NULL; #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (!fontFile && ftEngine) { - fontFile = ftEngine->loadOpenTypeCFFFont(idA, fileName, deleteFile, + fontFile = ftEngine->loadOpenTypeCFFFont(idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif codeToGID, codeToGIDLen); } #endif -#ifndef WIN32 +#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) // delete the (temporary) font file -- with Unix hard link // semantics, this will remove the last link; otherwise it will // return an error, leaving the file to be deleted later (if @@ -248,9 +270,13 @@ SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, } SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else char *fileName, - int fontNum, GBool deleteFile, +#endif + int fontNum, int *codeToGID, int codeToGIDLen, char *fontName) { @@ -259,8 +285,13 @@ SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, fontFile = NULL; #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H if (!fontFile && ftEngine) { - fontFile = ftEngine->loadTrueTypeFont(idA, fileName, fontNum, deleteFile, - codeToGID, codeToGIDLen); + fontFile = ftEngine->loadTrueTypeFont(idA, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName, deleteFile, +#endif + fontNum, codeToGID, codeToGIDLen); } #endif @@ -268,7 +299,7 @@ SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, gfree(codeToGID); } -#ifndef WIN32 +#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) // delete the (temporary) font file -- with Unix hard link // semantics, this will remove the last link; otherwise it will // return an error, leaving the file to be deleted later (if diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontEngine.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontEngine.h index a6d0e58ab61..43eb6d3eb48 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontEngine.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontEngine.h @@ -2,6 +2,8 @@ // // SplashFontEngine.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFONTENGINE_H @@ -14,8 +16,8 @@ #endif #include "gtypes.h" +class GString; -class SplashT1FontEngine; class SplashFTFontEngine; class SplashDTFontEngine; class SplashDT4FontEngine; @@ -40,9 +42,6 @@ public: // Create a font engine. SplashFontEngine( -#if HAVE_T1LIB_H - GBool enableT1lib, -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H GBool enableFreeType, Guint freeTypeFlags, @@ -56,19 +55,48 @@ public: SplashFontFile *getFontFile(SplashFontFileID *id); // Load fonts - these create new SplashFontFile objects. - SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName, - GBool deleteFile, const char **enc); - SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile, const char **enc); - SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile, const char **enc); - SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile); - SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, char *fileName, - GBool deleteFile, + SplashFontFile *loadType1Font(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + const char **enc); + SplashFontFile *loadType1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + const char **enc); + SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + const char **enc); + SplashFontFile *loadCIDFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf +#else + char *fileName, GBool deleteFile +#endif + ); + SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif int *codeToGID, int codeToGIDLen); - SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName, - int fontNum, GBool deleteFile, + SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBuf, +#else + char *fileName, GBool deleteFile, +#endif + int fontNum, int *codeToGID, int codeToGIDLen, char *fontName); @@ -87,9 +115,6 @@ private: SplashFont *fontCache[splashFontCacheSize]; -#if HAVE_T1LIB_H - SplashT1FontEngine *t1Engine; -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H SplashFTFontEngine *ftEngine; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFile.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFile.cc index acbc12a3b4f..d0e36a20c49 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFile.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFile.cc @@ -2,6 +2,8 @@ // // SplashFontFile.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -11,7 +13,7 @@ #endif #include <stdio.h> -#ifndef WIN32 +#ifndef _WIN32 # include <unistd.h> #endif #include "GString.h" @@ -28,19 +30,32 @@ extern "C" int unlink(char *filename); // SplashFontFile //------------------------------------------------------------------------ -SplashFontFile::SplashFontFile(SplashFontFileID *idA, char *fileNameA, - GBool deleteFileA) { +SplashFontFile::SplashFontFile(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA +#else + char *fileNameA, GBool deleteFileA +#endif + ) { id = idA; +#if LOAD_FONTS_FROM_MEM + fontBuf = fontBufA; +#else fileName = new GString(fileNameA); deleteFile = deleteFileA; +#endif refCnt = 0; } SplashFontFile::~SplashFontFile() { +#if LOAD_FONTS_FROM_MEM + delete fontBuf; +#else if (deleteFile) { unlink(fileName->getCString()); } delete fileName; +#endif delete id; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFile.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFile.h index 9f893129524..5f53eced170 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFile.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFile.h @@ -2,6 +2,8 @@ // // SplashFontFile.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFONTFILE_H @@ -46,12 +48,21 @@ public: protected: - SplashFontFile(SplashFontFileID *idA, char *fileNameA, - GBool deleteFileA); + SplashFontFile(SplashFontFileID *idA, +#if LOAD_FONTS_FROM_MEM + GString *fontBufA +#else + char *fileNameA, GBool deleteFileA +#endif + ); SplashFontFileID *id; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf; +#else GString *fileName; GBool deleteFile; +#endif int refCnt; friend class SplashFontEngine; diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFileID.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFileID.cc index af37cb2fd8c..327484788f6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFileID.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFileID.cc @@ -2,6 +2,8 @@ // // SplashFontFileID.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFileID.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFileID.h index bed11d336e0..384018a2f3a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashFontFileID.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashFontFileID.h @@ -2,6 +2,8 @@ // // SplashFontFileID.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHFONTFILEID_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashGlyphBitmap.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashGlyphBitmap.h index 044ba4a66ff..d375b3ccb46 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashGlyphBitmap.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashGlyphBitmap.h @@ -2,6 +2,8 @@ // // SplashGlyphBitmap.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHGLYPHBITMAP_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashMath.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashMath.h index 3b82e7a99a8..4b7ab1fdfbd 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashMath.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashMath.h @@ -2,6 +2,8 @@ // // SplashMath.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHMATH_H @@ -35,19 +37,18 @@ static inline int splashFloor(SplashCoord x) { Gushort oldCW, newCW, t; int result; - __asm__ volatile("fldl %4\n" - "fnstcw %0\n" + __asm__ volatile("fnstcw %0\n" "movw %0, %3\n" "andw $0xf3ff, %3\n" "orw $0x0400, %3\n" "movw %3, %1\n" // round down "fldcw %1\n" - "fistpl %2\n" + "fistl %2\n" "fldcw %0\n" : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t) - : "m" (x)); + : "t" (x)); return result; -#elif defined(WIN32) && defined(_M_IX86) +#elif defined(_WIN32) && defined(_M_IX86) // floor() and (int)() are implemented separately, which results // in changing the FPCW multiple times - so we optimize it with // some inline assembly @@ -81,19 +82,18 @@ static inline int splashCeil(SplashCoord x) { Gushort oldCW, newCW, t; int result; - __asm__ volatile("fldl %4\n" - "fnstcw %0\n" + __asm__ volatile("fnstcw %0\n" "movw %0, %3\n" "andw $0xf3ff, %3\n" "orw $0x0800, %3\n" "movw %3, %1\n" // round up "fldcw %1\n" - "fistpl %2\n" + "fistl %2\n" "fldcw %0\n" : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t) - : "m" (x)); + : "t" (x)); return result; -#elif defined(WIN32) && defined(_M_IX86) +#elif defined(_WIN32) && defined(_M_IX86) // ceil() and (int)() are implemented separately, which results // in changing the FPCW multiple times - so we optimize it with // some inline assembly @@ -128,19 +128,18 @@ static inline int splashRound(SplashCoord x) { int result; x += 0.5; - __asm__ volatile("fldl %4\n" - "fnstcw %0\n" + __asm__ volatile("fnstcw %0\n" "movw %0, %3\n" "andw $0xf3ff, %3\n" "orw $0x0400, %3\n" "movw %3, %1\n" // round down "fldcw %1\n" - "fistpl %2\n" + "fistl %2\n" "fldcw %0\n" : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t) - : "m" (x)); + : "t" (x)); return result; -#elif defined(WIN32) && defined(_M_IX86) +#elif defined(_WIN32) && defined(_M_IX86) // this could use round-to-nearest mode and avoid the "+0.5", // but that produces slightly different results (because i+0.5 // sometimes rounds up and sometimes down using the even rule) @@ -223,4 +222,68 @@ static inline GBool splashCheckDet(SplashCoord m11, SplashCoord m12, #endif } +// Perform stroke adjustment on a SplashCoord range [xMin, xMax), +// resulting in an int range [*xMinI, *xMaxI). +// +// There are several options: +// +// 1. Round both edge coordinates. +// Pro: adjacent strokes/fills line up without any gaps or +// overlaps +// Con: lines with the same original floating point width can +// end up with different integer widths, e.g.: +// xMin = 10.1 xMax = 11.3 (width = 1.2) +// --> xMinI = 10 xMaxI = 11 (width = 1) +// but +// xMin = 10.4 xMax = 11.6 (width = 1.2) +// --> xMinI = 10 xMaxI = 12 (width = 2) +// +// 2. Round the min coordinate; add the ceiling of the width. +// Pro: lines with the same original floating point width will +// always end up with the same integer width +// Con: adjacent strokes/fills can have overlaps (which is +// problematic with transparency) +// (This could use floor on the min coordinate, instead of +// rounding, with similar results.) +// (If the width is rounded instead of using ceiling, the results +// Are similar, except that adjacent strokes/fills can have gaps +// as well as overlaps.) +// +// 3. Use floor on the min coordinate and ceiling on the max +// coordinate. +// Pro: lines always end up at least as wide as the original +// floating point width +// Con: adjacent strokes/fills can have overlaps, and lines with +// the same original floating point width can end up with +// different integer widths; the integer width can be more +// than one pixel wider than the original width, e.g.: +// xMin = 10.9 xMax = 12.1 (width = 1.2) +// --> xMinI = 10 xMaxI = 13 (width = 3) +// but +// xMin = 10.1 xMax = 11.3 (width = 1.2) +// --> xMinI = 10 xMaxI = 12 (width = 2) +static inline void splashStrokeAdjust(SplashCoord xMin, SplashCoord xMax, + int *xMinI, int *xMaxI) { + int x0, x1; + + // NB: enable exactly one of these. +#if 1 // 1. Round both edge coordinates. + x0 = splashRound(xMin); + x1 = splashRound(xMax); +#endif +#if 0 // 2. Round the min coordinate; add the ceiling of the width. + x0 = splashRound(xMin); + x1 = x0 + splashCeil(xMax - xMin); +#endif +#if 0 // 3. Use floor on the min coord and ceiling on the max coord. + x0 = splashFloor(xMin); + x1 = splashCeil(xMax); +#endif + if (x1 == x0) { + ++x1; + } + *xMinI = x0; + *xMaxI = x1; +} + #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPath.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPath.cc index b4249ed6c27..4ee8be02809 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPath.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPath.cc @@ -2,6 +2,8 @@ // // SplashPath.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -53,6 +55,7 @@ SplashPath::SplashPath(SplashPath *path) { memcpy(hints, path->hints, hintsLength * sizeof(SplashPathHint)); } else { hints = NULL; + hintsLength = hintsSize = 0; } } diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPath.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPath.h index aae51f2e93a..a8715302042 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPath.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPath.h @@ -2,6 +2,8 @@ // // SplashPath.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHPATH_H @@ -94,7 +96,7 @@ public: // Get the points on the path. int getLength() { return length; } - void getPoint(int i, double *x, double *y, Guchar *f) + void getPoint(int i, SplashCoord *x, SplashCoord *y, Guchar *f) { *x = pts[i].x; *y = pts[i].y; *f = flags[i]; } // Get the current point. diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPattern.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPattern.cc index b77658ef43c..6ca4fb274e8 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPattern.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPattern.cc @@ -2,6 +2,8 @@ // // SplashPattern.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPattern.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPattern.h index 0a02e9c29bc..01207bfae40 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashPattern.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashPattern.h @@ -2,6 +2,8 @@ // // SplashPattern.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHPATTERN_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashScreen.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashScreen.cc index f717173bbff..68a762f7f2a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashScreen.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashScreen.cc @@ -2,6 +2,8 @@ // // SplashScreen.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashScreen.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashScreen.h index 708c37f39ef..4e9767be5f6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashScreen.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashScreen.h @@ -2,6 +2,8 @@ // // SplashScreen.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHSCREEN_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashState.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashState.cc index e6dde618d48..09c1949eb3d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashState.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashState.cc @@ -2,6 +2,8 @@ // // SplashState.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -45,7 +47,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, blendFunc = NULL; strokeAlpha = 1; fillAlpha = 1; - lineWidth = 0; + lineWidth = 1; lineCap = splashLineCapButt; lineJoin = splashLineJoinMiter; miterLimit = 10; @@ -54,10 +56,12 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, lineDashLength = 0; lineDashPhase = 0; strokeAdjust = gFalse; - clip = new SplashClip(0, 0, width, height, vectorAntialias); + clip = new SplashClip(0, 0, width, height); + clipIsShared = gFalse; softMask = NULL; deleteSoftMask = gFalse; inNonIsolatedGroup = gFalse; + inKnockoutGroup = gFalse; for (i = 0; i < 256; ++i) { rgbTransferR[i] = (Guchar)i; rgbTransferG[i] = (Guchar)i; @@ -87,7 +91,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, blendFunc = NULL; strokeAlpha = 1; fillAlpha = 1; - lineWidth = 0; + lineWidth = 1; lineCap = splashLineCapButt; lineJoin = splashLineJoinMiter; miterLimit = 10; @@ -96,10 +100,12 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias, lineDashLength = 0; lineDashPhase = 0; strokeAdjust = gFalse; - clip = new SplashClip(0, 0, width, height, vectorAntialias); + clip = new SplashClip(0, 0, width, height); + clipIsShared = gFalse; softMask = NULL; deleteSoftMask = gFalse; inNonIsolatedGroup = gFalse; + inKnockoutGroup = gFalse; for (i = 0; i < 256; ++i) { rgbTransferR[i] = (Guchar)i; rgbTransferG[i] = (Guchar)i; @@ -137,10 +143,12 @@ SplashState::SplashState(SplashState *state) { } lineDashPhase = state->lineDashPhase; strokeAdjust = state->strokeAdjust; - clip = state->clip->copy(); + clip = state->clip; + clipIsShared = gTrue; softMask = state->softMask; deleteSoftMask = gFalse; inNonIsolatedGroup = state->inNonIsolatedGroup; + inKnockoutGroup = state->inKnockoutGroup; memcpy(rgbTransferR, state->rgbTransferR, 256); memcpy(rgbTransferG, state->rgbTransferG, 256); memcpy(rgbTransferB, state->rgbTransferB, 256); @@ -158,7 +166,9 @@ SplashState::~SplashState() { delete fillPattern; delete screen; gfree(lineDash); - delete clip; + if (!clipIsShared) { + delete clip; + } if (deleteSoftMask && softMask) { delete softMask; } @@ -192,6 +202,32 @@ void SplashState::setLineDash(SplashCoord *lineDashA, int lineDashLengthA, lineDashPhase = lineDashPhaseA; } +void SplashState::clipResetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + if (clipIsShared) { + clip = clip->copy(); + clipIsShared = gFalse; + } + clip->resetToRect(x0, y0, x1, y1); +} + +SplashError SplashState::clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + if (clipIsShared) { + clip = clip->copy(); + clipIsShared = gFalse; + } + return clip->clipToRect(x0, y0, x1, y1); +} + +SplashError SplashState::clipToPath(SplashPath *path, GBool eo) { + if (clipIsShared) { + clip = clip->copy(); + clipIsShared = gFalse; + } + return clip->clipToPath(path, matrix, flatness, eo); +} + void SplashState::setSoftMask(SplashBitmap *softMaskA) { if (deleteSoftMask) { delete softMask; diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashState.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashState.h index 0d1b6c51652..fe773a5403f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashState.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashState.h @@ -2,6 +2,8 @@ // // SplashState.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHSTATE_H @@ -19,6 +21,7 @@ class SplashPattern; class SplashScreen; class SplashClip; class SplashBitmap; +class SplashPath; //------------------------------------------------------------------------ // line cap values @@ -67,6 +70,12 @@ public: void setLineDash(SplashCoord *lineDashA, int lineDashLengthA, SplashCoord lineDashPhaseA); + void clipResetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + SplashError clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + SplashError clipToPath(SplashPath *path, GBool eo); + // Set the soft mask bitmap. void setSoftMask(SplashBitmap *softMaskA); @@ -94,9 +103,11 @@ private: SplashCoord lineDashPhase; GBool strokeAdjust; SplashClip *clip; + GBool clipIsShared; SplashBitmap *softMask; GBool deleteSoftMask; GBool inNonIsolatedGroup; + GBool inKnockoutGroup; Guchar rgbTransferR[256], rgbTransferG[256], rgbTransferB[256]; diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1Font.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1Font.cc index 703aacf1f38..703aacf1f38 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1Font.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1Font.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1Font.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1Font.h index 8ea74de48f8..8ea74de48f8 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1Font.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1Font.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontEngine.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontEngine.cc index 277e2fc99d3..277e2fc99d3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontEngine.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontEngine.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontEngine.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontEngine.h index 8942b853697..8942b853697 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontEngine.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontEngine.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontFile.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontFile.cc index 8cec742997a..8cec742997a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontFile.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontFile.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontFile.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontFile.h index 57de84d7149..57de84d7149 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashT1FontFile.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashT1FontFile.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashTypes.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashTypes.h index 6eb26073832..240cb6f7b8c 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashTypes.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashTypes.h @@ -2,6 +2,8 @@ // // SplashTypes.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHTYPES_H diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPath.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPath.cc index 6ed2f4b171c..a1599885e2b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPath.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPath.cc @@ -2,6 +2,8 @@ // // SplashXPath.cc // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #include <aconf.h> @@ -54,12 +56,10 @@ inline void SplashXPath::transform(SplashCoord *matrix, SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, SplashCoord flatness, GBool closeSubpaths) { - SplashPathHint *hint; SplashXPathPoint *pts; - SplashXPathAdjust *adjusts, *adjust; SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp; - SplashCoord adj0, adj1; - int curSubpath, curSubpathX, i, j; + SplashCoord xMinFP, xMaxFP, yMinFP, yMaxFP; + int curSubpath, i; // transform the points pts = (SplashXPathPoint *)gmallocn(path->length, sizeof(SplashXPathPoint)); @@ -67,78 +67,16 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, transform(matrix, path->pts[i].x, path->pts[i].y, &pts[i].x, &pts[i].y); } - // set up the stroke adjustment hints + // do stroke adjustment if (path->hints) { - adjusts = (SplashXPathAdjust *)gmallocn(path->hintsLength, - sizeof(SplashXPathAdjust)); - for (i = 0; i < path->hintsLength; ++i) { - hint = &path->hints[i]; - x0 = pts[hint->ctrl0 ].x; y0 = pts[hint->ctrl0 ].y; - x1 = pts[hint->ctrl0 + 1].x; y1 = pts[hint->ctrl0 + 1].y; - x2 = pts[hint->ctrl1 ].x; y2 = pts[hint->ctrl1 ].y; - x3 = pts[hint->ctrl1 + 1].x; y3 = pts[hint->ctrl1 + 1].y; - if (x0 == x1 && x2 == x3) { - adjusts[i].vert = gTrue; - adj0 = x0; - adj1 = x2; - } else if (y0 == y1 && y2 == y3) { - adjusts[i].vert = gFalse; - adj0 = y0; - adj1 = y2; - } else { - gfree(adjusts); - adjusts = NULL; - break; - } - if (adj0 > adj1) { - x0 = adj0; - adj0 = adj1; - adj1 = x0; - } - adjusts[i].x0a = adj0 - 0.01; - adjusts[i].x0b = adj0 + 0.01; - adjusts[i].xma = (SplashCoord)0.5 * (adj0 + adj1) - 0.01; - adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + 0.01; - adjusts[i].x1a = adj1 - 0.01; - adjusts[i].x1b = adj1 + 0.01; - // rounding both edge coordinates can result in lines of - // different widths (e.g., adj=10.1, adj1=11.3 --> x0=10, x1=11; - // adj0=10.4, adj1=11.6 --> x0=10, x1=12), but it has the - // benefit of making adjacent strokes/fills line up without any - // gaps between them - x0 = splashRound(adj0); - x1 = splashRound(adj1); - if (x1 == x0) { - x1 = x1 + 1; - } - adjusts[i].x0 = (SplashCoord)x0; - adjusts[i].x1 = (SplashCoord)x1 - 0.01; - adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1); - adjusts[i].firstPt = hint->firstPt; - adjusts[i].lastPt = hint->lastPt; - } - - } else { - adjusts = NULL; - } - - // perform stroke adjustment - if (adjusts) { - for (i = 0, adjust = adjusts; i < path->hintsLength; ++i, ++adjust) { - for (j = adjust->firstPt; j <= adjust->lastPt; ++j) { - strokeAdjust(adjust, &pts[j].x, &pts[j].y); - } - } - gfree(adjusts); + strokeAdjust(pts, path->hints, path->hintsLength); } segs = NULL; length = size = 0; x0 = y0 = xsp = ysp = 0; // make gcc happy - adj0 = adj1 = 0; // make gcc happy curSubpath = 0; - curSubpathX = 0; i = 0; while (i < path->length) { @@ -149,7 +87,6 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, xsp = x0; ysp = y0; curSubpath = i; - curSubpathX = length; ++i; } else { @@ -197,32 +134,130 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, } gfree(pts); + +#if HAVE_STD_SORT + std::sort(segs, segs + length, SplashXPathSeg::cmpY); +#else + qsort(segs, length, sizeof(SplashXPathSeg), &SplashXPathSeg::cmpY); +#endif + + if (length == 0) { + xMin = yMin = xMax = yMax = 0; + } else { + if (segs[0].x0 < segs[0].x1) { + xMinFP = segs[0].x0; + xMaxFP = segs[0].x1; + } else { + xMinFP = segs[0].x1; + xMaxFP = segs[0].x0; + } + yMinFP = segs[0].y0; + yMaxFP = segs[0].y1; + for (i = 1; i < length; ++i) { + if (segs[i].x0 < xMinFP) { + xMinFP = segs[i].x0; + } else if (segs[i].x0 > xMaxFP) { + xMaxFP = segs[i].x0; + } + if (segs[i].x1 < xMinFP) { + xMinFP = segs[i].x1; + } else if (segs[i].x1 > xMaxFP) { + xMaxFP = segs[i].x1; + } + if (segs[i].y1 > yMaxFP) { + yMaxFP = segs[i].y1; + } + } + xMin = splashFloor(xMinFP); + yMin = splashFloor(yMinFP); + xMax = splashFloor(xMaxFP); + yMax = splashFloor(yMaxFP); + } } -// Apply the stroke adjust hints to point <pt>: (*<xp>, *<yp>). -void SplashXPath::strokeAdjust(SplashXPathAdjust *adjust, - SplashCoord *xp, SplashCoord *yp) { - SplashCoord x, y; +void SplashXPath::strokeAdjust(SplashXPathPoint *pts, + SplashPathHint *hints, int nHints) { + SplashXPathAdjust *adjusts, *adjust; + SplashPathHint *hint; + SplashCoord x0, y0, x1, y1, x2, y2, x3, y3; + SplashCoord adj0, adj1, d; + int xi0, xi1; + int i, j; - if (adjust->vert) { - x = *xp; - if (x > adjust->x0a && x < adjust->x0b) { - *xp = adjust->x0; - } else if (x > adjust->xma && x < adjust->xmb) { - *xp = adjust->xm; - } else if (x > adjust->x1a && x < adjust->x1b) { - *xp = adjust->x1; + // set up the stroke adjustment hints + adjusts = (SplashXPathAdjust *)gmallocn(nHints, sizeof(SplashXPathAdjust)); + for (i = 0; i < nHints; ++i) { + hint = &hints[i]; + x0 = pts[hint->ctrl0 ].x; y0 = pts[hint->ctrl0 ].y; + x1 = pts[hint->ctrl0 + 1].x; y1 = pts[hint->ctrl0 + 1].y; + x2 = pts[hint->ctrl1 ].x; y2 = pts[hint->ctrl1 ].y; + x3 = pts[hint->ctrl1 + 1].x; y3 = pts[hint->ctrl1 + 1].y; + if (x0 == x1 && x2 == x3) { + adjusts[i].vert = gTrue; + adj0 = x0; + adj1 = x2; + } else if (y0 == y1 && y2 == y3) { + adjusts[i].vert = gFalse; + adj0 = y0; + adj1 = y2; + } else { + goto done; } - } else { - y = *yp; - if (y > adjust->x0a && y < adjust->x0b) { - *yp = adjust->x0; - } else if (y > adjust->xma && y < adjust->xmb) { - *yp = adjust->xm; - } else if (y > adjust->x1a && y < adjust->x1b) { - *yp = adjust->x1; + if (adj0 > adj1) { + x0 = adj0; + adj0 = adj1; + adj1 = x0; + } + d = adj1 - adj0; + if (d > 0.04) { + d = 0.01; + } else { + d *= 0.25; } + adjusts[i].x0a = adj0 - d; + adjusts[i].x0b = adj0 + d; + adjusts[i].xma = (SplashCoord)0.5 * (adj0 + adj1) - d; + adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + d; + adjusts[i].x1a = adj1 - d; + adjusts[i].x1b = adj1 + d; + splashStrokeAdjust(adj0, adj1, &xi0, &xi1); + adjusts[i].x0 = (SplashCoord)xi0; + // the "minus epsilon" thing here is needed when vector + // antialiasing is turned off -- otherwise stroke adjusted lines + // will touch an extra pixel on one edge + adjusts[i].x1 = (SplashCoord)xi1 - 0.001; + adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1); + adjusts[i].firstPt = hint->firstPt; + adjusts[i].lastPt = hint->lastPt; } + + // perform stroke adjustment + for (i = 0, adjust = adjusts; i < nHints; ++i, ++adjust) { + for (j = adjust->firstPt; j <= adjust->lastPt; ++j) { + if (adjust->vert) { + x0 = pts[j].x; + if (x0 > adjust->x0a && x0 < adjust->x0b) { + pts[j].x = adjust->x0; + } else if (x0 > adjust->xma && x0 < adjust->xmb) { + pts[j].x = adjust->xm; + } else if (x0 > adjust->x1a && x0 < adjust->x1b) { + pts[j].x = adjust->x1; + } + } else { + y0 = pts[j].y; + if (y0 > adjust->x0a && y0 < adjust->x0b) { + pts[j].y = adjust->x0; + } else if (y0 > adjust->xma && y0 < adjust->xmb) { + pts[j].y = adjust->xm; + } else if (y0 > adjust->x1a && y0 < adjust->x1b) { + pts[j].y = adjust->x1; + } + } + } + } + + done: + gfree(adjusts); } SplashXPath::SplashXPath(SplashXPath *xPath) { @@ -230,6 +265,10 @@ SplashXPath::SplashXPath(SplashXPath *xPath) { size = xPath->size; segs = (SplashXPathSeg *)gmallocn(size, sizeof(SplashXPathSeg)); memcpy(segs, xPath->segs, length * sizeof(SplashXPathSeg)); + xMin = xPath->xMin; + yMin = xPath->yMin; + xMax = xPath->xMax; + yMax = xPath->yMax; } SplashXPath::~SplashXPath() { @@ -341,115 +380,38 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0, void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1) { grow(1); - segs[length].x0 = x0; - segs[length].y0 = y0; - segs[length].x1 = x1; - segs[length].y1 = y1; - segs[length].flags = 0; - if (y1 == y0) { - segs[length].dxdy = segs[length].dydx = 0; - segs[length].flags |= splashXPathHoriz; - if (x1 == x0) { - segs[length].flags |= splashXPathVert; - } - } else if (x1 == x0) { - segs[length].dxdy = segs[length].dydx = 0; - segs[length].flags |= splashXPathVert; + if (y0 <= y1) { + segs[length].x0 = x0; + segs[length].y0 = y0; + segs[length].x1 = x1; + segs[length].y1 = y1; + segs[length].count = 1; } else { + segs[length].x0 = x1; + segs[length].y0 = y1; + segs[length].x1 = x0; + segs[length].y1 = y0; + segs[length].count = -1; + } #if USE_FIXEDPOINT - if (FixedPoint::divCheck(x1 - x0, y1 - y0, &segs[length].dxdy)) { - segs[length].dydx = (SplashCoord)1 / segs[length].dxdy; - } else { - segs[length].dxdy = segs[length].dydx = 0; - if (splashAbs(x1 - x0) > splashAbs(y1 - y0)) { - segs[length].flags |= splashXPathHoriz; - } else { - segs[length].flags |= splashXPathVert; - } - } + if (y0 == y1 || x0 == x1 || + !FixedPoint::divCheck(x1 - x0, y1 - y0, &segs[length].dxdy) || + !FixedPoint::divCheck(y1 - y0, x1 - x0, &segs[length].dydx)) { + segs[length].dxdy = 0; + segs[length].dydx = 0; + } #else + if (y0 == y1 || x0 == x1) { + segs[length].dxdy = 0; + segs[length].dydx = 0; + } else { segs[length].dxdy = (x1 - x0) / (y1 - y0); - segs[length].dydx = (SplashCoord)1 / segs[length].dxdy; -#endif - } - if (y0 > y1) { - segs[length].flags |= splashXPathFlip; - } - ++length; -} - -void SplashXPath::aaScale() { - SplashXPathSeg *seg; - int i; - - for (i = 0, seg = segs; i < length; ++i, ++seg) { - seg->x0 *= splashAASize; - seg->y0 *= splashAASize; - seg->x1 *= splashAASize; - seg->y1 *= splashAASize; - } -} - -#if HAVE_STD_SORT - -struct cmpXPathSegsFunctor { - bool operator()(const SplashXPathSeg &seg0, const SplashXPathSeg &seg1) { - SplashCoord x0, y0, x1, y1; - - if (seg0.flags & splashXPathFlip) { - x0 = seg0.x1; - y0 = seg0.y1; + if (segs[length].dxdy == 0) { + segs[length].dydx = 0; } else { - x0 = seg0.x0; - y0 = seg0.y0; + segs[length].dydx = 1 / segs[length].dxdy; } - if (seg1.flags & splashXPathFlip) { - x1 = seg1.x1; - y1 = seg1.y1; - } else { - x1 = seg1.x0; - y1 = seg1.y0; - } - return (y0 != y1) ? (y0 < y1) : (x0 < x1); - } -}; - -#else // HAVE_STD_SORT - -static int cmpXPathSegs(const void *arg0, const void *arg1) { - SplashXPathSeg *seg0 = (SplashXPathSeg *)arg0; - SplashXPathSeg *seg1 = (SplashXPathSeg *)arg1; - SplashCoord x0, y0, x1, y1; - - if (seg0->flags & splashXPathFlip) { - x0 = seg0->x1; - y0 = seg0->y1; - } else { - x0 = seg0->x0; - y0 = seg0->y0; } - if (seg1->flags & splashXPathFlip) { - x1 = seg1->x1; - y1 = seg1->y1; - } else { - x1 = seg1->x0; - y1 = seg1->y0; - } - if (y0 != y1) { - return (y0 > y1) ? 1 : -1; - } - if (x0 != x1) { - return (x0 > x1) ? 1 : -1; - } - return 0; -} - -#endif // HAVE_STD_SORT - -void SplashXPath::sort() { -#if HAVE_STD_SORT - std::sort(segs, segs + length, cmpXPathSegsFunctor()); -#else - qsort(segs, length, sizeof(SplashXPathSeg), &cmpXPathSegs); #endif + ++length; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPath.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPath.h index 4e06d829cfd..5bcec61cd25 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/SplashXPath.h +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPath.h @@ -2,6 +2,8 @@ // // SplashXPath.h // +// Copyright 2003-2013 Glyph & Cog, LLC +// //======================================================================== #ifndef SPLASHXPATH_H @@ -16,7 +18,8 @@ #include "SplashTypes.h" class SplashPath; -struct SplashXPathAdjust; +struct SplashXPathPoint; +struct SplashPathHint; //------------------------------------------------------------------------ @@ -27,18 +30,44 @@ struct SplashXPathAdjust; //------------------------------------------------------------------------ struct SplashXPathSeg { - SplashCoord x0, y0; // first endpoint + SplashCoord x0, y0; // first endpoint (y0 <= y1) SplashCoord x1, y1; // second endpoint SplashCoord dxdy; // slope: delta-x / delta-y SplashCoord dydx; // slope: delta-y / delta-x - Guint flags; -}; + int count; // EO/NZWN counter increment + + //----- used by SplashXPathScanner + SplashCoord xCur0, xCur1; // current x values + +#if HAVE_STD_SORT + static bool cmpY(const SplashXPathSeg &seg0, + const SplashXPathSeg &seg1) { + return seg0.y0 < seg1.y0; + } +#else + static int cmpY(const void *seg0, const void *seg1) { + SplashCoord cmp; + + cmp = ((SplashXPathSeg *)seg0)->y0 + - ((SplashXPathSeg *)seg1)->y0; + return (cmp > 0) ? 1 : (cmp < 0) ? -1 : 0; + } +#endif + + static int cmpX(SplashXPathSeg *seg0, SplashXPathSeg *seg1) { + SplashCoord cmp; -#define splashXPathHoriz 0x01 // segment is vertical (y0 == y1) - // (dxdy is undef) -#define splashXPathVert 0x02 // segment is horizontal (x0 == x1) - // (dydx is undef) -#define splashXPathFlip 0x04 // y0 > y1 + if ((cmp = seg0->xCur0 - seg1->xCur0) == 0) { + cmp = seg0->dxdy - seg1->dxdy; + } + return (cmp > 0) ? 1 : (cmp < 0) ? -1 : 0; + } + + static int cmpXi(const void *p0, const void *p1) { + return cmpX(*(SplashXPathSeg **)p0, *(SplashXPathSeg **)p1); + } + +}; //------------------------------------------------------------------------ // SplashXPath @@ -59,20 +88,18 @@ public: ~SplashXPath(); - // Multiply all coordinates by splashAASize, in preparation for - // anti-aliased rendering. - void aaScale(); - - // Sort by upper coordinate (lower y), in y-major order. - void sort(); + int getXMin() { return xMin; } + int getXMax() { return xMax; } + int getYMin() { return yMin; } + int getYMax() { return yMax; } private: SplashXPath(SplashXPath *xPath); void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, SplashCoord *xo, SplashCoord *yo); - void strokeAdjust(SplashXPathAdjust *adjust, - SplashCoord *xp, SplashCoord *yp); + void strokeAdjust(SplashXPathPoint *pts, + SplashPathHint *hints, int nHints); void grow(int nSegs); void addCurve(SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1, @@ -85,6 +112,8 @@ private: SplashXPathSeg *segs; int length, size; // length and size of segs array + int xMin, xMax; + int yMin, yMax; friend class SplashXPathScanner; friend class SplashClip; diff --git a/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.cc b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.cc new file mode 100644 index 00000000000..aee60cce61e --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.cc @@ -0,0 +1,567 @@ +//======================================================================== +// +// SplashXPathScanner.cc +// +// Copyright 2003-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <string.h> +#if HAVE_STD_SORT +#include <algorithm> +#endif +#include "gmem.h" +#include "GList.h" +#include "SplashMath.h" +#include "SplashXPath.h" +#include "SplashXPathScanner.h" + +//------------------------------------------------------------------------ + +#define minVertStep 0.05 + +//------------------------------------------------------------------------ + +SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA, + int yMinA, int yMaxA) { + xPath = xPathA; + eo = eoA; + yMin = yMinA; + yMax = yMaxA; + + activeSegs = new GList(); + nextSeg = 0; + yNext = xPath->yMin; +} + +SplashXPathScanner::~SplashXPathScanner() { + delete activeSegs; +} + +void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1) { + SplashXPathSeg *seg, *seg0; + SplashCoord y0, y1, y1p; + GBool intersect, last; + int eoMask, state0, state1, count, i; + + //--- clear the scan line buffer + memset(line + x0, 0, x1 - x0 + 1); + + //--- reset the path + if (yNext != y) { + delete activeSegs; + activeSegs = new GList(); + nextSeg = 0; + while (nextSeg < xPath->length) { + seg = &xPath->segs[nextSeg]; + if (seg->y0 >= y) { + break; + } + if (seg->y0 != seg->y1 && seg->y1 > y) { + if (seg->y0 == y) { + seg->xCur0 = seg->x0; + } else { + seg->xCur0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy; + } + activeSegs->append(seg); + } + ++nextSeg; + } + activeSegs->sort(&SplashXPathSeg::cmpXi); + } + + //--- process the scan line + y0 = y; + while (y0 < y + 1) { + + //--- delete finished segs + i = 0; + while (i < activeSegs->getLength()) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (seg->y1 <= y0) { + activeSegs->del(i); + } else { + ++i; + } + } + + //--- check for bottom of path + if (!activeSegs->getLength() && nextSeg >= xPath->length) { + break; + } + + //--- sort activeSegs + sortActiveSegs(); + + //--- add waiting segs + while (nextSeg < xPath->length) { + seg = &xPath->segs[nextSeg]; + if (seg->y0 > y0) { + break; + } + if (seg->y0 != seg->y1) { + seg->xCur0 = seg->x0; + insertActiveSeg(seg); + } + ++nextSeg; + } + + //--- get the next "interesting" y value + y1 = y + 1; + if (nextSeg < xPath->length && xPath->segs[nextSeg].y0 < y1) { + y1 = xPath->segs[nextSeg].y0; + } + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (seg->y1 < y1) { + y1 = seg->y1; + } + } + + //--- compute xCur1 values, check for intersections + seg0 = NULL; + intersect = gFalse; + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (seg->y1 == y1) { + seg->xCur1 = seg->x1; + } else { + seg->xCur1 = seg->x0 + (y1 - seg->y0) * seg->dxdy; + } + if (seg0 && seg0->xCur1 > seg->xCur1) { + intersect = gTrue; + } + seg0 = seg; + } + + //--- draw rectangles + if (intersect) { + for (; y0 < y1; y0 += minVertStep) { + if ((y1p = y0 + minVertStep) >= y1) { + y1p = y1; + last = gTrue; + } else { + last = gFalse; + } + state0 = state1 = count = 0; + seg0 = NULL; + eoMask = eo ? 1 : 0xffffffff; + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (last && seg->y1 == y1) { + seg->xCur1 = seg->x1; + } else { + seg->xCur1 = seg->x0 + (y1p - seg->y0) * seg->dxdy; + } + count += seg->count; + state1 = count & eoMask; + if (!state0 && state1) { + seg0 = seg; + } else if (state0 && !state1) { + drawRectangle(line, x0, x1, y0, y1p, seg0->xCur0, seg->xCur0); + } + state0 = state1; + } + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + seg->xCur0 = seg->xCur1; + } + sortActiveSegs(); + } + + //--- draw trapezoids + } else { + state0 = state1 = count = 0; + seg0 = NULL; + eoMask = eo ? 1 : 0xffffffff; + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + count += seg->count; + state1 = count & eoMask; + if (!state0 && state1) { + seg0 = seg; + } else if (state0 && !state1) { + drawTrapezoid(line, x0, x1, y0, y1, + seg0->xCur0, seg0->xCur1, seg0->dydx, + seg->xCur0, seg->xCur1, seg->dydx); + } + state0 = state1; + } + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + seg->xCur0 = seg->xCur1; + } + } + + //--- next slice + y0 = y1; + } + + yNext = y + 1; +} + +void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1) { + SplashXPathSeg *seg; + int xx0, xx1, xx; + int eoMask, state0, state1, count, i; + + //--- clear the scan line buffer + memset(line + x0, 0, x1 - x0 + 1); + + //--- reset the path + if (yNext != y) { + delete activeSegs; + activeSegs = new GList(); + nextSeg = 0; + while (nextSeg < xPath->length) { + seg = &xPath->segs[nextSeg]; + if (seg->y0 >= y) { + break; + } + if (seg->y1 > y) { + if (seg->y0 == y) { + seg->xCur0 = seg->x0; + } else { + seg->xCur0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy; + } + activeSegs->append(seg); + } + ++nextSeg; + } + activeSegs->sort(&SplashXPathSeg::cmpXi); + } + + //--- delete finished segs + i = 0; + while (i < activeSegs->getLength()) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (seg->y1 <= y) { + activeSegs->del(i); + } else { + ++i; + } + } + + //--- sort activeSegs + sortActiveSegs(); + + //--- add waiting segs + while (nextSeg < xPath->length) { + seg = &xPath->segs[nextSeg]; + if (seg->y0 >= y + 1) { + break; + } + seg->xCur0 = seg->x0; + insertActiveSeg(seg); + ++nextSeg; + } + + //--- compute xCur1 values + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (seg->y1 <= y + 1) { + seg->xCur1 = seg->x1; + } else { + seg->xCur1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy; + } + } + + //--- draw spans + state0 = state1 = count = 0; + eoMask = eo ? 1 : 0xffffffff; + xx0 = xx1 = 0; // make gcc happy + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + if (seg->y0 <= y && seg->y0 < seg->y1) { + count += seg->count; + state1 = count & eoMask; + } + if (state0) { + xx = splashCeil(seg->xCur0) - 1; + if (xx > xx1) { + xx1 = xx; + } + xx = splashFloor(seg->xCur1); + if (xx < xx0) { + xx0 = xx; + } + xx = splashCeil(seg->xCur1) - 1; + if (xx > xx1) { + xx1 = xx; + } + } else { + if (seg->xCur0 < seg->xCur1) { + xx0 = splashFloor(seg->xCur0); + xx1 = splashCeil(seg->xCur1) - 1; + } else { + xx0 = splashFloor(seg->xCur1); + xx1 = splashCeil(seg->xCur0) - 1; + } + } + if (!state1) { + if (xx0 < x0) { + xx0 = x0; + } + if (xx1 > x1) { + xx1 = x1; + } + for (xx = xx0; xx <= xx1; ++xx) { + line[xx] = 0xff; + } + } + state0 = state1; + } + + //--- update xCur0 values + for (i = 0; i < activeSegs->getLength(); ++i) { + seg = (SplashXPathSeg *)activeSegs->get(i); + seg->xCur0 = seg->xCur1; + } + + yNext = y + 1; +} + +inline void SplashXPathScanner::addArea(Guchar *line, int x, SplashCoord a) { + int a2, t; + + a2 = splashRound(a * 255); + if (a2 <= 0) { + return; + } + t = line[x] + a2; + if (t > 255) { + t = 255; + } + line[x] = t; +} + +// Draw a trapezoid with edges: +// top: (xa0, y0) - (xb0, y0) +// left: (xa0, y0) - (xa1, y1) +// right: (xb0, y0) - (xb1, y1) +// bottom: (xa1, y1) - (xb1, y1) +void SplashXPathScanner::drawTrapezoid(Guchar *line, int xMin, int xMax, + SplashCoord y0, SplashCoord y1, + SplashCoord xa0, SplashCoord xa1, + SplashCoord dydxa, + SplashCoord xb0, SplashCoord xb1, + SplashCoord dydxb) { + SplashCoord a, dy; + int x0, x1, x2, x3, x; + + // check for a rectangle + if (dydxa == 0 && dydxb == 0 && xa0 >= xMin && xb0 <= xMax) { + x0 = splashFloor(xa0); + x3 = splashFloor(xb0); + dy = y1 - y0; + if (x0 == x3) { + addArea(line, x0, (xb0 - xa0) * dy); + } else { + addArea(line, x0, ((SplashCoord)1 - (xa0 - x0)) * dy); + for (x = x0 + 1; x <= x3 - 1; ++x) { + addArea(line, x, y1 - y0); + } + addArea(line, x3, (xb0 - x3) * (y1 - y0)); + } + return; + } + + if (dydxa > 0) { + x0 = splashFloor(xa0); + x1 = splashFloor(xa1); + } else { + x0 = splashFloor(xa1); + x1 = splashFloor(xa0); + } + if (x0 < xMin) { + x0 = xMin; + } + if (dydxb > 0) { + x2 = splashFloor(xb0); + x3 = splashFloor(xb1); + } else { + x2 = splashFloor(xb1); + x3 = splashFloor(xb0); + } + if (x3 > xMax) { + x3 = xMax; + } + for (x = x0; x <= x3; ++x) { + a = y1 - y0; + if (x <= x1) { + a -= areaLeft(x, xa0, y0, xa1, y1, dydxa); + } + if (x >= x2) { + a -= areaRight(x, xb0, y0, xb1, y1, dydxb); + } + addArea(line, x, a); + } +} + +// Compute area within a pixel slice ((xp,y0)-(xp+1,y1)) to the left +// of a trapezoid edge ((x0,y0)-(x1,y1)). +SplashCoord SplashXPathScanner::areaLeft(int xp, + SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord dydx) { + SplashCoord a, ya, yb; + + if (dydx >= 0) { + if (x0 >= xp) { + if (x1 <= xp + 1) { + a = ((x0 + x1) * 0.5 - xp) * (y1 - y0); + } else { + yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; + a = (y1 - y0) - ((SplashCoord)(xp + 1) - x0) * (yb - y0) * 0.5; + } + } else { + if (x1 <= xp + 1) { + ya = y0 + ((SplashCoord)xp - x0) * dydx; + a = (x1 - xp) * (y1 - ya) * 0.5; + } else { + // ya = y1 - (x1 - xp - 0.5) * dydx; + // a = y1 - ya; + a = (x1 - xp - 0.5) * dydx; + } + } + } else { + if (x0 <= xp + 1) { + if (x1 >= xp) { + a = ((x0 + x1) * 0.5 - xp) * (y1 - y0); + } else { + ya = y0 + ((SplashCoord)xp - x0) * dydx; + a = (x0 - xp) * (ya - y0) * 0.5; + } + } else { + if (x1 >= xp) { + yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; + a = (y1 - y0) - ((SplashCoord)(xp + 1) - x1) * (y1 - yb) * 0.5; + } else { + // ya = y0 + (xp - x0 + 0.5) * dydx; + // a = ya - y0; + a = ((SplashCoord)xp - x0 + 0.5) * dydx; + } + } + } + return a; +} + +// Compute area within a pixel slice ((xp,y0)-(xp+1,y1)) to the left +// of a trapezoid edge ((x0,y0)-(x1,y1)). +SplashCoord SplashXPathScanner::areaRight(int xp, + SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord dydx) { + SplashCoord a, ya, yb; + + if (dydx >= 0) { + if (x0 >= xp) { + if (x1 <= xp + 1) { + a = ((SplashCoord)(xp + 1) - (x0 + x1) * 0.5) * (y1 - y0); + } else { + yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; + a = ((SplashCoord)(xp + 1) - x0) * (yb - y0) * 0.5; + } + } else { + if (x1 <= xp + 1) { + ya = y0 + ((SplashCoord)xp - x0) * dydx; + a = (y1 - y0) - (x1 - xp) * (y1 - ya) * 0.5; + } else { + // ya = y0 + (xp - x0 + 0.5) * dydx; + // a = ya - y0; + a = ((SplashCoord)xp + 0.5 - x0) * dydx; + } + } + } else { + if (x0 <= xp + 1) { + if (x1 >= xp) { + a = ((SplashCoord)(xp + 1) - (x0 + x1) * 0.5) * (y1 - y0); + } else { + ya = y0 + ((SplashCoord)xp - x0) * dydx; + a = (y1 - y0) - (x0 - xp) * (ya - y0) * 0.5; + } + } else { + if (x1 >= xp) { + yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx; + a = ((SplashCoord)(xp + 1) - x1) * (y1 - yb) * 0.5; + } else { + // ya = y1 - (x1 - xp - 0.5) * dydx; + // a = y1 - ya; + a = (x1 - xp - 0.5) * dydx; + } + } + } + return a; +} + +void SplashXPathScanner::drawRectangle(Guchar *line, int xMin, int xMax, + SplashCoord y0, SplashCoord y1, + SplashCoord x0, SplashCoord x1) { + SplashCoord dy, a; + int xx0, xx1, x; + + xx0 = splashFloor(x0); + if (xx0 < xMin) { + xx0 = xMin; + } + xx1 = splashFloor(x1); + if (xx1 > xMax) { + xx1 = xMax; + } + dy = y1 - y0; + for (x = xx0; x <= xx1; ++x) { + a = dy; + if ((SplashCoord)x < x0) { + a -= (x0 - x) * dy; + } + if ((SplashCoord)(x + 1) > x1) { + a -= ((SplashCoord)(x + 1) - x1) * dy; + } + addArea(line, x, a); + } +} + +void SplashXPathScanner::sortActiveSegs() { + SplashXPathSeg *seg0, *seg1; + int i, j, k; + + if (activeSegs->getLength() < 2) { + return; + } + seg0 = (SplashXPathSeg *)activeSegs->get(0); + for (i = 1; i < activeSegs->getLength(); ++i) { + seg1 = (SplashXPathSeg *)activeSegs->get(i); + if (SplashXPathSeg::cmpX(seg0, seg1) > 0) { + for (j = i - 1; j > 0; --j) { + if (SplashXPathSeg::cmpX((SplashXPathSeg *)activeSegs->get(j - 1), + seg1) <= 0) { + break; + } + } + for (k = i; k > j; --k) { + activeSegs->put(k, activeSegs->get(k-1)); + } + activeSegs->put(j, seg1); + } else { + seg0 = seg1; + } + } +} + +void SplashXPathScanner::insertActiveSeg(SplashXPathSeg *seg) { + int i; + + for (i = 0; i < activeSegs->getLength(); ++i) { + if (SplashXPathSeg::cmpX(seg, (SplashXPathSeg *)activeSegs->get(i)) < 0) { + break; + } + } + activeSegs->insert(i, seg); +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.h b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.h new file mode 100644 index 00000000000..519ff4dfcac --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/SplashXPathScanner.h @@ -0,0 +1,75 @@ +//======================================================================== +// +// SplashXPathScanner.h +// +// Copyright 2003-2013 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SPLASHXPATHSCANNER_H +#define SPLASHXPATHSCANNER_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class GList; +class SplashXPath; + +//------------------------------------------------------------------------ +// SplashXPathScanner +//------------------------------------------------------------------------ + +class SplashXPathScanner { +public: + + // Create a new SplashXPathScanner object. <xPathA> must be sorted. + SplashXPathScanner(SplashXPath *xPathA, GBool eoA, + int yMinA, int yMaxA); + + ~SplashXPathScanner(); + + // Compute shape values for a scan line. Fills in line[] with shape + // values for one scan line: ([x0, x1], y). The values are in [0, + // 255]. + void getSpan(Guchar *line, int y, int x0, int x1); + + // Like getSpan(), but uses the values 0 and 255 only. Writes 255 + // for all pixels which include non-zero area inside the path. + void getSpanBinary(Guchar *line, int y, int x0, int x1); + +private: + + inline void addArea(Guchar *line, int x, SplashCoord a); + void drawTrapezoid(Guchar *line, int xMin, int xMax, + SplashCoord y0, SplashCoord y1, + SplashCoord xa0, SplashCoord xa1, SplashCoord dydxa, + SplashCoord xb0, SplashCoord xb1, SplashCoord dydxb); + SplashCoord areaLeft(int xp, + SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord dydx); + SplashCoord areaRight(int xp, + SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord dydx); + void drawRectangle(Guchar *line, int xMin, int xMax, + SplashCoord y0, SplashCoord y1, + SplashCoord x0, SplashCoord x1); + void sortActiveSegs(); + void insertActiveSeg(SplashXPathSeg *seg); + + SplashXPath *xPath; + GBool eo; + int yMin, yMax; + + GList *activeSegs; // [SplashXPathSeg] + int nextSeg; + int yNext; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/splash/vms_make.com b/Build/source/libs/xpdf/xpdf-3.04/splash/vms_make.com index e69de29bb2d..e69de29bb2d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/splash/vms_make.com +++ b/Build/source/libs/xpdf/xpdf-3.04/splash/vms_make.com diff --git a/Build/source/libs/xpdf/xpdf-3.03/vms_make.com b/Build/source/libs/xpdf/xpdf-3.04/vms_make.com index d70caad765b..d70caad765b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/vms_make.com +++ b/Build/source/libs/xpdf/xpdf-3.04/vms_make.com diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Annot.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.cc index 887157fa8f1..86e70375c85 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Annot.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.cc @@ -1,8 +1,8 @@ //======================================================================== // -// Annot.cc +// AcroForm.cc // -// Copyright 2000-2003 Glyph & Cog, LLC +// Copyright 2012 Glyph & Cog, LLC // //======================================================================== @@ -15,106 +15,476 @@ #include <stdlib.h> #include <math.h> #include "gmem.h" +#include "GString.h" #include "GList.h" #include "Error.h" #include "Object.h" -#include "Catalog.h" +#include "PDFDoc.h" +#include "TextString.h" #include "Gfx.h" #include "GfxFont.h" -#include "Lexer.h" -#include "PDFDoc.h" #include "OptionalContent.h" #include "Annot.h" +#include "Lexer.h" +#include "AcroForm.h" //------------------------------------------------------------------------ +#define acroFormFlagReadOnly (1 << 0) // all +#define acroFormFlagRequired (1 << 1) // all +#define acroFormFlagNoExport (1 << 2) // all +#define acroFormFlagMultiline (1 << 12) // text +#define acroFormFlagPassword (1 << 13) // text +#define acroFormFlagNoToggleToOff (1 << 14) // button +#define acroFormFlagRadio (1 << 15) // button +#define acroFormFlagPushbutton (1 << 16) // button +#define acroFormFlagCombo (1 << 17) // choice +#define acroFormFlagEdit (1 << 18) // choice +#define acroFormFlagSort (1 << 19) // choice +#define acroFormFlagFileSelect (1 << 20) // text +#define acroFormFlagMultiSelect (1 << 21) // choice +#define acroFormFlagDoNotSpellCheck (1 << 22) // text, choice +#define acroFormFlagDoNotScroll (1 << 23) // text +#define acroFormFlagComb (1 << 24) // text +#define acroFormFlagRadiosInUnison (1 << 25) // button +#define acroFormFlagRichText (1 << 25) // text +#define acroFormFlagCommitOnSelChange (1 << 26) // choice + +#define acroFormQuadLeft 0 +#define acroFormQuadCenter 1 +#define acroFormQuadRight 2 + #define annotFlagHidden 0x0002 #define annotFlagPrint 0x0004 #define annotFlagNoView 0x0020 -#define fieldFlagReadOnly 0x00000001 -#define fieldFlagRequired 0x00000002 -#define fieldFlagNoExport 0x00000004 -#define fieldFlagMultiline 0x00001000 -#define fieldFlagPassword 0x00002000 -#define fieldFlagNoToggleToOff 0x00004000 -#define fieldFlagRadio 0x00008000 -#define fieldFlagPushbutton 0x00010000 -#define fieldFlagCombo 0x00020000 -#define fieldFlagEdit 0x00040000 -#define fieldFlagSort 0x00080000 -#define fieldFlagFileSelect 0x00100000 -#define fieldFlagMultiSelect 0x00200000 -#define fieldFlagDoNotSpellCheck 0x00400000 -#define fieldFlagDoNotScroll 0x00800000 -#define fieldFlagComb 0x01000000 -#define fieldFlagRichText 0x02000000 -#define fieldFlagRadiosInUnison 0x02000000 -#define fieldFlagCommitOnSelChange 0x04000000 - -#define fieldQuadLeft 0 -#define fieldQuadCenter 1 -#define fieldQuadRight 2 - // distance of Bezier control point from center for circle approximation // = (4 * (sqrt(2) - 1) / 3) * r #define bezierCircle 0.55228475 //------------------------------------------------------------------------ -// AnnotBorderStyle + +// map an annotation ref to a page number +class AcroFormAnnotPage { +public: + AcroFormAnnotPage(int annotNumA, int annotGenA, int pageNumA) + { annotNum = annotNumA; annotGen = annotGenA; pageNum = pageNumA; } + int annotNum; + int annotGen; + int pageNum; +}; + +//------------------------------------------------------------------------ +// AcroForm //------------------------------------------------------------------------ -AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType typeA, double widthA, - double *dashA, int dashLengthA, - double rA, double gA, double bA) { - type = typeA; - width = widthA; - dash = dashA; - dashLength = dashLengthA; - r = rA; - g = gA; - b = bA; +AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { + AcroForm *acroForm; + Object fieldsObj, obj1, obj2; + int i; + + acroForm = new AcroForm(docA, acroFormObjA); + + if (acroFormObjA->dictLookup("NeedAppearances", &obj1)->isBool()) { + acroForm->needAppearances = obj1.getBool(); + } + obj1.free(); + + acroForm->buildAnnotPageList(catalog); + + if (!acroFormObjA->dictLookup("Fields", &obj1)->isArray()) { + if (!obj1.isNull()) { + error(errSyntaxError, -1, "AcroForm Fields entry is wrong type"); + } + obj1.free(); + delete acroForm; + return NULL; + } + for (i = 0; i < obj1.arrayGetLength(); ++i) { + obj1.arrayGetNF(i, &obj2); + acroForm->scanField(&obj2); + obj2.free(); + } + obj1.free(); + + return acroForm; +} + +AcroForm::AcroForm(PDFDoc *docA, Object *acroFormObjA): Form(docA) { + acroFormObjA->copy(&acroFormObj); + needAppearances = gFalse; + annotPages = new GList(); + fields = new GList(); +} + +AcroForm::~AcroForm() { + acroFormObj.free(); + deleteGList(annotPages, AcroFormAnnotPage); + deleteGList(fields, AcroFormField); +} + +void AcroForm::buildAnnotPageList(Catalog *catalog) { + Object annotsObj, annotObj; + int pageNum, i; + + for (pageNum = 1; pageNum <= catalog->getNumPages(); ++pageNum) { + if (catalog->getPage(pageNum)->getAnnots(&annotsObj)->isArray()) { + for (i = 0; i < annotsObj.arrayGetLength(); ++i) { + if (annotsObj.arrayGetNF(i, &annotObj)->isRef()) { + annotPages->append(new AcroFormAnnotPage(annotObj.getRefNum(), + annotObj.getRefGen(), + pageNum)); + } + annotObj.free(); + } + } + annotsObj.free(); + } + //~ sort the list +} + +int AcroForm::lookupAnnotPage(Object *annotRef) { + AcroFormAnnotPage *annotPage; + int num, gen, i; + + if (!annotRef->isRef()) { + return 0; + } + num = annotRef->getRefNum(); + gen = annotRef->getRefGen(); + //~ use bin search + for (i = 0; i < annotPages->getLength(); ++i) { + annotPage = (AcroFormAnnotPage *)annotPages->get(i); + if (annotPage->annotNum == num && annotPage->annotGen == gen) { + return annotPage->pageNum; + } + } + return 0; +} + +void AcroForm::scanField(Object *fieldRef) { + AcroFormField *field; + Object fieldObj, kidsObj, kidRef, kidObj, subtypeObj; + GBool isTerminal; + int i; + + fieldRef->fetch(doc->getXRef(), &fieldObj); + if (!fieldObj.isDict()) { + error(errSyntaxError, -1, "AcroForm field object is wrong type"); + fieldObj.free(); + return; + } + + // if this field has a Kids array, and all of the kids have a Parent + // reference (i.e., they're all form fields, not widget + // annotations), then this is a non-terminal field, and we need to + // scan the kids + isTerminal = gTrue; + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + isTerminal = gFalse; + for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGet(i, &kidObj); + if (kidObj.isDict()) { + if (kidObj.dictLookup("Parent", &subtypeObj)->isNull()) { + isTerminal = gTrue; + } + subtypeObj.free(); + } + kidObj.free(); + } + if (!isTerminal) { + for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGetNF(i, &kidRef); + scanField(&kidRef); + kidRef.free(); + } + } + } + kidsObj.free(); + + if (isTerminal) { + if ((field = AcroFormField::load(this, fieldRef))) { + fields->append(field); + } + } + + fieldObj.free(); } -AnnotBorderStyle::~AnnotBorderStyle() { - if (dash) { - gfree(dash); +void AcroForm::draw(int pageNum, Gfx *gfx, GBool printing) { + int i; + + for (i = 0; i < fields->getLength(); ++i) { + ((AcroFormField *)fields->get(i))->draw(pageNum, gfx, printing); } } +int AcroForm::getNumFields() { + return fields->getLength(); +} + +FormField *AcroForm::getField(int idx) { + return (AcroFormField *)fields->get(idx); +} + //------------------------------------------------------------------------ -// Annot +// AcroFormField //------------------------------------------------------------------------ -Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { - Object apObj, asObj, obj1, obj2, obj3; - AnnotBorderType borderType; - double borderWidth; - double *borderDash; - int borderDashLength; - double borderR, borderG, borderB; - double t; +AcroFormField *AcroFormField::load(AcroForm *acroFormA, Object *fieldRefA) { + GString *typeStr; + TextString *nameA; + Guint flagsA; + GBool haveFlags; + Object fieldObjA, parentObj, parentObj2, obj1, obj2; + AcroFormFieldType typeA; + AcroFormField *field; + + fieldRefA->fetch(acroFormA->doc->getXRef(), &fieldObjA); + + //----- get field info + + if (fieldObjA.dictLookup("T", &obj1)->isString()) { + nameA = new TextString(obj1.getString()); + } else { + nameA = new TextString(); + } + obj1.free(); + + if (fieldObjA.dictLookup("FT", &obj1)->isName()) { + typeStr = new GString(obj1.getName()); + } else { + typeStr = NULL; + } + obj1.free(); + + if (fieldObjA.dictLookup("Ff", &obj1)->isInt()) { + flagsA = (Guint)obj1.getInt(); + haveFlags = gTrue; + } else { + flagsA = 0; + haveFlags = gFalse; + } + obj1.free(); + + //----- get info from parent non-terminal fields + + fieldObjA.dictLookup("Parent", &parentObj); + while (parentObj.isDict()) { + + if (parentObj.dictLookup("T", &obj1)->isString()) { + if (nameA->getLength()) { + nameA->insert(0, (Unicode)'.'); + } + nameA->insert(0, obj1.getString()); + } + obj1.free(); + + if (!typeStr) { + if (parentObj.dictLookup("FT", &obj1)->isName()) { + typeStr = new GString(obj1.getName()); + } + obj1.free(); + } + + if (!haveFlags) { + if (parentObj.dictLookup("Ff", &obj1)->isInt()) { + flagsA = (Guint)obj1.getInt(); + haveFlags = gTrue; + } + obj1.free(); + } + + parentObj.dictLookup("Parent", &parentObj2); + parentObj.free(); + parentObj = parentObj2; + } + parentObj.free(); + + if (!typeStr) { + error(errSyntaxError, -1, "Missing type in AcroForm field"); + goto err1; + } else if (!typeStr->cmp("Btn")) { + if (flagsA & acroFormFlagPushbutton) { + typeA = acroFormFieldPushbutton; + } else if (flagsA & acroFormFlagRadio) { + typeA = acroFormFieldRadioButton; + } else { + typeA = acroFormFieldCheckbox; + } + } else if (!typeStr->cmp("Tx")) { + if (flagsA & acroFormFlagFileSelect) { + typeA = acroFormFieldFileSelect; + } else if (flagsA & acroFormFlagMultiline) { + typeA = acroFormFieldMultilineText; + } else { + typeA = acroFormFieldText; + } + } else if (!typeStr->cmp("Ch")) { + if (flagsA & acroFormFlagCombo) { + typeA = acroFormFieldComboBox; + } else { + typeA = acroFormFieldListBox; + } + } else if (!typeStr->cmp("Sig")) { + typeA = acroFormFieldSignature; + } else { + error(errSyntaxError, -1, "Invalid type in AcroForm field"); + goto err1; + } + delete typeStr; + + field = new AcroFormField(acroFormA, fieldRefA, &fieldObjA, + typeA, nameA, flagsA); + fieldObjA.free(); + return field; + + err1: + delete typeStr; + delete nameA; + fieldObjA.free(); + return NULL; +} + +AcroFormField::AcroFormField(AcroForm *acroFormA, + Object *fieldRefA, Object *fieldObjA, + AcroFormFieldType typeA, TextString *nameA, + Guint flagsA) { + acroForm = acroFormA; + fieldRefA->copy(&fieldRef); + fieldObjA->copy(&fieldObj); + type = typeA; + name = nameA; + flags = flagsA; +} + +AcroFormField::~AcroFormField() { + fieldRef.free(); + fieldObj.free(); + delete name; +} + +const char *AcroFormField::getType() { + switch (type) { + case acroFormFieldPushbutton: return "PushButton"; + case acroFormFieldRadioButton: return "RadioButton"; + case acroFormFieldCheckbox: return "Checkbox"; + case acroFormFieldFileSelect: return "FileSelect"; + case acroFormFieldMultilineText: return "MultilineText"; + case acroFormFieldText: return "Text"; + case acroFormFieldComboBox: return "ComboBox"; + case acroFormFieldListBox: return "ListBox"; + case acroFormFieldSignature: return "Signature"; + default: return NULL; + } +} + +Unicode *AcroFormField::getName(int *length) { + Unicode *u, *ret; + int n; + + u = name->getUnicode(); + n = name->getLength(); + ret = (Unicode *)gmallocn(n, sizeof(Unicode)); + memcpy(ret, u, n * sizeof(Unicode)); + *length = n; + return ret; +} + +Unicode *AcroFormField::getValue(int *length) { + Object obj1; + Unicode *u; + char *s; + TextString *ts; + int n, i; + + fieldLookup("V", &obj1); + if (obj1.isName()) { + s = obj1.getName(); + n = (int)strlen(s); + u = (Unicode *)gmallocn(n, sizeof(Unicode)); + for (i = 0; i < n; ++i) { + u[i] = s[i] & 0xff; + } + *length = n; + return u; + } else if (obj1.isString()) { + ts = new TextString(obj1.getString()); + n = ts->getLength(); + u = (Unicode *)gmallocn(n, sizeof(Unicode)); + memcpy(u, ts->getUnicode(), n * sizeof(Unicode)); + *length = n; + delete ts; + return u; + } else { + return NULL; + } +} + +void AcroFormField::draw(int pageNum, Gfx *gfx, GBool printing) { + Object kidsObj, annotRef, annotObj; int i; - ok = gTrue; - doc = docA; - xref = doc->getXRef(); - ref = *refA; - type = NULL; - appearanceState = NULL; - appearBuf = NULL; - borderStyle = NULL; + // find the annotation object(s) + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + for (i = 0; i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGetNF(i, &annotRef); + annotRef.fetch(acroForm->doc->getXRef(), &annotObj); + drawAnnot(pageNum, gfx, printing, &annotRef, &annotObj); + annotObj.free(); + annotRef.free(); + } + } else { + drawAnnot(pageNum, gfx, printing, &fieldRef, &fieldObj); + } + kidsObj.free(); +} - //----- parse the type +void AcroFormField::drawAnnot(int pageNum, Gfx *gfx, GBool printing, + Object *annotRef, Object *annotObj) { + Object obj1, obj2; + double xMin, yMin, xMax, yMax, t; + int annotFlags; + GBool oc; - if (dict->lookup("Subtype", &obj1)->isName()) { - type = new GString(obj1.getName()); + if (!annotObj->isDict()) { + return; + } + + //----- get the page number + + // the "P" (page) field in annotations is optional, so we can't + // depend on it here + if (acroForm->lookupAnnotPage(annotRef) != pageNum) { + return; + } + + //----- check annotation flags + + if (annotObj->dictLookup("F", &obj1)->isInt()) { + annotFlags = obj1.getInt(); + } else { + annotFlags = 0; + } + obj1.free(); + if ((annotFlags & annotFlagHidden) || + (printing && !(annotFlags & annotFlagPrint)) || + (!printing && (annotFlags & annotFlagNoView))) { + return; + } + + //----- check the optional content entry + + annotObj->dictLookupNF("OC", &obj1); + if (acroForm->doc->getOptionalContent()->evalOCObject(&obj1, &oc) && !oc) { + obj1.free(); + return; } obj1.free(); - //----- parse the rectangle + //----- get the bounding box - if (dict->lookup("Rect", &obj1)->isArray() && + if (annotObj->dictLookup("Rect", &obj1)->isArray() && obj1.arrayGetLength() == 4) { xMin = yMin = xMax = yMax = 0; if (obj1.arrayGet(0, &obj2)->isNum()) { @@ -141,29 +511,106 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { } } else { error(errSyntaxError, -1, "Bad bounding box for annotation"); - ok = gFalse; + obj1.free(); + return; } obj1.free(); - //----- parse the flags + //----- draw it - if (dict->lookup("F", &obj1)->isInt()) { - flags = obj1.getInt(); + if (acroForm->needAppearances) { + drawNewAppearance(gfx, annotObj->getDict(), + xMin, yMin, xMax, yMax); } else { - flags = 0; + drawExistingAppearance(gfx, annotObj->getDict(), + xMin, yMin, xMax, yMax); } - obj1.free(); +} + +// Draw the existing appearance stream for a single annotation +// attached to this field. +void AcroFormField::drawExistingAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax) { + Object apObj, asObj, appearance, obj1; + + //----- get the appearance stream + + if (annot->lookup("AP", &apObj)->isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict()) { + if (annot->lookup("AS", &asObj)->isName()) { + obj1.dictLookupNF(asObj.getName(), &appearance); + } else if (obj1.dictGetLength() == 1) { + obj1.dictGetValNF(0, &appearance); + } else { + obj1.dictLookupNF("Off", &appearance); + } + asObj.free(); + } else { + apObj.dictLookupNF("N", &appearance); + } + obj1.free(); + } + apObj.free(); - //----- parse the border style + //----- draw it + if (!appearance.isNone()) { + gfx->drawAnnot(&appearance, NULL, xMin, yMin, xMax, yMax); + appearance.free(); + } +} + +// Regenerate the appearnce for this field, and draw it. +void AcroFormField::drawNewAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax) { + Object appearance, mkObj, ftObj, appearDict, drObj, apObj, asObj; + Object obj1, obj2, obj3; + Dict *mkDict; + MemStream *appearStream; + GfxFontDict *fontDict; + GBool hasCaption; + double dx, dy, r; + GString *caption, *da; + GString **text; + GBool *selection; + AnnotBorderType borderType; + double borderWidth; + double *borderDash; + GString *appearanceState; + int borderDashLength, rot, quadding, comb, nOptions, topIdx, i, j; + + appearBuf = new GString(); + + // get the appearance characteristics (MK) dictionary + if (annot->lookup("MK", &mkObj)->isDict()) { + mkDict = mkObj.getDict(); + } else { + mkDict = NULL; + } + + // draw the background + if (mkDict) { + if (mkDict->lookup("BG", &obj1)->isArray() && + obj1.arrayGetLength() > 0) { + setColor(obj1.getArray(), gTrue, 0); + appearBuf->appendf("0 0 {0:.4f} {1:.4f} re f\n", + xMax - xMin, yMax - yMin); + } + obj1.free(); + } + + // get the field type + fieldLookup("FT", &ftObj); + + // draw the border borderType = annotBorderSolid; borderWidth = 1; borderDash = NULL; borderDashLength = 0; - borderR = 0; - borderG = 0; - borderB = 1; - if (dict->lookup("BS", &obj1)->isDict()) { + if (annot->lookup("BS", &obj1)->isDict()) { if (obj1.dictLookup("S", &obj2)->isName()) { if (obj2.isName("S")) { borderType = annotBorderSolid; @@ -197,7 +644,7 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { obj2.free(); } else { obj1.free(); - if (dict->lookup("Border", &obj1)->isArray()) { + if (annot->lookup("Border", &obj1)->isArray()) { if (obj1.arrayGetLength() >= 3) { if (obj1.arrayGet(2, &obj2)->isNum()) { borderWidth = obj2.getNum(); @@ -227,136 +674,8 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { } } obj1.free(); - if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) { - if (obj1.arrayGet(0, &obj2)->isNum()) { - borderR = obj2.getNum(); - } - obj1.free(); - if (obj1.arrayGet(1, &obj2)->isNum()) { - borderG = obj2.getNum(); - } - obj1.free(); - if (obj1.arrayGet(2, &obj2)->isNum()) { - borderB = obj2.getNum(); - } - obj1.free(); - } - obj1.free(); - borderStyle = new AnnotBorderStyle(borderType, borderWidth, - borderDash, borderDashLength, - borderR, borderG, borderB); - - //----- get the appearance state - - dict->lookup("AP", &apObj); - dict->lookup("AS", &asObj); - if (asObj.isName()) { - appearanceState = new GString(asObj.getName()); - } else if (apObj.isDict()) { - apObj.dictLookup("N", &obj1); - if (obj1.isDict() && obj1.dictGetLength() == 1) { - appearanceState = new GString(obj1.dictGetKey(0)); - } - obj1.free(); - } - if (!appearanceState) { - appearanceState = new GString("Off"); - } - asObj.free(); - - //----- get the annotation appearance - - if (apObj.isDict()) { - apObj.dictLookup("N", &obj1); - apObj.dictLookupNF("N", &obj2); - if (obj1.isDict()) { - if (obj1.dictLookupNF(appearanceState->getCString(), &obj3)->isRef()) { - obj3.copy(&appearance); - } - obj3.free(); - } else if (obj2.isRef()) { - obj2.copy(&appearance); - } - obj1.free(); - obj2.free(); - } - apObj.free(); - - //----- get the optional content entry - - dict->lookupNF("OC", &ocObj); -} - -Annot::~Annot() { - if (type) { - delete type; - } - if (appearanceState) { - delete appearanceState; - } - appearance.free(); - if (appearBuf) { - delete appearBuf; - } - if (borderStyle) { - delete borderStyle; - } - ocObj.free(); -} - -void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { - Object mkObj, ftObj, appearDict, drObj, obj1, obj2, obj3; - Dict *mkDict; - MemStream *appearStream; - GfxFontDict *fontDict; - GBool hasCaption; - double w, dx, dy, r; - double *dash; - GString *caption, *da; - GString **text; - GBool *selection; - int rot, dashLength, ff, quadding, comb, nOptions, topIdx, i, j; - - // must be a Widget annotation - if (type && type->cmp("Widget")) { - return; - } - - appearBuf = new GString(); - - // get the appearance characteristics (MK) dictionary - if (annot->lookup("MK", &mkObj)->isDict()) { - mkDict = mkObj.getDict(); - } else { - mkDict = NULL; - } - - // draw the background if (mkDict) { - if (mkDict->lookup("BG", &obj1)->isArray() && - obj1.arrayGetLength() > 0) { - setColor(obj1.getArray(), gTrue, 0); - appearBuf->appendf("0 0 {0:.2f} {1:.2f} re f\n", - xMax - xMin, yMax - yMin); - } - obj1.free(); - } - - // get the field type - fieldLookup(field, acroForm, "FT", &ftObj); - - // get the field flags (Ff) value - if (fieldLookup(field, acroForm, "Ff", &obj1)->isInt()) { - ff = obj1.getInt(); - } else { - ff = 0; - } - obj1.free(); - - // draw the border - if (mkDict) { - w = borderStyle->getWidth(); - if (w > 0) { + if (borderWidth > 0) { mkDict->lookup("BC", &obj1); if (!(obj1.isArray() && obj1.arrayGetLength() > 0)) { mkDict->lookup("BG", &obj1); @@ -368,107 +687,108 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { // radio buttons with no caption have a round border hasCaption = mkDict->lookup("CA", &obj2)->isString(); obj2.free(); - if (ftObj.isName("Btn") && (ff & fieldFlagRadio) && !hasCaption) { + if (ftObj.isName("Btn") && (flags & acroFormFlagRadio) && !hasCaption) { r = 0.5 * (dx < dy ? dx : dy); - switch (borderStyle->getType()) { + switch (borderType) { case annotBorderDashed: appearBuf->append("["); - borderStyle->getDash(&dash, &dashLength); - for (i = 0; i < dashLength; ++i) { - appearBuf->appendf(" {0:.2f}", dash[i]); + for (i = 0; i < borderDashLength; ++i) { + appearBuf->appendf(" {0:.4f}", borderDash[i]); } appearBuf->append("] 0 d\n"); // fall through to the solid case case annotBorderSolid: case annotBorderUnderlined: - appearBuf->appendf("{0:.2f} w\n", w); + appearBuf->appendf("{0:.4f} w\n", borderWidth); setColor(obj1.getArray(), gFalse, 0); - drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * w, gFalse); + drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * borderWidth, "s"); break; case annotBorderBeveled: case annotBorderInset: - appearBuf->appendf("{0:.2f} w\n", 0.5 * w); + appearBuf->appendf("{0:.4f} w\n", 0.5 * borderWidth); setColor(obj1.getArray(), gFalse, 0); - drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * w, gFalse); + drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * borderWidth, "s"); setColor(obj1.getArray(), gFalse, - borderStyle->getType() == annotBorderBeveled ? 1 : -1); - drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * w); + borderType == annotBorderBeveled ? 1 : -1); + drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * borderWidth); setColor(obj1.getArray(), gFalse, - borderStyle->getType() == annotBorderBeveled ? -1 : 1); - drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * w); + borderType == annotBorderBeveled ? -1 : 1); + drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * borderWidth); break; } } else { - switch (borderStyle->getType()) { + switch (borderType) { case annotBorderDashed: appearBuf->append("["); - borderStyle->getDash(&dash, &dashLength); - for (i = 0; i < dashLength; ++i) { - appearBuf->appendf(" {0:.2f}", dash[i]); + for (i = 0; i < borderDashLength; ++i) { + appearBuf->appendf(" {0:.4f}", borderDash[i]); } appearBuf->append("] 0 d\n"); // fall through to the solid case case annotBorderSolid: - appearBuf->appendf("{0:.2f} w\n", w); + appearBuf->appendf("{0:.4f} w\n", borderWidth); setColor(obj1.getArray(), gFalse, 0); - appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n", - 0.5 * w, dx - w, dy - w); + appearBuf->appendf("{0:.4f} {0:.4f} {1:.4f} {2:.4f} re s\n", + 0.5 * borderWidth, + dx - borderWidth, dy - borderWidth); break; case annotBorderBeveled: case annotBorderInset: setColor(obj1.getArray(), gTrue, - borderStyle->getType() == annotBorderBeveled ? 1 : -1); + borderType == annotBorderBeveled ? 1 : -1); appearBuf->append("0 0 m\n"); - appearBuf->appendf("0 {0:.2f} l\n", dy); - appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy); - appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w); - appearBuf->appendf("{0:.2f} {1:.2f} l\n", w, dy - w); - appearBuf->appendf("{0:.2f} {0:.2f} l\n", w); + appearBuf->appendf("0 {0:.4f} l\n", dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", dx, dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + dx - borderWidth, dy - borderWidth); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + borderWidth, dy - borderWidth); + appearBuf->appendf("{0:.4f} {0:.4f} l\n", borderWidth); appearBuf->append("f\n"); setColor(obj1.getArray(), gTrue, - borderStyle->getType() == annotBorderBeveled ? -1 : 1); + borderType == annotBorderBeveled ? -1 : 1); appearBuf->append("0 0 m\n"); - appearBuf->appendf("{0:.2f} 0 l\n", dx); - appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy); - appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w); - appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, w); - appearBuf->appendf("{0:.2f} {0:.2f} l\n", w); + appearBuf->appendf("{0:.4f} 0 l\n", dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", dx, dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + dx - borderWidth, dy - borderWidth); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + dx - borderWidth, borderWidth); + appearBuf->appendf("{0:.4f} {0:.4f} l\n", borderWidth); appearBuf->append("f\n"); break; case annotBorderUnderlined: - appearBuf->appendf("{0:.2f} w\n", w); + appearBuf->appendf("{0:.4f} w\n", borderWidth); setColor(obj1.getArray(), gFalse, 0); - appearBuf->appendf("0 0 m {0:.2f} 0 l s\n", dx); + appearBuf->appendf("0 0 m {0:.4f} 0 l s\n", dx); break; } // clip to the inside of the border - appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n", - w, dx - 2 * w, dy - 2 * w); + appearBuf->appendf("{0:.4f} {0:.4f} {1:.4f} {2:.4f} re W n\n", + borderWidth, + dx - 2 * borderWidth, dy - 2 * borderWidth); } } obj1.free(); } } + gfree(borderDash); // get the resource dictionary - fieldLookup(field, acroForm, "DR", &drObj); + fieldLookup("DR", &drObj); // build the font dictionary if (drObj.isDict() && drObj.dictLookup("Font", &obj1)->isDict()) { - fontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict()); + fontDict = new GfxFontDict(acroForm->doc->getXRef(), NULL, obj1.getDict()); } else { fontDict = NULL; } obj1.free(); // get the default appearance string - if (fieldLookup(field, acroForm, "DA", &obj1)->isNull()) { - obj1.free(); - acroForm->lookup("DA", &obj1); - } - if (obj1.isString()) { + if (fieldLookup("DA", &obj1)->isString()) { da = obj1.getString()->copy(); } else { da = NULL; @@ -484,6 +804,25 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { obj1.free(); } + // get the appearance state + annot->lookup("AP", &apObj); + annot->lookup("AS", &asObj); + appearanceState = NULL; + if (asObj.isName()) { + appearanceState = new GString(asObj.getName()); + } else if (apObj.isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict() && obj1.dictGetLength() == 1) { + appearanceState = new GString(obj1.dictGetKey(0)); + } + obj1.free(); + } + if (!appearanceState) { + appearanceState = new GString("Off"); + } + asObj.free(); + apObj.free(); + // draw the field contents if (ftObj.isName("Btn")) { caption = NULL; @@ -494,13 +833,13 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { obj1.free(); } // radio button - if (ff & fieldFlagRadio) { + if (flags & acroFormFlagRadio) { //~ Acrobat doesn't draw a caption if there is no AP dict (?) - if (fieldLookup(field, acroForm, "V", &obj1) + if (fieldLookup("V", &obj1) ->isName(appearanceState->getCString())) { if (caption) { - drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, - gFalse, gTrue, rot); + drawText(caption, da, fontDict, gFalse, 0, acroFormQuadCenter, + gFalse, gTrue, rot, xMin, yMin, xMax, yMax, borderWidth); } else { if (mkDict) { if (mkDict->lookup("BC", &obj2)->isArray() && @@ -508,8 +847,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { dx = xMax - xMin; dy = yMax - yMin; setColor(obj2.getArray(), gTrue, 0); - drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy), - gTrue); + drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy), "f"); } obj2.free(); } @@ -517,20 +855,20 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { } obj1.free(); // pushbutton - } else if (ff & fieldFlagPushbutton) { + } else if (flags & acroFormFlagPushbutton) { if (caption) { - drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, - gFalse, gFalse, rot); + drawText(caption, da, fontDict, gFalse, 0, acroFormQuadCenter, + gFalse, gFalse, rot, xMin, yMin, xMax, yMax, borderWidth); } // checkbox } else { - fieldLookup(field, acroForm, "V", &obj1); + fieldLookup("V", &obj1); if (obj1.isName() && !obj1.isName("Off")) { if (!caption) { caption = new GString("3"); // ZapfDingbats checkmark } - drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, - gFalse, gTrue, rot); + drawText(caption, da, fontDict, gFalse, 0, acroFormQuadCenter, + gFalse, gTrue, rot, xMin, yMin, xMax, yMax, borderWidth); } obj1.free(); } @@ -539,47 +877,49 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { } } else if (ftObj.isName("Tx")) { //~ value strings can be Unicode - if (!fieldLookup(field, acroForm, "V", &obj1)->isString()) { + if (!fieldLookup("V", &obj1)->isString()) { obj1.free(); - fieldLookup(field, acroForm, "DV", &obj1); + fieldLookup("DV", &obj1); } if (obj1.isString()) { - if (fieldLookup(field, acroForm, "Q", &obj2)->isInt()) { + if (fieldLookup("Q", &obj2)->isInt()) { quadding = obj2.getInt(); } else { - quadding = fieldQuadLeft; + quadding = acroFormQuadLeft; } obj2.free(); comb = 0; - if (ff & fieldFlagComb) { - if (fieldLookup(field, acroForm, "MaxLen", &obj2)->isInt()) { + if (flags & acroFormFlagComb) { + if (fieldLookup("MaxLen", &obj2)->isInt()) { comb = obj2.getInt(); } obj2.free(); } drawText(obj1.getString(), da, fontDict, - ff & fieldFlagMultiline, comb, quadding, gTrue, gFalse, rot); + flags & acroFormFlagMultiline, comb, quadding, + gTrue, gFalse, rot, xMin, yMin, xMax, yMax, borderWidth); } obj1.free(); } else if (ftObj.isName("Ch")) { //~ value/option strings can be Unicode - if (fieldLookup(field, acroForm, "Q", &obj1)->isInt()) { + if (fieldLookup("Q", &obj1)->isInt()) { quadding = obj1.getInt(); } else { - quadding = fieldQuadLeft; + quadding = acroFormQuadLeft; } obj1.free(); // combo box - if (ff & fieldFlagCombo) { - if (fieldLookup(field, acroForm, "V", &obj1)->isString()) { + if (flags & acroFormFlagCombo) { + if (fieldLookup("V", &obj1)->isString()) { drawText(obj1.getString(), da, fontDict, - gFalse, 0, quadding, gTrue, gFalse, rot); + gFalse, 0, quadding, gTrue, gFalse, rot, + xMin, yMin, xMax, yMax, borderWidth); //~ Acrobat draws a popup icon on the right side } obj1.free(); // list box } else { - if (field->lookup("Opt", &obj1)->isArray()) { + if (fieldObj.dictLookup("Opt", &obj1)->isArray()) { nOptions = obj1.arrayGetLength(); // get the option text text = (GString **)gmallocn(nOptions, sizeof(GString *)); @@ -602,7 +942,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { // get the selected option(s) selection = (GBool *)gmallocn(nOptions, sizeof(GBool)); //~ need to use the I field in addition to the V field - fieldLookup(field, acroForm, "V", &obj2); + fieldLookup("V", &obj2); for (i = 0; i < nOptions; ++i) { selection[i] = gFalse; if (obj2.isString()) { @@ -621,14 +961,15 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { } obj2.free(); // get the top index - if (field->lookup("TI", &obj2)->isInt()) { + if (fieldObj.dictLookup("TI", &obj2)->isInt()) { topIdx = obj2.getInt(); } else { topIdx = 0; } obj2.free(); // draw the text - drawListBox(text, selection, nOptions, topIdx, da, fontDict, quadding); + drawListBox(text, selection, nOptions, topIdx, da, fontDict, quadding, + xMin, yMin, xMax, yMax, borderWidth); for (i = 0; i < nOptions; ++i) { delete text[i]; } @@ -643,16 +984,17 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { error(errSyntaxError, -1, "Unknown field type"); } + delete appearanceState; if (da) { delete da; } // build the appearance stream dictionary - appearDict.initDict(doc->getXRef()); + appearDict.initDict(acroForm->doc->getXRef()); appearDict.dictAdd(copyString("Length"), obj1.initInt(appearBuf->getLength())); appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); - obj1.initArray(doc->getXRef()); + obj1.initArray(acroForm->doc->getXRef()); obj1.arrayAdd(obj2.initReal(0)); obj1.arrayAdd(obj2.initReal(0)); obj1.arrayAdd(obj2.initReal(xMax - xMin)); @@ -668,9 +1010,14 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { // build the appearance stream appearStream = new MemStream(appearBuf->getCString(), 0, appearBuf->getLength(), &appearDict); - appearance.free(); appearance.initStream(appearStream); + // draw it + gfx->drawAnnot(&appearance, NULL, xMin, yMin, xMax, yMax); + + appearance.free(); + delete appearBuf; + appearBuf = NULL; if (fontDict) { delete fontDict; } @@ -682,7 +1029,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { // have 1, 3, or 4 elements). If <adjust> is +1, color is brightened; // if <adjust> is -1, color is darkened; otherwise color is not // modified. -void Annot::setColor(Array *a, GBool fill, int adjust) { +void AcroFormField::setColor(Array *a, GBool fill, int adjust) { Object obj1; double color[4]; int nComps, i; @@ -727,15 +1074,17 @@ void Annot::setColor(Array *a, GBool fill, int adjust) { } // Draw the variable text or caption for a field. -void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, - GBool multiline, int comb, int quadding, - GBool txField, GBool forceZapfDingbats, int rot) { +void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict, + GBool multiline, int comb, int quadding, + GBool txField, GBool forceZapfDingbats, int rot, + double xMin, double yMin, double xMax, double yMax, + double border) { GString *text2; GList *daToks; GString *tok; GfxFont *font; double dx, dy; - double fontSize, fontSize2, border, x, xPrev, y, w, w2, wMax; + double fontSize, fontSize2, x, xPrev, y, w, w2, wMax; int tfPos, tmPos, i, j, k, c; //~ if there is no MK entry, this should use the existing content stream, @@ -818,25 +1167,22 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string"); } - // get the border width - border = borderStyle->getWidth(); - // setup if (txField) { appearBuf->append("/Tx BMC\n"); } appearBuf->append("q\n"); if (rot == 90) { - appearBuf->appendf("0 1 -1 0 {0:.2f} 0 cm\n", xMax - xMin); + appearBuf->appendf("0 1 -1 0 {0:.4f} 0 cm\n", xMax - xMin); dx = yMax - yMin; dy = xMax - xMin; } else if (rot == 180) { - appearBuf->appendf("-1 0 0 -1 {0:.2f} {1:.2f} cm\n", + appearBuf->appendf("-1 0 0 -1 {0:.4f} {1:.4f} cm\n", xMax - xMin, yMax - yMin); dx = xMax - yMax; dy = yMax - yMin; } else if (rot == 270) { - appearBuf->appendf("0 -1 1 0 0 {0:.2f} cm\n", yMax - yMin); + appearBuf->appendf("0 -1 1 0 0 {0:.4f} cm\n", yMax - yMin); dx = yMax - yMin; dy = xMax - xMin; } else { // assume rot == 0 @@ -889,7 +1235,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, tok->append('0'); tok = (GString *)daToks->get(tmPos + 5); tok->clear(); - tok->appendf("{0:.2f}", y); + tok->appendf("{0:.4f}", y); } // write the DA string @@ -901,7 +1247,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, // write the font matrix (if not part of the DA string) if (tmPos < 0) { - appearBuf->appendf("1 0 0 1 0 {0:.2f} Tm\n", y); + appearBuf->appendf("1 0 0 1 0 {0:.4f} Tm\n", y); } // write a series of lines of text @@ -913,20 +1259,20 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, // compute text start position switch (quadding) { - case fieldQuadLeft: + case acroFormQuadLeft: default: x = border + 2; break; - case fieldQuadCenter: + case acroFormQuadCenter: x = (dx - w) / 2; break; - case fieldQuadRight: + case acroFormQuadRight: x = dx - border - 2 - w; break; } // draw the line - appearBuf->appendf("{0:.2f} {1:.2f} Td\n", x - xPrev, -fontSize); + appearBuf->appendf("{0:.4f} {1:.4f} Td\n", x - xPrev, -fontSize); appearBuf->append('('); for (; i < j; ++i) { c = text2->getChar(i) & 0xff; @@ -966,20 +1312,20 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, if (tfPos >= 0) { tok = (GString *)daToks->get(tfPos + 1); tok->clear(); - tok->appendf("{0:.2f}", fontSize); + tok->appendf("{0:.4f}", fontSize); } } // compute text start position switch (quadding) { - case fieldQuadLeft: + case acroFormQuadLeft: default: x = border + 2; break; - case fieldQuadCenter: + case acroFormQuadCenter: x = border + 2 + 0.5 * (comb - text2->getLength()) * w; break; - case fieldQuadRight: + case acroFormQuadRight: x = border + 2 + (comb - text2->getLength()) * w; break; } @@ -989,10 +1335,10 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, if (tmPos >= 0) { tok = (GString *)daToks->get(tmPos + 4); tok->clear(); - tok->appendf("{0:.2f}", x); + tok->appendf("{0:.4f}", x); tok = (GString *)daToks->get(tmPos + 5); tok->clear(); - tok->appendf("{0:.2f}", y); + tok->appendf("{0:.4f}", y); } // write the DA string @@ -1004,7 +1350,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, // write the font matrix (if not part of the DA string) if (tmPos < 0) { - appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y); + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x, y); } // write the text string @@ -1012,7 +1358,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, //~ its comb cell for (i = 0; i < text2->getLength(); ++i) { if (i > 0) { - appearBuf->appendf("{0:.2f} 0 Td\n", w); + appearBuf->appendf("{0:.4f} 0 Td\n", w); } appearBuf->append('('); c = text2->getChar(i) & 0xff; @@ -1020,7 +1366,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, appearBuf->append('\\'); appearBuf->append(c); } else if (c < 0x20 || c >= 0x80) { - appearBuf->appendf("{0:.2f} 0 Td\n", w); + appearBuf->appendf("{0:.4f} 0 Td\n", w); } else { appearBuf->append(c); } @@ -1052,21 +1398,21 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, if (tfPos >= 0) { tok = (GString *)daToks->get(tfPos + 1); tok->clear(); - tok->appendf("{0:.2f}", fontSize); + tok->appendf("{0:.4f}", fontSize); } } // compute text start position w *= fontSize; switch (quadding) { - case fieldQuadLeft: + case acroFormQuadLeft: default: x = border + 2; break; - case fieldQuadCenter: + case acroFormQuadCenter: x = (dx - w) / 2; break; - case fieldQuadRight: + case acroFormQuadRight: x = dx - border - 2 - w; break; } @@ -1076,10 +1422,10 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, if (tmPos >= 0) { tok = (GString *)daToks->get(tmPos + 4); tok->clear(); - tok->appendf("{0:.2f}", x); + tok->appendf("{0:.4f}", x); tok = (GString *)daToks->get(tmPos + 5); tok->clear(); - tok->appendf("{0:.2f}", y); + tok->appendf("{0:.4f}", y); } // write the DA string @@ -1091,7 +1437,7 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, // write the font matrix (if not part of the DA string) if (tmPos < 0) { - appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y); + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x, y); } // write the text string @@ -1127,13 +1473,15 @@ void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, } // Draw the variable text or caption for a field. -void Annot::drawListBox(GString **text, GBool *selection, - int nOptions, int topIdx, - GString *da, GfxFontDict *fontDict, GBool quadding) { +void AcroFormField::drawListBox(GString **text, GBool *selection, + int nOptions, int topIdx, + GString *da, GfxFontDict *fontDict, + GBool quadding, double xMin, double yMin, + double xMax, double yMax, double border) { GList *daToks; GString *tok; GfxFont *font; - double fontSize, fontSize2, border, x, y, w, wMax; + double fontSize, fontSize2, x, y, w, wMax; int tfPos, tmPos, i, j, c; //~ if there is no MK entry, this should use the existing content stream, @@ -1187,9 +1535,6 @@ void Annot::drawListBox(GString **text, GBool *selection, error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string"); } - // get the border width - border = borderStyle->getWidth(); - // compute font autosize if (fontSize == 0) { wMax = 0; @@ -1216,7 +1561,7 @@ void Annot::drawListBox(GString **text, GBool *selection, if (tfPos >= 0) { tok = (GString *)daToks->get(tfPos + 1); tok->clear(); - tok->appendf("{0:.2f}", fontSize); + tok->appendf("{0:.4f}", fontSize); } } @@ -1230,7 +1575,7 @@ void Annot::drawListBox(GString **text, GBool *selection, // draw the background if selected if (selection[i]) { appearBuf->append("0 g f\n"); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re f\n", border, y - 0.2 * fontSize, xMax - xMin - 2 * border, @@ -1254,14 +1599,14 @@ void Annot::drawListBox(GString **text, GBool *selection, // compute text start position w *= fontSize; switch (quadding) { - case fieldQuadLeft: + case acroFormQuadLeft: default: x = border + 2; break; - case fieldQuadCenter: + case acroFormQuadCenter: x = (xMax - xMin - w) / 2; break; - case fieldQuadRight: + case acroFormQuadRight: x = xMax - xMin - border - 2 - w; break; } @@ -1270,10 +1615,10 @@ void Annot::drawListBox(GString **text, GBool *selection, if (tmPos >= 0) { tok = (GString *)daToks->get(tmPos + 4); tok->clear(); - tok->appendf("{0:.2f}", x); + tok->appendf("{0:.4f}", x); tok = (GString *)daToks->get(tmPos + 5); tok->clear(); - tok->appendf("{0:.2f}", y); + tok->appendf("{0:.4f}", y); } // write the DA string @@ -1285,7 +1630,7 @@ void Annot::drawListBox(GString **text, GBool *selection, // write the font matrix (if not part of the DA string) if (tmPos < 0) { - appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y); + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", x, y); } // change the text color if selected @@ -1325,9 +1670,9 @@ void Annot::drawListBox(GString **text, GBool *selection, // *end = one past the last character to be included // *width = width of the characters start .. end-1 // *next = index of first character on the following line -void Annot::getNextLine(GString *text, int start, - GfxFont *font, double fontSize, double wMax, - int *end, double *width, int *next) { +void AcroFormField::getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next) { double w, dw; int j, k, c; @@ -1388,45 +1733,46 @@ void Annot::getNextLine(GString *text, int start, } // Draw an (approximate) circle of radius <r> centered at (<cx>, <cy>). -// If <fill> is true, the circle is filled; otherwise it is stroked. -void Annot::drawCircle(double cx, double cy, double r, GBool fill) { - appearBuf->appendf("{0:.2f} {1:.2f} m\n", +// <cmd> is used to draw the circle ("f", "s", or "b"). +void AcroFormField::drawCircle(double cx, double cy, double r, + const char *cmd) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", cx + r, cy); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx + r, cy + bezierCircle * r, cx + bezierCircle * r, cy + r, cx, cy + r); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx - bezierCircle * r, cy + r, cx - r, cy + bezierCircle * r, cx - r, cy); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx - r, cy - bezierCircle * r, cx - bezierCircle * r, cy - r, cx, cy - r); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx + bezierCircle * r, cy - r, cx + r, cy - bezierCircle * r, cx + r, cy); - appearBuf->append(fill ? "f\n" : "s\n"); + appearBuf->appendf("{0:s}\n", cmd); } // Draw the top-left half of an (approximate) circle of radius <r> // centered at (<cx>, <cy>). -void Annot::drawCircleTopLeft(double cx, double cy, double r) { +void AcroFormField::drawCircleTopLeft(double cx, double cy, double r) { double r2; r2 = r / sqrt(2.0); - appearBuf->appendf("{0:.2f} {1:.2f} m\n", + appearBuf->appendf("{0:.4f} {1:.4f} m\n", cx + r2, cy + r2); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx + (1 - bezierCircle) * r2, cy + (1 + bezierCircle) * r2, cx - (1 - bezierCircle) * r2, cy + (1 + bezierCircle) * r2, cx - r2, cy + r2); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx - (1 + bezierCircle) * r2, cy + (1 - bezierCircle) * r2, cx - (1 + bezierCircle) * r2, @@ -1438,20 +1784,20 @@ void Annot::drawCircleTopLeft(double cx, double cy, double r) { // Draw the bottom-right half of an (approximate) circle of radius <r> // centered at (<cx>, <cy>). -void Annot::drawCircleBottomRight(double cx, double cy, double r) { +void AcroFormField::drawCircleBottomRight(double cx, double cy, double r) { double r2; r2 = r / sqrt(2.0); - appearBuf->appendf("{0:.2f} {1:.2f} m\n", + appearBuf->appendf("{0:.4f} {1:.4f} m\n", cx - r2, cy - r2); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx - (1 - bezierCircle) * r2, cy - (1 + bezierCircle) * r2, cx + (1 - bezierCircle) * r2, cy - (1 + bezierCircle) * r2, cx + r2, cy - r2); - appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", cx + (1 + bezierCircle) * r2, cy - (1 - bezierCircle) * r2, cx + (1 + bezierCircle) * r2, @@ -1461,187 +1807,91 @@ void Annot::drawCircleBottomRight(double cx, double cy, double r) { appearBuf->append("S\n"); } -// Look up an inheritable field dictionary entry. -Object *Annot::fieldLookup(Dict *field, Dict *acroForm, - const char *key, Object *obj) { - Dict *dict; - Object parent; - - dict = field; - if (!dict->lookup(key, obj)->isNull()) { - return obj; - } - obj->free(); - if (dict->lookup("Parent", &parent)->isDict()) { - fieldLookup(parent.getDict(), acroForm, key, obj); - } else if (acroForm) { - // some fields don't specify a parent, so we check the AcroForm - // dictionary just in case - fieldLookup(acroForm, NULL, key, obj); - } else { - obj->initNull(); - } - parent.free(); - return obj; -} - -void Annot::draw(Gfx *gfx, GBool printing) { - Object obj; - GBool oc, isLink; - - // check the flags - if ((flags & annotFlagHidden) || - (printing && !(flags & annotFlagPrint)) || - (!printing && (flags & annotFlagNoView))) { - return; - } - - // check the optional content entry - if (doc->getOptionalContent()->evalOCObject(&ocObj, &oc) && !oc) { - return; - } - - // draw the appearance stream - isLink = type && !type->cmp("Link"); - appearance.fetch(doc->getXRef(), &obj); - gfx->drawAnnot(&obj, isLink ? borderStyle : (AnnotBorderStyle *)NULL, - xMin, yMin, xMax, yMax); - obj.free(); -} - -Object *Annot::getObject(Object *obj) { - if (ref.num >= 0) { - xref->fetch(ref.num, ref.gen, obj); - } else { - obj->initNull(); - } - return obj; -} - -//------------------------------------------------------------------------ -// Annots -//------------------------------------------------------------------------ - -Annots::Annots(PDFDoc *docA, Object *annotsObj) { - Annot *annot; - Object obj1; - Ref ref; - int size; +Object *AcroFormField::getResources(Object *res) { + Object kidsObj, annotObj, obj1; int i; - doc = docA; - annots = NULL; - size = 0; - nAnnots = 0; - - if (annotsObj->isArray()) { - for (i = 0; i < annotsObj->arrayGetLength(); ++i) { - if (annotsObj->arrayGetNF(i, &obj1)->isRef()) { - ref = obj1.getRef(); - obj1.free(); - annotsObj->arrayGet(i, &obj1); - } else { - ref.num = ref.gen = -1; - } - if (obj1.isDict()) { - annot = new Annot(doc, obj1.getDict(), &ref); - if (annot->isOk()) { - if (nAnnots >= size) { - size += 16; - annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); + if (acroForm->needAppearances) { + fieldLookup("DR", res); + } else { + res->initArray(acroForm->doc->getXRef()); + // find the annotation object(s) + if (fieldObj.dictLookup("Kids", &kidsObj)->isArray()) { + for (i = 0; i < kidsObj.arrayGetLength(); ++i) { + kidsObj.arrayGet(i, &annotObj); + if (annotObj.isDict()) { + if (getAnnotResources(annotObj.getDict(), &obj1)->isDict()) { + res->arrayAdd(&obj1); + } else { + obj1.free(); } - annots[nAnnots++] = annot; - } else { - delete annot; } + annotObj.free(); } - obj1.free(); - } - } -} - -Annots::~Annots() { - int i; - - for (i = 0; i < nAnnots; ++i) { - delete annots[i]; - } - gfree(annots); -} - -void Annots::generateAppearances() { - Dict *acroForm; - Object obj1, obj2; - Ref ref; - int i; - - acroForm = doc->getCatalog()->getAcroForm()->isDict() ? - doc->getCatalog()->getAcroForm()->getDict() : NULL; - if (acroForm->lookup("Fields", &obj1)->isArray()) { - for (i = 0; i < obj1.arrayGetLength(); ++i) { - if (obj1.arrayGetNF(i, &obj2)->isRef()) { - ref = obj2.getRef(); - obj2.free(); - obj1.arrayGet(i, &obj2); + } else { + if (getAnnotResources(fieldObj.getDict(), &obj1)->isDict()) { + res->arrayAdd(&obj1); } else { - ref.num = ref.gen = -1; - } - if (obj2.isDict()) { - scanFieldAppearances(obj2.getDict(), &ref, NULL, acroForm); + obj1.free(); } - obj2.free(); } + kidsObj.free(); } - obj1.free(); + + return res; } -void Annots::scanFieldAppearances(Dict *node, Ref *ref, Dict *parent, - Dict *acroForm) { - Annot *annot; - Object obj1, obj2; - Ref ref2; - int i; +Object *AcroFormField::getAnnotResources(Dict *annot, Object *res) { + Object apObj, asObj, appearance, obj1; - // non-terminal node: scan the children - if (node->lookup("Kids", &obj1)->isArray()) { - for (i = 0; i < obj1.arrayGetLength(); ++i) { - if (obj1.arrayGetNF(i, &obj2)->isRef()) { - ref2 = obj2.getRef(); - obj2.free(); - obj1.arrayGet(i, &obj2); + // get the appearance stream + if (annot->lookup("AP", &apObj)->isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict()) { + if (annot->lookup("AS", &asObj)->isName()) { + obj1.dictLookup(asObj.getName(), &appearance); + } else if (obj1.dictGetLength() == 1) { + obj1.dictGetVal(0, &appearance); } else { - ref2.num = ref2.gen = -1; - } - if (obj2.isDict()) { - scanFieldAppearances(obj2.getDict(), &ref2, node, acroForm); + obj1.dictLookup("Off", &appearance); } - obj2.free(); + asObj.free(); + } else { + obj1.copy(&appearance); } obj1.free(); - return; } - obj1.free(); + apObj.free(); - // terminal node: this is either a combined annot/field dict, or an - // annot dict whose parent is a field - if ((annot = findAnnot(ref))) { - node->lookupNF("Parent", &obj1); - if (!parent || !obj1.isNull()) { - annot->generateFieldAppearance(node, node, acroForm); - } else { - annot->generateFieldAppearance(parent, node, acroForm); - } - obj1.free(); + if (appearance.isStream()) { + appearance.streamGetDict()->lookup("Resources", res); + } else { + res->initNull(); } + appearance.free(); + + return res; } -Annot *Annots::findAnnot(Ref *ref) { - int i; +// Look up an inheritable field dictionary entry. +Object *AcroFormField::fieldLookup(const char *key, Object *obj) { + return fieldLookup(fieldObj.getDict(), key, obj); +} - for (i = 0; i < nAnnots; ++i) { - if (annots[i]->match(ref)) { - return annots[i]; - } +Object *AcroFormField::fieldLookup(Dict *dict, const char *key, Object *obj) { + Object parent; + + if (!dict->lookup(key, obj)->isNull()) { + return obj; } - return NULL; + obj->free(); + if (dict->lookup("Parent", &parent)->isDict()) { + fieldLookup(parent.getDict(), key, obj); + } else { + // some fields don't specify a parent, so we check the AcroForm + // dictionary just in case + acroForm->acroFormObj.dictLookup(key, obj); + } + parent.free(); + return obj; } diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.h new file mode 100644 index 00000000000..8e0075a858c --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/AcroForm.h @@ -0,0 +1,128 @@ +//======================================================================== +// +// AcroForm.h +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ACROFORM_H +#define ACROFORM_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Form.h" + +class TextString; +class GfxFont; +class GfxFontDict; + +//------------------------------------------------------------------------ + +class AcroForm: public Form { +public: + + static AcroForm *load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA); + + virtual ~AcroForm(); + + virtual const char *getType() { return "AcroForm"; } + + virtual void draw(int pageNum, Gfx *gfx, GBool printing); + + virtual int getNumFields(); + virtual FormField *getField(int idx); + +private: + + AcroForm(PDFDoc *docA, Object *acroFormObjA); + void buildAnnotPageList(Catalog *catalog); + int lookupAnnotPage(Object *annotRef); + void scanField(Object *fieldRef); + + Object acroFormObj; + GBool needAppearances; + GList *annotPages; // [AcroFormAnnotPage] + GList *fields; // [AcroFormField] + + friend class AcroFormField; +}; + +//------------------------------------------------------------------------ + +enum AcroFormFieldType { + acroFormFieldPushbutton, + acroFormFieldRadioButton, + acroFormFieldCheckbox, + acroFormFieldFileSelect, + acroFormFieldMultilineText, + acroFormFieldText, + acroFormFieldComboBox, + acroFormFieldListBox, + acroFormFieldSignature +}; + +class AcroFormField: public FormField { +public: + + static AcroFormField *load(AcroForm *acroFormA, Object *fieldRefA); + + virtual ~AcroFormField(); + + virtual const char *getType(); + virtual Unicode *getName(int *length); + virtual Unicode *getValue(int *length); + + virtual Object *getResources(Object *res); + +private: + + AcroFormField(AcroForm *acroFormA, Object *fieldRefA, Object *fieldObjA, + AcroFormFieldType typeA, TextString *nameA, + Guint flagsA); + void draw(int pageNum, Gfx *gfx, GBool printing); + void drawAnnot(int pageNum, Gfx *gfx, GBool printing, + Object *annotRef, Object *annotObj); + void drawExistingAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax); + void drawNewAppearance(Gfx *gfx, Dict *annot, + double xMin, double yMin, + double xMax, double yMax); + void setColor(Array *a, GBool fill, int adjust); + void drawText(GString *text, GString *da, GfxFontDict *fontDict, + GBool multiline, int comb, int quadding, + GBool txField, GBool forceZapfDingbats, int rot, + double xMin, double yMin, double xMax, double yMax, + double border); + void drawListBox(GString **text, GBool *selection, + int nOptions, int topIdx, + GString *da, GfxFontDict *fontDict, + GBool quadding, double xMin, double yMin, + double xMax, double yMax, double border); + void getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next); + void drawCircle(double cx, double cy, double r, const char *cmd); + void drawCircleTopLeft(double cx, double cy, double r); + void drawCircleBottomRight(double cx, double cy, double r); + Object *getAnnotResources(Dict *annot, Object *res); + Object *fieldLookup(const char *key, Object *obj); + Object *fieldLookup(Dict *dict, const char *key, Object *obj); + + AcroForm *acroForm; + Object fieldRef; + Object fieldObj; + AcroFormFieldType type; + TextString *name; + Guint flags; + GString *appearBuf; + + friend class AcroForm; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.cc new file mode 100644 index 00000000000..ff1e37648da --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.cc @@ -0,0 +1,1131 @@ +//======================================================================== +// +// Annot.cc +// +// Copyright 2000-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <math.h> +#include "gmem.h" +#include "GList.h" +#include "Error.h" +#include "Object.h" +#include "Catalog.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "Lexer.h" +#include "PDFDoc.h" +#include "OptionalContent.h" +#include "Form.h" +#include "Annot.h" + +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//------------------------------------------------------------------------ + +#define annotFlagHidden 0x0002 +#define annotFlagPrint 0x0004 +#define annotFlagNoView 0x0020 + +// distance of Bezier control point from center for circle approximation +// = (4 * (sqrt(2) - 1) / 3) * r +#define bezierCircle 0.55228475 + +#define lineEndSize1 6 +#define lineEndSize2 10 +#define lineArrowAngle (M_PI / 6) + +//------------------------------------------------------------------------ +// AnnotBorderStyle +//------------------------------------------------------------------------ + +AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType typeA, double widthA, + double *dashA, int dashLengthA, + double *colorA, int nColorCompsA) { + type = typeA; + width = widthA; + dash = dashA; + dashLength = dashLengthA; + color[0] = colorA[0]; + color[1] = colorA[1]; + color[2] = colorA[2]; + color[3] = colorA[3]; + nColorComps = nColorCompsA; +} + +AnnotBorderStyle::~AnnotBorderStyle() { + if (dash) { + gfree(dash); + } +} + +//------------------------------------------------------------------------ +// Annot +//------------------------------------------------------------------------ + +Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { + Object apObj, asObj, obj1, obj2, obj3; + AnnotBorderType borderType; + double borderWidth; + double *borderDash; + int borderDashLength; + double borderColor[4]; + int nBorderColorComps; + double t; + int i; + + ok = gTrue; + doc = docA; + xref = doc->getXRef(); + ref = *refA; + type = NULL; + appearanceState = NULL; + appearBuf = NULL; + borderStyle = NULL; + + //----- parse the type + + if (dict->lookup("Subtype", &obj1)->isName()) { + type = new GString(obj1.getName()); + } + obj1.free(); + + //----- parse the rectangle + + if (dict->lookup("Rect", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + xMin = yMin = xMax = yMax = 0; + if (obj1.arrayGet(0, &obj2)->isNum()) { + xMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + yMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + xMax = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(3, &obj2)->isNum()) { + yMax = obj2.getNum(); + } + obj2.free(); + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + } else { + error(errSyntaxError, -1, "Bad bounding box for annotation"); + ok = gFalse; + } + obj1.free(); + + //----- parse the flags + + if (dict->lookup("F", &obj1)->isInt()) { + flags = obj1.getInt(); + } else { + flags = 0; + } + obj1.free(); + + //----- parse the border style + + borderType = annotBorderSolid; + borderWidth = 1; + borderDash = NULL; + borderDashLength = 0; + nBorderColorComps = 3; + borderColor[0] = 0; + borderColor[1] = 0; + borderColor[2] = 1; + borderColor[3] = 0; + if (dict->lookup("BS", &obj1)->isDict()) { + if (obj1.dictLookup("S", &obj2)->isName()) { + if (obj2.isName("S")) { + borderType = annotBorderSolid; + } else if (obj2.isName("D")) { + borderType = annotBorderDashed; + } else if (obj2.isName("B")) { + borderType = annotBorderBeveled; + } else if (obj2.isName("I")) { + borderType = annotBorderInset; + } else if (obj2.isName("U")) { + borderType = annotBorderUnderlined; + } + } + obj2.free(); + if (obj1.dictLookup("W", &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.dictLookup("D", &obj2)->isArray()) { + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } + obj2.free(); + } else { + obj1.free(); + if (dict->lookup("Border", &obj1)->isArray()) { + if (obj1.arrayGetLength() >= 3) { + if (obj1.arrayGet(2, &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGetLength() >= 4) { + if (obj1.arrayGet(3, &obj2)->isArray()) { + borderType = annotBorderDashed; + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } else { + // Adobe draws no border at all if the last element is of + // the wrong type. + borderWidth = 0; + } + obj2.free(); + } + } else { + // an empty Border array also means "no border" + borderWidth = 0; + } + } + } + obj1.free(); + if (dict->lookup("C", &obj1)->isArray() && + (obj1.arrayGetLength() == 1 || + obj1.arrayGetLength() == 3 || + obj1.arrayGetLength() == 4)) { + nBorderColorComps = obj1.arrayGetLength(); + for (i = 0; i < nBorderColorComps; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + borderColor[i] = obj2.getNum(); + } else { + borderColor[i] = 0; + } + obj2.free(); + } + } + obj1.free(); + borderStyle = new AnnotBorderStyle(borderType, borderWidth, + borderDash, borderDashLength, + borderColor, nBorderColorComps); + + //----- get the appearance state + + dict->lookup("AP", &apObj); + dict->lookup("AS", &asObj); + if (asObj.isName()) { + appearanceState = new GString(asObj.getName()); + } else if (apObj.isDict()) { + apObj.dictLookup("N", &obj1); + if (obj1.isDict() && obj1.dictGetLength() == 1) { + appearanceState = new GString(obj1.dictGetKey(0)); + } + obj1.free(); + } + if (!appearanceState) { + appearanceState = new GString("Off"); + } + asObj.free(); + + //----- get the annotation appearance + + if (apObj.isDict()) { + apObj.dictLookup("N", &obj1); + apObj.dictLookupNF("N", &obj2); + if (obj1.isDict()) { + if (obj1.dictLookupNF(appearanceState->getCString(), &obj3)->isRef()) { + obj3.copy(&appearance); + } + obj3.free(); + } else if (obj2.isRef()) { + obj2.copy(&appearance); + } + obj1.free(); + obj2.free(); + } + apObj.free(); + + //----- get the optional content entry + + dict->lookupNF("OC", &ocObj); +} + +Annot::~Annot() { + if (type) { + delete type; + } + if (appearanceState) { + delete appearanceState; + } + appearance.free(); + if (appearBuf) { + delete appearBuf; + } + if (borderStyle) { + delete borderStyle; + } + ocObj.free(); +} + +void Annot::generateAnnotAppearance() { + Object obj; + + appearance.fetch(doc->getXRef(), &obj); + if (!obj.isStream()) { + if (type) { + if (!type->cmp("Line")) { + generateLineAppearance(); + } else if (!type->cmp("PolyLine")) { + generatePolyLineAppearance(); + } else if (!type->cmp("Polygon")) { + generatePolygonAppearance(); + } + } + } + obj.free(); +} + +//~ this doesn't draw the caption +void Annot::generateLineAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + MemStream *appearStream; + double x1, y1, x2, y2, dx, dy, len, w; + double lx1, ly1, lx2, ly2; + double tx1, ty1, tx2, ty2; + double ax1, ay1, ax2, ay2; + double bx1, by1, bx2, by2; + double leaderLen, leaderExtLen, leaderOffLen; + AnnotLineEndType lineEnd1, lineEnd2; + GBool fill; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- set line style, colors + setLineStyle(borderStyle, &w); + setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); + fill = gFalse; + if (annotObj.dictLookup("IC", &obj1)->isArray()) { + if (setFillColor(&obj1)) { + fill = gTrue; + } + } + obj1.free(); + + //----- get line properties + if (annotObj.dictLookup("L", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + if (obj1.arrayGet(0, &obj2)->isNum()) { + x1 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + y1 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + x2 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + if (obj1.arrayGet(3, &obj2)->isNum()) { + y2 = obj2.getNum(); + } else { + obj2.free(); + obj1.free(); + goto err1; + } + obj2.free(); + } else { + obj1.free(); + goto err1; + } + obj1.free(); + lineEnd1 = lineEnd2 = annotLineEndNone; + if (annotObj.dictLookup("LE", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + lineEnd1 = parseLineEndType(obj1.arrayGet(0, &obj2)); + obj2.free(); + lineEnd2 = parseLineEndType(obj1.arrayGet(1, &obj2)); + obj2.free(); + } + obj1.free(); + if (annotObj.dictLookup("LL", &obj1)->isNum()) { + leaderLen = obj1.getNum(); + } else { + leaderLen = 0; + } + obj1.free(); + if (annotObj.dictLookup("LLE", &obj1)->isNum()) { + leaderExtLen = obj1.getNum(); + } else { + leaderExtLen = 0; + } + obj1.free(); + if (annotObj.dictLookup("LLO", &obj1)->isNum()) { + leaderOffLen = obj1.getNum(); + } else { + leaderOffLen = 0; + } + obj1.free(); + + //----- compute positions + x1 -= xMin; + y1 -= yMin; + x2 -= xMin; + y2 -= yMin; + dx = x2 - x1; + dy = y2 - y1; + len = sqrt(dx*dx + dy*dy); + if (len > 0) { + dx /= len; + dy /= len; + } + if (leaderLen != 0) { + ax1 = x1 + leaderOffLen * dy; + ay1 = y1 - leaderOffLen * dx; + lx1 = ax1 + leaderLen * dy; + ly1 = ay1 - leaderLen * dx; + bx1 = lx1 + leaderExtLen * dy; + by1 = ly1 - leaderExtLen * dx; + ax2 = x2 + leaderOffLen * dy; + ay2 = y2 - leaderOffLen * dx; + lx2 = ax2 + leaderLen * dy; + ly2 = ay2 - leaderLen * dx; + bx2 = lx2 + leaderExtLen * dy; + by2 = ly2 - leaderExtLen * dx; + } else { + lx1 = x1; + ly1 = y1; + lx2 = x2; + ly2 = y2; + ax1 = ay1 = ax2 = ay2 = 0; // make gcc happy + bx1 = by1 = bx2 = by2 = 0; + } + adjustLineEndpoint(lineEnd1, lx1, ly1, dx, dy, w, &tx1, &ty1); + adjustLineEndpoint(lineEnd2, lx2, ly2, -dx, -dy, w, &tx2, &ty2); + + //----- draw leaders + if (leaderLen != 0) { + appearBuf->appendf("{0:.4f} {1:.4f} m {2:.4f} {3:.4f} l\n", + ax1, ay1, bx1, by1); + appearBuf->appendf("{0:.4f} {1:.4f} m {2:.4f} {3:.4f} l\n", + ax2, ay2 , bx2, by2); + } + + //----- draw the line + appearBuf->appendf("{0:.4f} {1:.4f} m {2:.4f} {3:.4f} l\n", + tx1, ty1, tx2, ty2); + appearBuf->append("S\n"); + + //----- draw the arrows + if (borderStyle->getType() == annotBorderDashed) { + appearBuf->append("[] 0 d\n"); + } + drawLineArrow(lineEnd1, lx1, ly1, dx, dy, w, fill); + drawLineArrow(lineEnd2, lx2, ly2, -dx, -dy, w, fill); + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + if (gfxStateDict.isDict()) { + obj1.initDict(doc->getXRef()); + obj2.initDict(doc->getXRef()); + obj2.dictAdd(copyString("GS1"), &gfxStateDict); + obj1.dictAdd(copyString("ExtGState"), &obj2); + appearDict.dictAdd(copyString("Resources"), &obj1); + } + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + err1: + annotObj.free(); +} + +//~ this doesn't handle line ends (arrows) +void Annot::generatePolyLineAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + MemStream *appearStream; + double x1, y1, w; + int i; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- set line style, colors + setLineStyle(borderStyle, &w); + setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); + // fill = gFalse; + // if (annotObj.dictLookup("IC", &obj1)->isArray()) { + // if (setFillColor(&obj1)) { + // fill = gTrue; + // } + // } + // obj1.free(); + + //----- draw line + if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + obj1.free(); + goto err1; + } + for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { + if (!obj1.arrayGet(i, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(i+1, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + x1 -= xMin; + y1 -= yMin; + if (i == 0) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", x1, y1); + } else { + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x1, y1); + } + } + appearBuf->append("S\n"); + obj1.free(); + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + if (gfxStateDict.isDict()) { + obj1.initDict(doc->getXRef()); + obj2.initDict(doc->getXRef()); + obj2.dictAdd(copyString("GS1"), &gfxStateDict); + obj1.dictAdd(copyString("ExtGState"), &obj2); + appearDict.dictAdd(copyString("Resources"), &obj1); + } + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + err1: + annotObj.free(); +} + +void Annot::generatePolygonAppearance() { + Object annotObj, gfxStateDict, appearDict, obj1, obj2; + MemStream *appearStream; + double x1, y1; + int i; + + if (!getObject(&annotObj)->isDict()) { + annotObj.free(); + return; + } + + appearBuf = new GString(); + + //----- check for transparency + if (annotObj.dictLookup("CA", &obj1)->isNum()) { + gfxStateDict.initDict(doc->getXRef()); + gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); + appearBuf->append("/GS1 gs\n"); + } + obj1.free(); + + //----- set fill color + if (!annotObj.dictLookup("IC", &obj1)->isArray() || + !setFillColor(&obj1)) { + obj1.free(); + goto err1; + } + obj1.free(); + + //----- fill polygon + if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + obj1.free(); + goto err1; + } + for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { + if (!obj1.arrayGet(i, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(i+1, &obj2)->isNum()) { + obj2.free(); + obj1.free(); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + x1 -= xMin; + y1 -= yMin; + if (i == 0) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", x1, y1); + } else { + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x1, y1); + } + } + appearBuf->append("f\n"); + obj1.free(); + + //----- build the appearance stream dictionary + appearDict.initDict(doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + if (gfxStateDict.isDict()) { + obj1.initDict(doc->getXRef()); + obj2.initDict(doc->getXRef()); + obj2.dictAdd(copyString("GS1"), &gfxStateDict); + obj1.dictAdd(copyString("ExtGState"), &obj2); + appearDict.dictAdd(copyString("Resources"), &obj1); + } + + //----- build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + err1: + annotObj.free(); +} + +void Annot::setLineStyle(AnnotBorderStyle *bs, double *lineWidth) { + double *dash; + double w; + int dashLength, i; + + if ((w = borderStyle->getWidth()) <= 0) { + w = 0.1; + } + *lineWidth = w; + appearBuf->appendf("{0:.4f} w\n", w); + // this treats beveled/inset/underline as solid + if (borderStyle->getType() == annotBorderDashed) { + borderStyle->getDash(&dash, &dashLength); + appearBuf->append("["); + for (i = 0; i < dashLength; ++i) { + appearBuf->appendf(" {0:.4f}", dash[i]); + } + appearBuf->append("] 0 d\n"); + } + appearBuf->append("0 j\n0 J\n"); +} + +void Annot::setStrokeColor(double *color, int nComps) { + switch (nComps) { + case 0: + appearBuf->append("0 G\n"); + break; + case 1: + appearBuf->appendf("{0:.2f} G\n", color[0]); + break; + case 3: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} RG\n", + color[0], color[1], color[2]); + break; + case 4: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} K\n", + color[0], color[1], color[2], color[3]); + break; + } +} + +GBool Annot::setFillColor(Object *colorObj) { + Object obj; + double color[4]; + int i; + + if (!colorObj->isArray()) { + return gFalse; + } + for (i = 0; i < colorObj->arrayGetLength(); ++i) { + if (colorObj->arrayGet(i, &obj)->isNum()) { + color[i] = obj.getNum(); + } else { + color[i] = 0; + } + obj.free(); + } + switch (colorObj->arrayGetLength()) { + case 1: + appearBuf->appendf("{0:.2f} g\n", color[0]); + return gTrue; + case 3: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} rg\n", + color[0], color[1], color[2]); + return gTrue; + case 4: + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.3f} k\n", + color[0], color[1], + color[2], color[3]); + return gTrue; + } + return gFalse; +} + +AnnotLineEndType Annot::parseLineEndType(Object *obj) { + if (obj->isName("None")) { + return annotLineEndNone; + } else if (obj->isName("Square")) { + return annotLineEndSquare; + } else if (obj->isName("Circle")) { + return annotLineEndCircle; + } else if (obj->isName("Diamond")) { + return annotLineEndDiamond; + } else if (obj->isName("OpenArrow")) { + return annotLineEndOpenArrow; + } else if (obj->isName("ClosedArrow")) { + return annotLineEndClosedArrow; + } else if (obj->isName("Butt")) { + return annotLineEndButt; + } else if (obj->isName("ROpenArrow")) { + return annotLineEndROpenArrow; + } else if (obj->isName("RClosedArrow")) { + return annotLineEndRClosedArrow; + } else if (obj->isName("Slash")) { + return annotLineEndSlash; + } else { + return annotLineEndNone; + } +} + +void Annot::adjustLineEndpoint(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, double *tx, double *ty) { + switch (lineEnd) { + case annotLineEndNone: + w = 0; + break; + case annotLineEndSquare: + w *= lineEndSize1; + break; + case annotLineEndCircle: + w *= lineEndSize1; + break; + case annotLineEndDiamond: + w *= lineEndSize1; + break; + case annotLineEndOpenArrow: + w = 0; + break; + case annotLineEndClosedArrow: + w *= lineEndSize2 * cos(lineArrowAngle); + break; + case annotLineEndButt: + w = 0; + break; + case annotLineEndROpenArrow: + w *= lineEndSize2 * cos(lineArrowAngle); + break; + case annotLineEndRClosedArrow: + w *= lineEndSize2 * cos(lineArrowAngle); + break; + case annotLineEndSlash: + w = 0; + break; + } + *tx = x + w * dx; + *ty = y + w * dy; +} + +void Annot::drawLineArrow(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, GBool fill) { + switch (lineEnd) { + case annotLineEndNone: + break; + case annotLineEndSquare: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*dx + 0.5*w*dy, + y + w*dy - 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + 0.5*w*dy, + y - 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - 0.5*w*dy, + y + 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*dx - 0.5*w*dy, + y + w*dy + 0.5*w*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndCircle: + w *= lineEndSize1; + drawCircle(x + 0.5*w*dx, y + 0.5*w*dy, 0.5*w, fill ? "b" : "s"); + break; + case annotLineEndDiamond: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", x, y); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + 0.5*w*dx - 0.5*w*dy, + y + 0.5*w*dy + 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*dx, + y + w*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + 0.5*w*dx + 0.5*w*dy, + y + 0.5*w*dy - 0.5*w*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndOpenArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*cos(lineArrowAngle)*dx + w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x, y); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx - w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy + w*sin(lineArrowAngle)*dx); + appearBuf->append("S\n"); + break; + case annotLineEndClosedArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*cos(lineArrowAngle)*dx + w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", x, y); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx - w*sin(lineArrowAngle)*dy, + y + w*cos(lineArrowAngle)*dy + w*sin(lineArrowAngle)*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndButt: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + 0.5*w*dy, + y - 0.5*w*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - 0.5*w*dy, + y + 0.5*w*dx); + appearBuf->append("S\n"); + break; + case annotLineEndROpenArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*sin(lineArrowAngle)*dy, + y - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx, + y + w*cos(lineArrowAngle)*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - w*sin(lineArrowAngle)*dy, + y + w*sin(lineArrowAngle)*dx); + appearBuf->append("S\n"); + break; + case annotLineEndRClosedArrow: + w *= lineEndSize2; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + w*sin(lineArrowAngle)*dy, + y - w*sin(lineArrowAngle)*dx); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x + w*cos(lineArrowAngle)*dx, + y + w*cos(lineArrowAngle)*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - w*sin(lineArrowAngle)*dy, + y + w*sin(lineArrowAngle)*dx); + appearBuf->append(fill ? "b\n" : "s\n"); + break; + case annotLineEndSlash: + w *= lineEndSize1; + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + x + 0.5*w*cos(lineArrowAngle)*dy + - 0.5*w*sin(lineArrowAngle)*dx, + y - 0.5*w*cos(lineArrowAngle)*dx + - 0.5*w*sin(lineArrowAngle)*dy); + appearBuf->appendf("{0:.4f} {1:.4f} l\n", + x - 0.5*w*cos(lineArrowAngle)*dy + + 0.5*w*sin(lineArrowAngle)*dx, + y + 0.5*w*cos(lineArrowAngle)*dx + + 0.5*w*sin(lineArrowAngle)*dy); + appearBuf->append("S\n"); + break; + } +} + +// Draw an (approximate) circle of radius <r> centered at (<cx>, <cy>). +// <cmd> is used to draw the circle ("f", "s", or "b"). +void Annot::drawCircle(double cx, double cy, double r, const char *cmd) { + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx + r, cy); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + r, cy + bezierCircle * r, + cx + bezierCircle * r, cy + r, + cx, cy + r); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - bezierCircle * r, cy + r, + cx - r, cy + bezierCircle * r, + cx - r, cy); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - r, cy - bezierCircle * r, + cx - bezierCircle * r, cy - r, + cx, cy - r); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + bezierCircle * r, cy - r, + cx + r, cy - bezierCircle * r, + cx + r, cy); + appearBuf->appendf("{0:s}\n", cmd); +} + +// Draw the top-left half of an (approximate) circle of radius <r> +// centered at (<cx>, <cy>). +void Annot::drawCircleTopLeft(double cx, double cy, double r) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx + r2, cy + r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - r2, + cy + r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx - (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx - r2, + cy - r2); + appearBuf->append("S\n"); +} + +// Draw the bottom-right half of an (approximate) circle of radius <r> +// centered at (<cx>, <cy>). +void Annot::drawCircleBottomRight(double cx, double cy, double r) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.4f} {1:.4f} m\n", + cx - r2, cy - r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx - (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + r2, + cy - r2); + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} {4:.4f} {5:.4f} c\n", + cx + (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx + (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx + r2, + cy + r2); + appearBuf->append("S\n"); +} + +void Annot::draw(Gfx *gfx, GBool printing) { + GBool oc, isLink; + + // check the flags + if ((flags & annotFlagHidden) || + (printing && !(flags & annotFlagPrint)) || + (!printing && (flags & annotFlagNoView))) { + return; + } + + // check the optional content entry + if (doc->getOptionalContent()->evalOCObject(&ocObj, &oc) && !oc) { + return; + } + + // draw the appearance stream + isLink = type && !type->cmp("Link"); + gfx->drawAnnot(&appearance, isLink ? borderStyle : (AnnotBorderStyle *)NULL, + xMin, yMin, xMax, yMax); +} + +Object *Annot::getObject(Object *obj) { + if (ref.num >= 0) { + xref->fetch(ref.num, ref.gen, obj); + } else { + obj->initNull(); + } + return obj; +} + +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +Annots::Annots(PDFDoc *docA, Object *annotsObj) { + Annot *annot; + Object obj1, obj2; + Ref ref; + GBool drawWidgetAnnots; + int size; + int i; + + doc = docA; + annots = NULL; + size = 0; + nAnnots = 0; + + if (annotsObj->isArray()) { + // Kludge: some PDF files define an empty AcroForm, but still + // include Widget-type annotations -- in that case, we want to + // draw the widgets (since the form code won't). This really + // ought to look for Widget-type annotations that are not included + // in any form field. + drawWidgetAnnots = !doc->getCatalog()->getForm() || + doc->getCatalog()->getForm()->getNumFields() == 0; + for (i = 0; i < annotsObj->arrayGetLength(); ++i) { + if (annotsObj->arrayGetNF(i, &obj1)->isRef()) { + ref = obj1.getRef(); + obj1.free(); + annotsObj->arrayGet(i, &obj1); + } else { + ref.num = ref.gen = -1; + } + if (obj1.isDict()) { + if (drawWidgetAnnots || + !obj1.dictLookup("Subtype", &obj2)->isName("Widget")) { + annot = new Annot(doc, obj1.getDict(), &ref); + if (annot->isOk()) { + if (nAnnots >= size) { + size += 16; + annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); + } + annots[nAnnots++] = annot; + } else { + delete annot; + } + } + obj2.free(); + } + obj1.free(); + } + } +} + +Annots::~Annots() { + int i; + + for (i = 0; i < nAnnots; ++i) { + delete annots[i]; + } + gfree(annots); +} + +void Annots::generateAnnotAppearances() { + int i; + + for (i = 0; i < nAnnots; ++i) { + annots[i]->generateAnnotAppearance(); + } +} + +Annot *Annots::findAnnot(Ref *ref) { + int i; + + for (i = 0; i < nAnnots; ++i) { + if (annots[i]->match(ref)) { + return annots[i]; + } + } + return NULL; +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Annot.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.h index 987e80ecd97..6f52ac45670 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Annot.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Annot.h @@ -38,15 +38,15 @@ public: AnnotBorderStyle(AnnotBorderType typeA, double widthA, double *dashA, int dashLengthA, - double rA, double gA, double bA); + double *colorA, int nColorCompsA); ~AnnotBorderStyle(); AnnotBorderType getType() { return type; } double getWidth() { return width; } void getDash(double **dashA, int *dashLengthA) { *dashA = dash; *dashLengthA = dashLength; } - void getColor(double *rA, double *gA, double *bA) - { *rA = r; *gA = g; *bA = b; } + int getNumColorComps() { return nColorComps; } + double *getColor() { return color; } private: @@ -54,7 +54,23 @@ private: double width; double *dash; int dashLength; - double r, g, b; + double color[4]; + int nColorComps; +}; + +//------------------------------------------------------------------------ + +enum AnnotLineEndType { + annotLineEndNone, + annotLineEndSquare, + annotLineEndCircle, + annotLineEndDiamond, + annotLineEndOpenArrow, + annotLineEndClosedArrow, + annotLineEndButt, + annotLineEndROpenArrow, + annotLineEndRClosedArrow, + annotLineEndSlash }; //------------------------------------------------------------------------ @@ -85,25 +101,26 @@ public: GBool match(Ref *refA) { return ref.num == refA->num && ref.gen == refA->gen; } - void generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm); + void generateAnnotAppearance(); private: - void setColor(Array *a, GBool fill, int adjust); - void drawText(GString *text, GString *da, GfxFontDict *fontDict, - GBool multiline, int comb, int quadding, - GBool txField, GBool forceZapfDingbats, int rot); - void drawListBox(GString **text, GBool *selection, - int nOptions, int topIdx, - GString *da, GfxFontDict *fontDict, GBool quadding); - void getNextLine(GString *text, int start, - GfxFont *font, double fontSize, double wMax, - int *end, double *width, int *next); - void drawCircle(double cx, double cy, double r, GBool fill); + void generateLineAppearance(); + void generatePolyLineAppearance(); + void generatePolygonAppearance(); + void setLineStyle(AnnotBorderStyle *bs, double *lineWidth); + void setStrokeColor(double *color, int nComps); + GBool setFillColor(Object *colorObj); + AnnotLineEndType parseLineEndType(Object *obj); + void adjustLineEndpoint(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, double *tx, double *ty); + void drawLineArrow(AnnotLineEndType lineEnd, + double x, double y, double dx, double dy, + double w, GBool fill); + void drawCircle(double cx, double cy, double r, const char *cmd); void drawCircleTopLeft(double cx, double cy, double r); void drawCircleBottomRight(double cx, double cy, double r); - Object *fieldLookup(Dict *field, Dict *acroForm, - const char *key, Object *obj); PDFDoc *doc; XRef *xref; // the xref table for this PDF file @@ -137,9 +154,9 @@ public: int getNumAnnots() { return nAnnots; } Annot *getAnnot(int i) { return annots[i]; } - // (Re)generate the appearance streams for all annotations belonging - // to a form field. - void generateAppearances(); + // Generate an appearance stream for any non-form-field annotation + // that is missing it. + void generateAnnotAppearances(); private: diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Array.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Array.cc index 10ded148db6..10ded148db6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Array.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Array.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Array.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Array.h index 20ae05f2970..20ae05f2970 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Array.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Array.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFont.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFont.cc index 33c9fa5e11e..33c9fa5e11e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFont.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFont.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFont.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFont.h index 9cddb0ceef1..9cddb0ceef1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFont.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFont.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFontTables.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFontTables.cc index 9c362389c1b..9c362389c1b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFontTables.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFontTables.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFontTables.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFontTables.h index eb45549efd2..eb45549efd2 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/BuiltinFontTables.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/BuiltinFontTables.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CMap.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CMap.cc index bb80bdde7f4..affdf931df9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CMap.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CMap.cc @@ -283,34 +283,36 @@ void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) { void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) { CMapVectorEntry *vec; - CID cid; - int byte; - Guint i, j; - - vec = vector; - for (i = nBytes - 1; i >= 1; --i) { - byte = (start >> (8 * i)) & 0xff; - if (!vec[byte].isVector) { - vec[byte].isVector = gTrue; - vec[byte].vector = - (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); - for (j = 0; j < 256; ++j) { - vec[byte].vector[j].isVector = gFalse; - vec[byte].vector[j].cid = 0; + int byte, byte0, byte1; + Guint start1, end1, i, j, k; + + start1 = start & 0xffffff00; + end1 = end & 0xffffff00; + for (i = start1; i <= end1; i += 0x100) { + vec = vector; + for (j = nBytes - 1; j >= 1; --j) { + byte = (i >> (8 * j)) & 0xff; + if (!vec[byte].isVector) { + vec[byte].isVector = gTrue; + vec[byte].vector = + (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (k = 0; k < 256; ++k) { + vec[byte].vector[k].isVector = gFalse; + vec[byte].vector[k].cid = 0; + } } + vec = vec[byte].vector; } - vec = vec[byte].vector; - } - cid = firstCID; - for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) { - if (vec[byte].isVector) { - error(errSyntaxError, -1, - "Invalid CID ({0:x} - {1:x} [{2:d} bytes]) in CMap", - start, end, nBytes); - } else { - vec[byte].cid = cid; + byte0 = (i < start) ? (start & 0xff) : 0; + byte1 = (i + 0xff > end) ? (end & 0xff) : 0xff; + for (byte = byte0; byte <= byte1; ++byte) { + if (vec[byte].isVector) { + error(errSyntaxError, -1, "Invalid CID ({0:x} [{1:d} bytes]) in CMap", + i, nBytes); + } else { + vec[byte].cid = firstCID + ((i + byte) - start); + } } - ++cid; } } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CMap.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CMap.h index f21b800c2b3..f21b800c2b3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CMap.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CMap.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Catalog.cc index 6c8a703b786..e2e2a8747d4 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Catalog.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Catalog.cc @@ -2,7 +2,7 @@ // // Catalog.cc // -// Copyright 1996-2007 Glyph & Cog, LLC +// Copyright 1996-2013 Glyph & Cog, LLC // //======================================================================== @@ -27,7 +27,8 @@ #include "Page.h" #include "Error.h" #include "Link.h" -#include "PDFDocEncoding.h" +#include "Form.h" +#include "TextString.h" #include "Catalog.h" //------------------------------------------------------------------------ @@ -69,23 +70,20 @@ PageTreeNode::~PageTreeNode() { class EmbeddedFile { public: - EmbeddedFile(Unicode *nameA, int nameLenA, Object *streamRefA); + EmbeddedFile(TextString *nameA, Object *streamRefA); ~EmbeddedFile(); - Unicode *name; - int nameLen; + TextString *name; Object streamRef; }; -EmbeddedFile::EmbeddedFile(Unicode *nameA, int nameLenA, - Object *streamRefA) { +EmbeddedFile::EmbeddedFile(TextString *nameA, Object *streamRefA) { name = nameA; - nameLen = nameLenA; streamRefA->copy(&streamRef); } EmbeddedFile::~EmbeddedFile() { - gfree(name); + delete name; streamRef.free(); } @@ -105,6 +103,7 @@ Catalog::Catalog(PDFDoc *docA) { pageRefs = NULL; numPages = 0; baseURI = NULL; + form = NULL; embeddedFiles = NULL; xref->getCatalog(&catDict); @@ -165,6 +164,10 @@ Catalog::Catalog(PDFDoc *docA) { // get the AcroForm dictionary catDict.dictLookup("AcroForm", &acroForm); + if (!acroForm.isNull()) { + form = Form::load(doc, this, &acroForm); + } + // get the OCProperties dictionary catDict.dictLookup("OCProperties", &ocProperties); @@ -205,6 +208,9 @@ Catalog::~Catalog() { structTreeRoot.free(); outline.free(); acroForm.free(); + if (form) { + delete form; + } ocProperties.free(); if (embeddedFiles) { deleteGList(embeddedFiles, EmbeddedFile); @@ -236,7 +242,8 @@ GString *Catalog::readMetadata() { GString *s; Dict *dict; Object obj; - int c; + char buf[4096]; + int n; if (!metadata.isStream()) { return NULL; @@ -249,8 +256,8 @@ GString *Catalog::readMetadata() { obj.free(); s = new GString(); metadata.streamReset(); - while ((c = metadata.streamGetChar()) != EOF) { - s->append(c); + while ((n = metadata.streamGetBlock(buf, sizeof(buf))) > 0) { + s->append(buf, n); } metadata.streamClose(); return s; @@ -615,6 +622,12 @@ void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, Object pageNode, kids, kid, annots, annot, subtype, fileSpec, contents; int i; + // check for an invalid object reference (e.g., in a damaged PDF file) + if (pageNodeRef->getRefNum() < 0 || + pageNodeRef->getRefNum() >= xref->getNumObjects()) { + return; + } + // check for a page tree loop if (pageNodeRef->isRef()) { if (touchedObjs[pageNodeRef->getRefNum()]) { @@ -661,42 +674,22 @@ void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, void Catalog::readEmbeddedFile(Object *fileSpec, Object *name1) { Object name2, efObj, streamObj; GString *s; - Unicode *name; - int nameLen, i; + TextString *name; if (fileSpec->isDict()) { if (fileSpec->dictLookup("UF", &name2)->isString()) { - s = name2.getString(); + name = new TextString(name2.getString()); } else { name2.free(); if (fileSpec->dictLookup("F", &name2)->isString()) { - s = name2.getString(); + name = new TextString(name2.getString()); } else if (name1 && name1->isString()) { - s = name1->getString(); - } else { - s = NULL; - } - } - if (s) { - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - nameLen = (s->getLength() - 2) / 2; - name = (Unicode *)gmallocn(nameLen, sizeof(Unicode)); - for (i = 0; i < nameLen; ++i) { - name[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | - (s->getChar(3 + 2*i) & 0xff); - } + name = new TextString(name1->getString()); } else { - nameLen = s->getLength(); - name = (Unicode *)gmallocn(nameLen, sizeof(Unicode)); - for (i = 0; i < nameLen; ++i) { - name[i] = pdfDocEncoding[s->getChar(i) & 0xff]; - } + s = new GString("?"); + name = new TextString(s); + delete s; } - } else { - nameLen = 1; - name = (Unicode *)gmallocn(nameLen, sizeof(Unicode)); - name[0] = '?'; } name2.free(); if (fileSpec->dictLookup("EF", &efObj)->isDict()) { @@ -704,13 +697,13 @@ void Catalog::readEmbeddedFile(Object *fileSpec, Object *name1) { if (!embeddedFiles) { embeddedFiles = new GList(); } - embeddedFiles->append(new EmbeddedFile(name, nameLen, &streamObj)); + embeddedFiles->append(new EmbeddedFile(name, &streamObj)); } else { - gfree(name); + delete name; } streamObj.free(); } else { - gfree(name); + delete name; } efObj.free(); } @@ -721,11 +714,15 @@ int Catalog::getNumEmbeddedFiles() { } Unicode *Catalog::getEmbeddedFileName(int idx) { - return ((EmbeddedFile *)embeddedFiles->get(idx))->name; + return ((EmbeddedFile *)embeddedFiles->get(idx))->name->getUnicode(); } int Catalog::getEmbeddedFileNameLength(int idx) { - return ((EmbeddedFile *)embeddedFiles->get(idx))->nameLen; + return ((EmbeddedFile *)embeddedFiles->get(idx))->name->getLength(); +} + +Object *Catalog::getEmbeddedFileStreamRef(int idx) { + return &((EmbeddedFile *)embeddedFiles->get(idx))->streamRef; } Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) { diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Catalog.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Catalog.h index efbbeda3635..7f064aac849 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Catalog.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Catalog.h @@ -26,6 +26,7 @@ class PageAttrs; struct Ref; class LinkDest; class PageTreeNode; +class Form; //------------------------------------------------------------------------ // Catalog @@ -82,12 +83,15 @@ public: Object *getAcroForm() { return &acroForm; } + Form *getForm() { return form; } + Object *getOCProperties() { return &ocProperties; } // Get the list of embedded files. int getNumEmbeddedFiles(); Unicode *getEmbeddedFileName(int idx); int getEmbeddedFileNameLength(int idx); + Object *getEmbeddedFileStreamRef(int idx); Object *getEmbeddedFileStreamObj(int idx, Object *strObj); private: @@ -106,6 +110,7 @@ private: Object structTreeRoot; // structure tree root dictionary Object outline; // outline dictionary Object acroForm; // AcroForm dictionary + Form *form; // parsed form Object ocProperties; // OCProperties dictionary GList *embeddedFiles; // embedded file list [EmbeddedFile] GBool ok; // true if catalog is valid diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CharCodeToUnicode.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CharCodeToUnicode.cc index ff40595575d..674b992434c 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CharCodeToUnicode.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CharCodeToUnicode.cc @@ -167,7 +167,7 @@ CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode( while (getLine(buf, sizeof(buf), f)) { ++line; if (!(tok = strtok(buf, " \t\r\n")) || - !parseHex(tok, strlen(tok), &u0)) { + !parseHex(tok, (int)strlen(tok), &u0)) { error(errSyntaxWarning, -1, "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'", line, fileName); @@ -178,7 +178,7 @@ CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode( if (!(tok = strtok(NULL, " \t\r\n"))) { break; } - if (!parseHex(tok, strlen(tok), &uBuf[n])) { + if (!parseHex(tok, (int)strlen(tok), &uBuf[n])) { error(errSyntaxWarning, -1, "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'", line, fileName); @@ -336,23 +336,21 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, if (code1 > maxCode || code2 > maxCode) { error(errSyntaxWarning, -1, "Invalid entry in bfrange block in ToUnicode CMap"); - if (code1 > maxCode) { - code1 = maxCode; - } if (code2 > maxCode) { code2 = maxCode; } } if (!strcmp(tok3, "[")) { i = 0; - while (pst->getToken(tok1, sizeof(tok1), &n1) && - code1 + i <= code2) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { if (!strcmp(tok1, "]")) { break; } if (tok1[0] == '<' && tok1[n1 - 1] == '>') { - tok1[n1 - 1] = '\0'; - addMapping(code1 + i, tok1 + 1, n1 - 2, 0); + if (code1 + i <= code2) { + tok1[n1 - 1] = '\0'; + addMapping(code1 + i, tok1 + 1, n1 - 2, 0); + } } else { error(errSyntaxWarning, -1, "Illegal entry in bfrange block in ToUnicode CMap"); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CharCodeToUnicode.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CharCodeToUnicode.h index b4ccd0439f8..1b870efe8d0 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CharCodeToUnicode.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CharCodeToUnicode.h @@ -74,6 +74,8 @@ public: // code supported by the mapping. CharCode getLength() { return mapLen; } + GBool isIdentity() { return !map; } + private: void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CharTypes.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CharTypes.h index d0df630d0c9..d0df630d0c9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CharTypes.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CharTypes.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CompactFontTables.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CompactFontTables.h index 28e16e775ea..28e16e775ea 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CompactFontTables.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CompactFontTables.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CoreOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CoreOutputDev.cc index 78751102430..78751102430 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CoreOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CoreOutputDev.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CoreOutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CoreOutputDev.h index 006d3517f4d..006d3517f4d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/CoreOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/CoreOutputDev.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Decrypt.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Decrypt.cc index afde3c30ceb..bf0bfb7007c 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Decrypt.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Decrypt.cc @@ -16,13 +16,12 @@ #include "gmem.h" #include "Decrypt.h" -static void aesKeyExpansion(DecryptAESState *s, - Guchar *objKey, int objKeyLen); -static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last); static void aes256KeyExpansion(DecryptAES256State *s, Guchar *objKey, int objKeyLen); static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last); static void sha256(Guchar *msg, int msgLen, Guchar *hash); +static void sha384(Guchar *msg, int msgLen, Guchar *hash); +static void sha512(Guchar *msg, int msgLen, Guchar *hash); static Guchar passwordPad[32] = { 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, @@ -45,6 +44,7 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, DecryptAES256State state; Guchar test[127 + 56], test2[32]; GString *userPassword2; + const char *userPW; Guchar fState[256]; Guchar tmpKey[16]; Guchar fx, fy; @@ -52,7 +52,7 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, *ownerPasswordOk = gFalse; - if (encRevision == 5) { + if (encRevision == 5 || encRevision == 6) { // check the owner password if (ownerPassword) { @@ -65,6 +65,10 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, memcpy(test + len, ownerKey->getCString() + 32, 8); memcpy(test + len + 8, userKey->getCString(), 48); sha256(test, len + 56, test); + if (encRevision == 6) { + r6Hash(test, 32, ownerPassword->getCString(), len, + userKey->getCString()); + } if (!memcmp(test, ownerKey->getCString(), 32)) { // compute the file key from the owner password @@ -72,6 +76,10 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, memcpy(test + len, ownerKey->getCString() + 40, 8); memcpy(test + len + 8, userKey->getCString(), 48); sha256(test, len + 56, test); + if (encRevision == 6) { + r6Hash(test, 32, ownerPassword->getCString(), len, + userKey->getCString()); + } aes256KeyExpansion(&state, test, 32); for (i = 0; i < 16; ++i) { state.cbc[i] = 0; @@ -90,34 +98,45 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, // check the user password if (userPassword) { //~ this is supposed to convert the password to UTF-8 using "SASLprep" + userPW = userPassword->getCString(); len = userPassword->getLength(); if (len > 127) { len = 127; } - memcpy(test, userPassword->getCString(), len); - memcpy(test + len, userKey->getCString() + 32, 8); - sha256(test, len + 8, test); - if (!memcmp(test, userKey->getCString(), 32)) { - - // compute the file key from the user password - memcpy(test, userPassword->getCString(), len); - memcpy(test + len, userKey->getCString() + 40, 8); - sha256(test, len + 8, test); - aes256KeyExpansion(&state, test, 32); - for (i = 0; i < 16; ++i) { - state.cbc[i] = 0; - } - aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse); - memcpy(fileKey, state.buf, 16); - aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16, - gFalse); - memcpy(fileKey + 16, state.buf, 16); + } else { + userPW = ""; + len = 0; + } + memcpy(test, userPW, len); + memcpy(test + len, userKey->getCString() + 32, 8); + sha256(test, len + 8, test); + if (encRevision == 6) { + r6Hash(test, 32, userPW, len, NULL); + } + if (!memcmp(test, userKey->getCString(), 32)) { - return gTrue; + // compute the file key from the user password + memcpy(test, userPW, len); + memcpy(test + len, userKey->getCString() + 40, 8); + sha256(test, len + 8, test); + if (encRevision == 6) { + r6Hash(test, 32, userPW, len, NULL); } + aes256KeyExpansion(&state, test, 32); + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } + aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse); + memcpy(fileKey, state.buf, 16); + aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16, + gFalse); + memcpy(fileKey + 16, state.buf, 16); + + return gTrue; } return gFalse; + } else { // try using the supplied owner password to generate the user password @@ -172,6 +191,61 @@ GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, } } +void Decrypt::r6Hash(Guchar *key, int keyLen, const char *pwd, int pwdLen, + char *userKey) { + Guchar key1[64*(127+64+48)]; + DecryptAESState state128; + int n, i, j, k; + + i = 0; + while (1) { + memcpy(key1, pwd, pwdLen); + memcpy(key1 + pwdLen, key, keyLen); + n = pwdLen + keyLen; + if (userKey) { + memcpy(key1 + pwdLen + keyLen, userKey, 48); + n += 48; + } + for (j = 1; j < 64; ++j) { + memcpy(key1 + j * n, key1, n); + } + n *= 64; + aesKeyExpansion(&state128, key, 16, gFalse); + for (j = 0; j < 16; ++j) { + state128.cbc[j] = key[16+j]; + } + for (j = 0; j < n; j += 16) { + aesEncryptBlock(&state128, key1 + j); + memcpy(key1 + j, state128.buf, 16); + } + k = 0; + for (j = 0; j < 16; ++j) { + k += key1[j] % 3; + } + k %= 3; + switch (k) { + case 0: + sha256(key1, n, key); + keyLen = 32; + break; + case 1: + sha384(key1, n, key); + keyLen = 48; + break; + case 2: + sha512(key1, n, key); + keyLen = 64; + break; + } + // from the spec, it appears that i should be incremented after + // the test, but that doesn't match what Adobe does + ++i; + if (i >= 64 && key1[n - 1] <= i - 32) { + break; + } + } +} + GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, GString *ownerKey, GString *userKey, int permissions, GString *fileID, @@ -305,8 +379,6 @@ DecryptStream::~DecryptStream() { } void DecryptStream::reset() { - int i; - str->reset(); switch (algo) { case cryptRC4: @@ -315,17 +387,13 @@ void DecryptStream::reset() { state.rc4.buf = EOF; break; case cryptAES: - aesKeyExpansion(&state.aes, objKey, objKeyLength); - for (i = 0; i < 16; ++i) { - state.aes.cbc[i] = str->getChar(); - } + aesKeyExpansion(&state.aes, objKey, objKeyLength, gTrue); + str->getBlock((char *)state.aes.cbc, 16); state.aes.bufIdx = 16; break; case cryptAES256: aes256KeyExpansion(&state.aes256, objKey, objKeyLength); - for (i = 0; i < 16; ++i) { - state.aes256.cbc[i] = str->getChar(); - } + str->getBlock((char *)state.aes256.cbc, 16); state.aes256.bufIdx = 16; break; } @@ -333,7 +401,7 @@ void DecryptStream::reset() { int DecryptStream::getChar() { Guchar in[16]; - int c, i; + int c; c = EOF; // make gcc happy switch (algo) { @@ -350,11 +418,8 @@ int DecryptStream::getChar() { break; case cryptAES: if (state.aes.bufIdx == 16) { - for (i = 0; i < 16; ++i) { - if ((c = str->getChar()) == EOF) { - return EOF; - } - in[i] = (Guchar)c; + if (str->getBlock((char *)in, 16) != 16) { + return EOF; } aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); } @@ -366,11 +431,8 @@ int DecryptStream::getChar() { break; case cryptAES256: if (state.aes256.bufIdx == 16) { - for (i = 0; i < 16; ++i) { - if ((c = str->getChar()) == EOF) { - return EOF; - } - in[i] = (Guchar)c; + if (str->getBlock((char *)in, 16) != 16) { + return EOF; } aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF); } @@ -386,7 +448,7 @@ int DecryptStream::getChar() { int DecryptStream::lookChar() { Guchar in[16]; - int c, i; + int c; c = EOF; // make gcc happy switch (algo) { @@ -402,11 +464,8 @@ int DecryptStream::lookChar() { break; case cryptAES: if (state.aes.bufIdx == 16) { - for (i = 0; i < 16; ++i) { - if ((c = str->getChar()) == EOF) { - return EOF; - } - in[i] = c; + if (str->getBlock((char *)in, 16) != 16) { + return EOF; } aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); } @@ -418,11 +477,8 @@ int DecryptStream::lookChar() { break; case cryptAES256: if (state.aes256.bufIdx == 16) { - for (i = 0; i < 16; ++i) { - if ((c = str->getChar()) == EOF) { - return EOF; - } - in[i] = c; + if (str->getBlock((char *)in, 16) != 16) { + return EOF; } aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF); } @@ -540,6 +596,14 @@ static inline Guint rotWord(Guint x) { return ((x << 8) & 0xffffffff) | (x >> 24); } +static inline void subBytes(Guchar *state) { + int i; + + for (i = 0; i < 16; ++i) { + state[i] = sbox[state[i]]; + } +} + static inline void invSubBytes(Guchar *state) { int i; @@ -548,6 +612,29 @@ static inline void invSubBytes(Guchar *state) { } } +static inline void shiftRows(Guchar *state) { + Guchar t; + + t = state[4]; + state[4] = state[5]; + state[5] = state[6]; + state[6] = state[7]; + state[7] = t; + + t = state[8]; + state[8] = state[10]; + state[10] = t; + t = state[9]; + state[9] = state[11]; + state[11] = t; + + t = state[15]; + state[15] = state[14]; + state[14] = state[13]; + state[13] = state[12]; + state[12] = t; +} + static inline void invShiftRows(Guchar *state) { Guchar t; @@ -571,6 +658,22 @@ static inline void invShiftRows(Guchar *state) { state[15] = t; } +// {02} \cdot s +static inline Guchar mul02(Guchar s) { + Guchar s2; + + s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); + return s2; +} + +// {03} \cdot s +static inline Guchar mul03(Guchar s) { + Guchar s2; + + s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); + return s ^ s2; +} + // {09} \cdot s static inline Guchar mul09(Guchar s) { Guchar s2, s4, s8; @@ -611,6 +714,22 @@ static inline Guchar mul0e(Guchar s) { return s2 ^ s4 ^ s8; } +static inline void mixColumns(Guchar *state) { + int c; + Guchar s0, s1, s2, s3; + + for (c = 0; c < 4; ++c) { + s0 = state[c]; + s1 = state[4+c]; + s2 = state[8+c]; + s3 = state[12+c]; + state[c] = mul02(s0) ^ mul03(s1) ^ s2 ^ s3; + state[4+c] = s0 ^ mul02(s1) ^ mul03(s2) ^ s3; + state[8+c] = s0 ^ s1 ^ mul02(s2) ^ mul03(s3); + state[12+c] = mul03(s0) ^ s1 ^ s2 ^ mul02(s3); + } +} + static inline void invMixColumns(Guchar *state) { int c; Guchar s0, s1, s2, s3; @@ -654,8 +773,9 @@ static inline void addRoundKey(Guchar *state, Guint *w) { } } -static void aesKeyExpansion(DecryptAESState *s, - Guchar *objKey, int objKeyLen) { +void aesKeyExpansion(DecryptAESState *s, + Guchar *objKey, int objKeyLen, + GBool decrypt) { Guint temp; int i, round; @@ -672,12 +792,50 @@ static void aesKeyExpansion(DecryptAESState *s, } s->w[i] = s->w[i-4] ^ temp; } + if (decrypt) { + for (round = 1; round <= 9; ++round) { + invMixColumnsW(&s->w[round * 4]); + } + } +} + +void aesEncryptBlock(DecryptAESState *s, Guchar *in) { + int c, round; + + // initial state + CBC + for (c = 0; c < 4; ++c) { + s->state[c] = in[4*c] ^ s->cbc[4*c]; + s->state[4+c] = in[4*c+1] ^ s->cbc[4*c+1]; + s->state[8+c] = in[4*c+2] ^ s->cbc[4*c+2]; + s->state[12+c] = in[4*c+3] ^ s->cbc[4*c+3]; + } + + // round 0 + addRoundKey(s->state, &s->w[0]); + + // rounds 1 .. 9 for (round = 1; round <= 9; ++round) { - invMixColumnsW(&s->w[round * 4]); + subBytes(s->state); + shiftRows(s->state); + mixColumns(s->state); + addRoundKey(s->state, &s->w[round * 4]); + } + + // round 10 + subBytes(s->state); + shiftRows(s->state); + addRoundKey(s->state, &s->w[10 * 4]); + + // output + save for next CBC + for (c = 0; c < 4; ++c) { + s->buf[4*c] = s->cbc[4*c] = s->state[c]; + s->buf[4*c+1] = s->cbc[4*c+1] = s->state[4+c]; + s->buf[4*c+2] = s->cbc[4*c+2] = s->state[8+c]; + s->buf[4*c+3] = s->cbc[4*c+3] = s->state[12+c]; } } -static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) { +void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) { int c, round, n, i; // initial state @@ -844,151 +1002,187 @@ static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d, return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); } -void md5(Guchar *msg, int msgLen, Guchar *digest) { +void md5Start(MD5State *state) { + state->a = 0x67452301; + state->b = 0xefcdab89; + state->c = 0x98badcfe; + state->d = 0x10325476; + state->bufLen = 0; + state->msgLen = 0; +} + +static void md5ProcessBlock(MD5State *state) { Gulong x[16]; - Gulong a, b, c, d, aa, bb, cc, dd; - int n64; - int i, j, k; + Gulong a, b, c, d; + int i; - // sanity check - if (msgLen < 0) { - return; + for (i = 0; i < 16; ++i) { + x[i] = state->buf[4*i] | (state->buf[4*i+1] << 8) | + (state->buf[4*i+2] << 16) | (state->buf[4*i+3] << 24); } - // compute number of 64-byte blocks - // (length + pad byte (0x80) + 8 bytes for length) - n64 = (msgLen + 1 + 8 + 63) / 64; - - // initialize a, b, c, d - a = 0x67452301; - b = 0xefcdab89; - c = 0x98badcfe; - d = 0x10325476; - - // loop through blocks - k = 0; - for (i = 0; i < n64; ++i) { - - // grab a 64-byte block - for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4) - x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k]; - if (i == n64 - 1) { - if (k == msgLen - 3) - x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k]; - else if (k == msgLen - 2) - x[j] = 0x800000 + (msg[k+1] << 8) + msg[k]; - else if (k == msgLen - 1) - x[j] = 0x8000 + msg[k]; - else - x[j] = 0x80; - ++j; - while (j < 16) - x[j++] = 0; - x[14] = msgLen << 3; - } + a = state->a; + b = state->b; + c = state->c; + d = state->d; + + // round 1 + a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); + d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); + c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); + b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); + a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); + d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); + c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); + b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); + a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); + d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); + c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); + b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); + a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); + d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); + c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); + b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); + + // round 2 + a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); + d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); + c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); + b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); + a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); + d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); + c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); + b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); + a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); + d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); + c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); + b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); + a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); + d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); + c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); + b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); + + // round 3 + a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); + d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); + c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); + b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); + a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); + d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); + c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); + b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); + a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); + d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); + c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); + b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); + a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); + d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); + c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); + b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); + + // round 4 + a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); + d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); + c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); + b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); + a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); + d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); + c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); + b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); + a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); + d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); + c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); + b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); + a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); + d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); + c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); + b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); + + // increment a, b, c, d + state->a += a; + state->b += b; + state->c += c; + state->d += d; + + state->bufLen = 0; +} - // save a, b, c, d - aa = a; - bb = b; - cc = c; - dd = d; - - // round 1 - a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); - d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); - c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); - b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); - a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); - d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); - c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); - b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); - a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); - d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); - c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); - b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); - a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); - d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); - c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); - b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); - - // round 2 - a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); - d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); - c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); - b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); - a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); - d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); - c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); - b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); - a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); - d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); - c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); - b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); - a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); - d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); - c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); - b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); - - // round 3 - a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); - d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); - c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); - b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); - a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); - d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); - c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); - b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); - a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); - d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); - c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); - b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); - a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); - d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); - c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); - b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); - - // round 4 - a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); - d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); - c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); - b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); - a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); - d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); - c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); - b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); - a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); - d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); - c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); - b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); - a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); - d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); - c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); - b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); - - // increment a, b, c, d - a += aa; - b += bb; - c += cc; - d += dd; +void md5Append(MD5State *state, Guchar *data, int dataLen) { + Guchar *p; + int remain, k; + + p = data; + remain = dataLen; + while (state->bufLen + remain >= 64) { + k = 64 - state->bufLen; + memcpy(state->buf + state->bufLen, p, k); + state->bufLen = 64; + md5ProcessBlock(state); + p += k; + remain -= k; } + if (remain > 0) { + memcpy(state->buf + state->bufLen, p, remain); + state->bufLen += remain; + } + state->msgLen += dataLen; +} + +void md5Finish(MD5State *state) { + // padding and length + state->buf[state->bufLen++] = 0x80; + if (state->bufLen > 56) { + while (state->bufLen < 64) { + state->buf[state->bufLen++] = 0x00; + } + md5ProcessBlock(state); + } + while (state->bufLen < 56) { + state->buf[state->bufLen++] = 0x00; + } + state->buf[56] = (Guchar)(state->msgLen << 3); + state->buf[57] = (Guchar)(state->msgLen >> 5); + state->buf[58] = (Guchar)(state->msgLen >> 13); + state->buf[59] = (Guchar)(state->msgLen >> 21); + state->buf[60] = (Guchar)(state->msgLen >> 29); + state->buf[61] = (Guchar)0; + state->buf[62] = (Guchar)0; + state->buf[63] = (Guchar)0; + state->bufLen = 64; + md5ProcessBlock(state); // break digest into bytes - digest[0] = (Guchar)(a & 0xff); - digest[1] = (Guchar)((a >>= 8) & 0xff); - digest[2] = (Guchar)((a >>= 8) & 0xff); - digest[3] = (Guchar)((a >>= 8) & 0xff); - digest[4] = (Guchar)(b & 0xff); - digest[5] = (Guchar)((b >>= 8) & 0xff); - digest[6] = (Guchar)((b >>= 8) & 0xff); - digest[7] = (Guchar)((b >>= 8) & 0xff); - digest[8] = (Guchar)(c & 0xff); - digest[9] = (Guchar)((c >>= 8) & 0xff); - digest[10] = (Guchar)((c >>= 8) & 0xff); - digest[11] = (Guchar)((c >>= 8) & 0xff); - digest[12] = (Guchar)(d & 0xff); - digest[13] = (Guchar)((d >>= 8) & 0xff); - digest[14] = (Guchar)((d >>= 8) & 0xff); - digest[15] = (Guchar)((d >>= 8) & 0xff); + state->digest[0] = (Guchar)state->a; + state->digest[1] = (Guchar)(state->a >> 8); + state->digest[2] = (Guchar)(state->a >> 16); + state->digest[3] = (Guchar)(state->a >> 24); + state->digest[4] = (Guchar)state->b; + state->digest[5] = (Guchar)(state->b >> 8); + state->digest[6] = (Guchar)(state->b >> 16); + state->digest[7] = (Guchar)(state->b >> 24); + state->digest[8] = (Guchar)state->c; + state->digest[9] = (Guchar)(state->c >> 8); + state->digest[10] = (Guchar)(state->c >> 16); + state->digest[11] = (Guchar)(state->c >> 24); + state->digest[12] = (Guchar)state->d; + state->digest[13] = (Guchar)(state->d >> 8); + state->digest[14] = (Guchar)(state->d >> 16); + state->digest[15] = (Guchar)(state->d >> 24); +} + +void md5(Guchar *msg, int msgLen, Guchar *digest) { + MD5State state; + int i; + + if (msgLen < 0) { + return; + } + md5Start(&state); + md5Append(&state, msg, msgLen); + md5Finish(&state); + for (i = 0; i < 16; ++i) { + digest[i] = state.digest[i]; + } } //------------------------------------------------------------------------ @@ -1042,7 +1236,7 @@ static inline Guint sha256sigma1(Guint x) { return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10); } -void sha256HashBlock(Guchar *blk, Guint *H) { +static void sha256HashBlock(Guchar *blk, Guint *H) { Guint W[64]; Guint a, b, c, d, e, f, g, h; Guint T1, T2; @@ -1147,3 +1341,270 @@ static void sha256(Guchar *msg, int msgLen, Guchar *hash) { hash[i*4 + 3] = (Guchar)H[i]; } } + +//------------------------------------------------------------------------ +// SHA-384 and SHA-512 hashes +//------------------------------------------------------------------------ + +typedef unsigned long long SHA512Uint64; + +static SHA512Uint64 sha512K[80] = { + 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL, + 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL, + 0x3956c25bf348b538LL, 0x59f111f1b605d019LL, + 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL, + 0xd807aa98a3030242LL, 0x12835b0145706fbeLL, + 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL, + 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL, + 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL, + 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL, + 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL, + 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL, + 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL, + 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL, + 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL, + 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL, + 0x06ca6351e003826fLL, 0x142929670a0e6e70LL, + 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL, + 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL, + 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL, + 0x81c2c92e47edaee6LL, 0x92722c851482353bLL, + 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL, + 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL, + 0xd192e819d6ef5218LL, 0xd69906245565a910LL, + 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL, + 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL, + 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL, + 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL, + 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL, + 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL, + 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL, + 0x90befffa23631e28LL, 0xa4506cebde82bde9LL, + 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL, + 0xca273eceea26619cLL, 0xd186b8c721c0c207LL, + 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL, + 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL, + 0x113f9804bef90daeLL, 0x1b710b35131c471bLL, + 0x28db77f523047d84LL, 0x32caab7b40c72493LL, + 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL, + 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL, + 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL +}; + +static inline SHA512Uint64 rotr64(SHA512Uint64 x, Guint n) { + return (x >> n) | (x << (64 - n)); +} + +static inline SHA512Uint64 sha512Ch(SHA512Uint64 x, SHA512Uint64 y, + SHA512Uint64 z) { + return (x & y) ^ (~x & z); +} + +static inline SHA512Uint64 sha512Maj(SHA512Uint64 x, SHA512Uint64 y, + SHA512Uint64 z) { + return (x & y) ^ (x & z) ^ (y & z); +} + +static inline SHA512Uint64 sha512Sigma0(SHA512Uint64 x) { + return rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39); +} + +static inline SHA512Uint64 sha512Sigma1(SHA512Uint64 x) { + return rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41); +} + +static inline SHA512Uint64 sha512sigma0(SHA512Uint64 x) { + return rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7); +} + +static inline SHA512Uint64 sha512sigma1(SHA512Uint64 x) { + return rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6); +} + +static void sha512HashBlock(Guchar *blk, SHA512Uint64 *H) { + SHA512Uint64 W[80]; + SHA512Uint64 a, b, c, d, e, f, g, h; + SHA512Uint64 T1, T2; + Guint t; + + // 1. prepare the message schedule + for (t = 0; t < 16; ++t) { + W[t] = ((SHA512Uint64)blk[t*8] << 56) | + ((SHA512Uint64)blk[t*8 + 1] << 48) | + ((SHA512Uint64)blk[t*8 + 2] << 40) | + ((SHA512Uint64)blk[t*8 + 3] << 32) | + ((SHA512Uint64)blk[t*8 + 4] << 24) | + ((SHA512Uint64)blk[t*8 + 5] << 16) | + ((SHA512Uint64)blk[t*8 + 6] << 8) | + (SHA512Uint64)blk[t*8 + 7]; + } + for (t = 16; t < 80; ++t) { + W[t] = sha512sigma1(W[t-2]) + W[t-7] + sha512sigma0(W[t-15]) + W[t-16]; + } + + // 2. initialize the eight working variables + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + f = H[5]; + g = H[6]; + h = H[7]; + + // 3. + for (t = 0; t < 80; ++t) { + T1 = h + sha512Sigma1(e) + sha512Ch(e,f,g) + sha512K[t] + W[t]; + T2 = sha512Sigma0(a) + sha512Maj(a,b,c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + // 4. compute the intermediate hash value + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + H[4] += e; + H[5] += f; + H[6] += g; + H[7] += h; +} + +static void sha512(Guchar *msg, int msgLen, Guchar *hash) { + Guchar blk[128]; + SHA512Uint64 H[8]; + int blkLen, i; + + H[0] = 0x6a09e667f3bcc908LL; + H[1] = 0xbb67ae8584caa73bLL; + H[2] = 0x3c6ef372fe94f82bLL; + H[3] = 0xa54ff53a5f1d36f1LL; + H[4] = 0x510e527fade682d1LL; + H[5] = 0x9b05688c2b3e6c1fLL; + H[6] = 0x1f83d9abfb41bd6bLL; + H[7] = 0x5be0cd19137e2179LL; + + blkLen = 0; + for (i = 0; i + 128 <= msgLen; i += 128) { + sha512HashBlock(msg + i, H); + } + blkLen = msgLen - i; + if (blkLen > 0) { + memcpy(blk, msg + i, blkLen); + } + + // pad the message + blk[blkLen++] = 0x80; + if (blkLen > 112) { + while (blkLen < 128) { + blk[blkLen++] = 0; + } + sha512HashBlock(blk, H); + blkLen = 0; + } + while (blkLen < 112) { + blk[blkLen++] = 0; + } + blk[112] = 0; + blk[113] = 0; + blk[114] = 0; + blk[115] = 0; + blk[116] = 0; + blk[117] = 0; + blk[118] = 0; + blk[119] = 0; + blk[120] = 0; + blk[121] = 0; + blk[122] = 0; + blk[123] = 0; + blk[124] = (Guchar)(msgLen >> 21); + blk[125] = (Guchar)(msgLen >> 13); + blk[126] = (Guchar)(msgLen >> 5); + blk[127] = (Guchar)(msgLen << 3); + sha512HashBlock(blk, H); + + // copy the output into the buffer (convert words to bytes) + for (i = 0; i < 8; ++i) { + hash[i*8] = (Guchar)(H[i] >> 56); + hash[i*8 + 1] = (Guchar)(H[i] >> 48); + hash[i*8 + 2] = (Guchar)(H[i] >> 40); + hash[i*8 + 3] = (Guchar)(H[i] >> 32); + hash[i*8 + 4] = (Guchar)(H[i] >> 24); + hash[i*8 + 5] = (Guchar)(H[i] >> 16); + hash[i*8 + 6] = (Guchar)(H[i] >> 8); + hash[i*8 + 7] = (Guchar)H[i]; + } +} + +static void sha384(Guchar *msg, int msgLen, Guchar *hash) { + Guchar blk[128]; + SHA512Uint64 H[8]; + int blkLen, i; + + H[0] = 0xcbbb9d5dc1059ed8LL; + H[1] = 0x629a292a367cd507LL; + H[2] = 0x9159015a3070dd17LL; + H[3] = 0x152fecd8f70e5939LL; + H[4] = 0x67332667ffc00b31LL; + H[5] = 0x8eb44a8768581511LL; + H[6] = 0xdb0c2e0d64f98fa7LL; + H[7] = 0x47b5481dbefa4fa4LL; + + blkLen = 0; + for (i = 0; i + 128 <= msgLen; i += 128) { + sha512HashBlock(msg + i, H); + } + blkLen = msgLen - i; + if (blkLen > 0) { + memcpy(blk, msg + i, blkLen); + } + + // pad the message + blk[blkLen++] = 0x80; + if (blkLen > 112) { + while (blkLen < 128) { + blk[blkLen++] = 0; + } + sha512HashBlock(blk, H); + blkLen = 0; + } + while (blkLen < 112) { + blk[blkLen++] = 0; + } + blk[112] = 0; + blk[113] = 0; + blk[114] = 0; + blk[115] = 0; + blk[116] = 0; + blk[117] = 0; + blk[118] = 0; + blk[119] = 0; + blk[120] = 0; + blk[121] = 0; + blk[122] = 0; + blk[123] = 0; + blk[124] = (Guchar)(msgLen >> 21); + blk[125] = (Guchar)(msgLen >> 13); + blk[126] = (Guchar)(msgLen >> 5); + blk[127] = (Guchar)(msgLen << 3); + sha512HashBlock(blk, H); + + // copy the output into the buffer (convert words to bytes) + for (i = 0; i < 6; ++i) { + hash[i*8] = (Guchar)(H[i] >> 56); + hash[i*8 + 1] = (Guchar)(H[i] >> 48); + hash[i*8 + 2] = (Guchar)(H[i] >> 40); + hash[i*8 + 3] = (Guchar)(H[i] >> 32); + hash[i*8 + 4] = (Guchar)(H[i] >> 24); + hash[i*8 + 5] = (Guchar)(H[i] >> 16); + hash[i*8 + 6] = (Guchar)(H[i] >> 8); + hash[i*8 + 7] = (Guchar)H[i]; + } +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Decrypt.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Decrypt.h index 156acecb520..5ddcfc8ad7b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Decrypt.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Decrypt.h @@ -42,6 +42,8 @@ public: private: + static void r6Hash(Guchar *key, int keyLen, const char *pwd, int pwdLen, + char *userKey); static GBool makeFileKey2(int encVersion, int encRevision, int keyLength, GString *ownerKey, GString *userKey, int permissions, GString *fileID, @@ -104,8 +106,24 @@ private: //------------------------------------------------------------------------ +struct MD5State { + Gulong a, b, c, d; + Guchar buf[64]; + int bufLen; + int msgLen; + Guchar digest[16]; +}; + extern void rc4InitKey(Guchar *key, int keyLen, Guchar *state); extern Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); +void md5Start(MD5State *state); +void md5Append(MD5State *state, Guchar *data, int dataLen); +void md5Finish(MD5State *state); extern void md5(Guchar *msg, int msgLen, Guchar *digest); +extern void aesKeyExpansion(DecryptAESState *s, + Guchar *objKey, int objKeyLen, + GBool decrypt); +extern void aesEncryptBlock(DecryptAESState *s, Guchar *in); +extern void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last); #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Dict.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Dict.cc index 3ef804bcb73..7e33fff1921 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Dict.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Dict.cc @@ -20,13 +20,24 @@ #include "Dict.h" //------------------------------------------------------------------------ + +struct DictEntry { + char *key; + Object val; + DictEntry *next; +}; + +//------------------------------------------------------------------------ // Dict //------------------------------------------------------------------------ Dict::Dict(XRef *xrefA) { xref = xrefA; - entries = NULL; - size = length = 0; + size = 8; + length = 0; + entries = (DictEntry *)gmallocn(size, sizeof(DictEntry)); + hashTab = (DictEntry **)gmallocn(2 * size - 1, sizeof(DictEntry *)); + memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); ref = 1; } @@ -38,32 +49,69 @@ Dict::~Dict() { entries[i].val.free(); } gfree(entries); + gfree(hashTab); } void Dict::add(char *key, Object *val) { - if (length == size) { - if (length == 0) { - size = 8; - } else { - size *= 2; + DictEntry *e; + int h; + + if ((e = find(key))) { + e->val.free(); + e->val = *val; + gfree(key); + } else { + if (length == size) { + expand(); } - entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); + h = hash(key); + entries[length].key = key; + entries[length].val = *val; + entries[length].next = hashTab[h]; + hashTab[h] = &entries[length]; + ++length; } - entries[length].key = key; - entries[length].val = *val; - ++length; } -inline DictEntry *Dict::find(const char *key) { - int i; +void Dict::expand() { + int h, i; + size *= 2; + entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); + hashTab = (DictEntry **)greallocn(hashTab, 2 * size - 1, + sizeof(DictEntry *)); + memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); for (i = 0; i < length; ++i) { - if (!strcmp(key, entries[i].key)) - return &entries[i]; + h = hash(entries[i].key); + entries[i].next = hashTab[h]; + hashTab[h] = &entries[i]; + } +} + +inline DictEntry *Dict::find(const char *key) { + DictEntry *e; + int h; + + h = hash(key); + for (e = hashTab[h]; e; e = e->next) { + if (!strcmp(key, e->key)) { + return e; + } } return NULL; } +int Dict::hash(const char *key) { + const char *p; + unsigned int h; + + h = 0; + for (p = key; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % (2 * size - 1)); +} + GBool Dict::is(const char *type) { DictEntry *e; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Dict.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Dict.h index 1f3f8b53901..301d0b860d3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Dict.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Dict.h @@ -17,15 +17,12 @@ #include "Object.h" +struct DictEntry; + //------------------------------------------------------------------------ // Dict //------------------------------------------------------------------------ -struct DictEntry { - char *key; - Object val; -}; - class Dict { public: @@ -67,11 +64,14 @@ private: XRef *xref; // the xref table for this PDF file DictEntry *entries; // array of entries + DictEntry **hashTab; // hash table pointers int size; // size of <entries> array int length; // number of entries in dictionary int ref; // reference count DictEntry *find(const char *key); + void expand(); + int hash(const char *key); }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Error.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Error.cc index cb4f27c2833..600442e0091 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Error.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Error.cc @@ -2,7 +2,7 @@ // // Error.cc // -// Copyright 1996-2003 Glyph & Cog, LLC +// Copyright 1996-2013 Glyph & Cog, LLC // //======================================================================== @@ -41,9 +41,12 @@ void setErrorCallback(void (*cbk)(void *data, ErrorCategory category, errorCbkData = data; } -void CDECL error(ErrorCategory category, int pos, const char *msg, ...) { +void CDECL error(ErrorCategory category, GFileOffset pos, + const char *msg, ...) { va_list args; - GString *s; + GString *s, *sanitized; + char c; + int i; // NB: this can be called before the globalParams object is created if (!errorCbk && globalParams && globalParams->getErrQuiet()) { @@ -52,17 +55,32 @@ void CDECL error(ErrorCategory category, int pos, const char *msg, ...) { va_start(args, msg); s = GString::formatv(msg, args); va_end(args); + + // remove non-printable characters, just in case they might cause + // problems for the terminal program + sanitized = new GString(); + for (i = 0; i < s->getLength(); ++i) { + c = s->getChar(i); + if (c >= 0x20 && c <= 0x7e) { + sanitized->append(c); + } else { + sanitized->appendf("<{0:02x}>", c & 0xff); + } + } + if (errorCbk) { - (*errorCbk)(errorCbkData, category, pos, s->getCString()); + (*errorCbk)(errorCbkData, category, (int)pos, sanitized->getCString()); } else { if (pos >= 0) { fprintf(stderr, "%s (%d): %s\n", - errorCategoryNames[category], pos, s->getCString()); + errorCategoryNames[category], (int)pos, sanitized->getCString()); } else { fprintf(stderr, "%s: %s\n", - errorCategoryNames[category], s->getCString()); + errorCategoryNames[category], sanitized->getCString()); } fflush(stderr); } + delete s; + delete sanitized; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Error.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Error.h index a4ae5c9c121..6c6afe33f36 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Error.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Error.h @@ -17,11 +17,12 @@ #include <stdio.h> #include "config.h" +#include "gfile.h" enum ErrorCategory { errSyntaxWarning, // PDF syntax error which can be worked around; // output will probably be correct - errSyntaxError, // PDF syntax error which can be worked around; + errSyntaxError, // PDF syntax error which cannot be worked around; // output will probably be incorrect errConfig, // error in Xpdf config info (xpdfrc file, etc.) errCommandLine, // error in user-supplied parameters, action not @@ -37,6 +38,7 @@ extern void setErrorCallback(void (*cbk)(void *data, ErrorCategory category, int pos, char *msg), void *data); -extern void CDECL error(ErrorCategory category, int pos, const char *msg, ...); +extern void CDECL error(ErrorCategory category, GFileOffset pos, + const char *msg, ...); #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/ErrorCodes.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/ErrorCodes.h index b28528df564..b28528df564 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/ErrorCodes.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/ErrorCodes.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/FontEncodingTables.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/FontEncodingTables.cc index bf04b5b190f..bf04b5b190f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/FontEncodingTables.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/FontEncodingTables.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/FontEncodingTables.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/FontEncodingTables.h index a417b324e48..a417b324e48 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/FontEncodingTables.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/FontEncodingTables.h diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.cc new file mode 100644 index 00000000000..f65a1e27541 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.cc @@ -0,0 +1,67 @@ +//======================================================================== +// +// Form.cc +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "GlobalParams.h" +#include "Error.h" +#include "Object.h" +#include "PDFDoc.h" +#include "AcroForm.h" +#include "XFAForm.h" +#include "Form.h" + +//------------------------------------------------------------------------ +// Form +//------------------------------------------------------------------------ + +Form *Form::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObj) { + Form *form; + Object xfaObj, catDict, needsRenderingObj; + + if (!acroFormObj->isDict()) { + error(errSyntaxError, -1, "AcroForm object is wrong type"); + return NULL; + } + //~ temporary: create an XFAForm only for XFAF, not for dynamic XFA + acroFormObj->dictLookup("XFA", &xfaObj); + docA->getXRef()->getCatalog(&catDict); + catDict.dictLookup("NeedsRendering", &needsRenderingObj); + catDict.free(); + if (globalParams->getEnableXFA() && + !xfaObj.isNull() && + !(needsRenderingObj.isBool() && needsRenderingObj.getBool())) { + form = XFAForm::load(docA, acroFormObj, &xfaObj); + } else { + form = AcroForm::load(docA, catalog, acroFormObj); + } + xfaObj.free(); + needsRenderingObj.free(); + return form; +} + +Form::Form(PDFDoc *docA) { + doc = docA; +} + +Form::~Form() { +} + +//------------------------------------------------------------------------ +// FormField +//------------------------------------------------------------------------ + +FormField::FormField() { +} + +FormField::~FormField() { +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.h new file mode 100644 index 00000000000..50c0f478a51 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Form.h @@ -0,0 +1,64 @@ +//======================================================================== +// +// Form.h +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FORM_H +#define FORM_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class Gfx; +class FormField; + +//------------------------------------------------------------------------ + +class Form { +public: + + static Form *load(PDFDoc *docA, Catalog *catalog, Object *acroFormObj); + + virtual ~Form(); + + virtual const char *getType() = 0; + + virtual void draw(int pageNum, Gfx *gfx, GBool printing) = 0; + + virtual int getNumFields() = 0; + virtual FormField *getField(int idx) = 0; + +protected: + + Form(PDFDoc *docA); + + PDFDoc *doc; +}; + +//------------------------------------------------------------------------ + +class FormField { +public: + + FormField(); + virtual ~FormField(); + + virtual const char *getType() = 0; + virtual Unicode *getName(int *length) = 0; + virtual Unicode *getValue(int *length) = 0; + + // Return the resource dictionaries used to draw this field. The + // returned object must be either a dictionary or an array of + // dictonaries. + virtual Object *getResources(Object *res) = 0; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Function.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Function.cc index 2659af1c446..a06d10dab71 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Function.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Function.cc @@ -17,6 +17,7 @@ #include <ctype.h> #include <math.h> #include "gmem.h" +#include "GList.h" #include "Object.h" #include "Dict.h" #include "Stream.h" @@ -350,7 +351,7 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) { samples = (double *)gmallocn(nSamples, sizeof(double)); buf = 0; bits = 0; - bitMask = (1 << sampleBits) - 1; + bitMask = (sampleBits < 32) ? ((1 << sampleBits) - 1) : 0xffffffffU; str->reset(); for (i = 0; i < nSamples; ++i) { if (sampleBits == 8) { @@ -778,55 +779,57 @@ void StitchingFunction::transform(double *in, double *out) { // PostScriptFunction //------------------------------------------------------------------------ -enum PSOp { - psOpAbs, - psOpAdd, - psOpAnd, - psOpAtan, - psOpBitshift, - psOpCeiling, - psOpCopy, - psOpCos, - psOpCvi, - psOpCvr, - psOpDiv, - psOpDup, - psOpEq, - psOpExch, - psOpExp, - psOpFalse, - psOpFloor, - psOpGe, - psOpGt, - psOpIdiv, - psOpIndex, - psOpLe, - psOpLn, - psOpLog, - psOpLt, - psOpMod, - psOpMul, - psOpNe, - psOpNeg, - psOpNot, - psOpOr, - psOpPop, - psOpRoll, - psOpRound, - psOpSin, - psOpSqrt, - psOpSub, - psOpTrue, - psOpTruncate, - psOpXor, - psOpIf, - psOpIfelse, - psOpReturn -}; +// This is not an enum, because we can't foreward-declare the enum +// type in Function.h +#define psOpAbs 0 +#define psOpAdd 1 +#define psOpAnd 2 +#define psOpAtan 3 +#define psOpBitshift 4 +#define psOpCeiling 5 +#define psOpCopy 6 +#define psOpCos 7 +#define psOpCvi 8 +#define psOpCvr 9 +#define psOpDiv 10 +#define psOpDup 11 +#define psOpEq 12 +#define psOpExch 13 +#define psOpExp 14 +#define psOpFalse 15 +#define psOpFloor 16 +#define psOpGe 17 +#define psOpGt 18 +#define psOpIdiv 19 +#define psOpIndex 20 +#define psOpLe 21 +#define psOpLn 22 +#define psOpLog 23 +#define psOpLt 24 +#define psOpMod 25 +#define psOpMul 26 +#define psOpNe 27 +#define psOpNeg 28 +#define psOpNot 29 +#define psOpOr 30 +#define psOpPop 31 +#define psOpRoll 32 +#define psOpRound 33 +#define psOpSin 34 +#define psOpSqrt 35 +#define psOpSub 36 +#define psOpTrue 37 +#define psOpTruncate 38 +#define psOpXor 39 +#define psOpPush 40 +#define psOpJ 41 +#define psOpJz 42 + +#define nPSOps 43 // Note: 'if' and 'ifelse' are parsed separately. // The rest are listed here in alphabetical order. -// The index in this table is equivalent to the entry in PSOp. +// The index in this table is equivalent to the psOpXXX defines. static const char *psOpNames[] = { "abs", "add", @@ -870,218 +873,22 @@ static const char *psOpNames[] = { "xor" }; -#define nPSOps (sizeof(psOpNames) / sizeof(char *)) - -enum PSObjectType { - psBool, - psInt, - psReal, - psOperator, - psBlock -}; - -// In the code array, 'if'/'ifelse' operators take up three slots -// plus space for the code in the subclause(s). -// -// +---------------------------------+ -// | psOperator: psOpIf / psOpIfelse | -// +---------------------------------+ -// | psBlock: ptr=<A> | -// +---------------------------------+ -// | psBlock: ptr=<B> | -// +---------------------------------+ -// | if clause | -// | ... | -// | psOperator: psOpReturn | -// +---------------------------------+ -// <A> | else clause | -// | ... | -// | psOperator: psOpReturn | -// +---------------------------------+ -// <B> | ... | -// -// For 'if', pointer <A> is present in the code stream but unused. - -struct PSObject { - PSObjectType type; +struct PSCode { + int op; union { - GBool booln; // boolean (stack only) - int intg; // integer (stack and code) - double real; // real (stack and code) - PSOp op; // operator (code only) - int blk; // if/ifelse block pointer (code only) - }; + double d; + int i; + } val; }; #define psStackSize 100 -class PSStack { -public: - - PSStack() { sp = psStackSize; } - void pushBool(GBool booln); - void pushInt(int intg); - void pushReal(double real); - GBool popBool(); - int popInt(); - double popNum(); - GBool empty() { return sp == psStackSize; } - GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; } - GBool topTwoAreInts() - { return sp < psStackSize - 1 && - stack[sp].type == psInt && - stack[sp+1].type == psInt; } - GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; } - GBool topTwoAreNums() - { return sp < psStackSize - 1 && - (stack[sp].type == psInt || stack[sp].type == psReal) && - (stack[sp+1].type == psInt || stack[sp+1].type == psReal); } - void copy(int n); - void roll(int n, int j); - void index(int i); - void pop(); - -private: - - GBool checkOverflow(int n = 1); - GBool checkUnderflow(); - GBool checkType(PSObjectType t1, PSObjectType t2); - - PSObject stack[psStackSize]; - int sp; -}; - -GBool PSStack::checkOverflow(int n) { - if (sp - n < 0) { - error(errSyntaxError, -1, "Stack overflow in PostScript function"); - return gFalse; - } - return gTrue; -} - -GBool PSStack::checkUnderflow() { - if (sp == psStackSize) { - error(errSyntaxError, -1, "Stack underflow in PostScript function"); - return gFalse; - } - return gTrue; -} - -GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) { - if (stack[sp].type != t1 && stack[sp].type != t2) { - error(errSyntaxError, -1, "Type mismatch in PostScript function"); - return gFalse; - } - return gTrue; -} - -void PSStack::pushBool(GBool booln) { - if (checkOverflow()) { - stack[--sp].type = psBool; - stack[sp].booln = booln; - } -} - -void PSStack::pushInt(int intg) { - if (checkOverflow()) { - stack[--sp].type = psInt; - stack[sp].intg = intg; - } -} - -void PSStack::pushReal(double real) { - if (checkOverflow()) { - stack[--sp].type = psReal; - stack[sp].real = real; - } -} - -GBool PSStack::popBool() { - if (checkUnderflow() && checkType(psBool, psBool)) { - return stack[sp++].booln; - } - return gFalse; -} - -int PSStack::popInt() { - if (checkUnderflow() && checkType(psInt, psInt)) { - return stack[sp++].intg; - } - return 0; -} - -double PSStack::popNum() { - double ret; - - if (checkUnderflow() && checkType(psInt, psReal)) { - ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real; - ++sp; - return ret; - } - return 0; -} - -void PSStack::copy(int n) { - int i; - - if (sp + n > psStackSize) { - error(errSyntaxError, -1, "Stack underflow in PostScript function"); - return; - } - if (!checkOverflow(n)) { - return; - } - for (i = sp + n - 1; i >= sp; --i) { - stack[i - n] = stack[i]; - } - sp -= n; -} - -void PSStack::roll(int n, int j) { - PSObject obj; - int i, k; - - if (j >= 0) { - j %= n; - } else { - j = -j % n; - if (j != 0) { - j = n - j; - } - } - if (n <= 0 || j == 0 || n > psStackSize || sp + n > psStackSize) { - return; - } - for (i = 0; i < j; ++i) { - obj = stack[sp]; - for (k = sp; k < sp + n - 1; ++k) { - stack[k] = stack[k+1]; - } - stack[sp + n - 1] = obj; - } -} - -void PSStack::index(int i) { - if (!checkOverflow()) { - return; - } - --sp; - stack[sp] = stack[sp + 1 + i]; -} - -void PSStack::pop() { - if (!checkUnderflow()) { - return; - } - ++sp; -} - PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { Stream *str; - int codePtr; + GList *tokens; GString *tok; double in[funcMaxInputs]; - int i; + int tokPtr, codePtr, i; codeString = NULL; code = NULL; @@ -1104,22 +911,27 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { } str = funcObj->getStream(); - //----- parse the function + //----- tokenize the function codeString = new GString(); + tokens = new GList(); str->reset(); - if (!(tok = getToken(str)) || tok->cmp("{")) { + while ((tok = getToken(str))) { + tokens->append(tok); + } + str->close(); + + //----- parse the function + if (tokens->getLength() < 1 || + ((GString *)tokens->get(0))->cmp("{")) { error(errSyntaxError, -1, "Expected '{' at start of PostScript function"); - if (tok) { - delete tok; - } - goto err1; + goto err2; } - delete tok; + tokPtr = 1; codePtr = 0; - if (!parseCode(str, &codePtr)) { + if (!parseCode(tokens, &tokPtr, &codePtr)) { goto err2; } - str->close(); + codeLen = codePtr; //----- set up the cache for (i = 0; i < m; ++i) { @@ -1131,16 +943,16 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { ok = gTrue; err2: - str->close(); + deleteGList(tokens, GString); err1: return; } PostScriptFunction::PostScriptFunction(PostScriptFunction *func) { memcpy(this, func, sizeof(PostScriptFunction)); - code = (PSObject *)gmallocn(codeSize, sizeof(PSObject)); - memcpy(code, func->code, codeSize * sizeof(PSObject)); codeString = func->codeString->copy(); + code = (PSCode *)gmallocn(codeSize, sizeof(PSCode)); + memcpy(code, func->code, codeSize * sizeof(PSCode)); } PostScriptFunction::~PostScriptFunction() { @@ -1151,8 +963,9 @@ PostScriptFunction::~PostScriptFunction() { } void PostScriptFunction::transform(double *in, double *out) { - PSStack *stack; - int i; + double stack[psStackSize]; + double x; + int sp, i; // check the cache for (i = 0; i < m; ++i) { @@ -1167,25 +980,28 @@ void PostScriptFunction::transform(double *in, double *out) { return; } - stack = new PSStack(); for (i = 0; i < m; ++i) { - //~ may need to check for integers here - stack->pushReal(in[i]); + stack[psStackSize - 1 - i] = in[i]; } - exec(stack, 0); - for (i = n - 1; i >= 0; --i) { - out[i] = stack->popNum(); - if (out[i] < range[i][0]) { + sp = exec(stack, psStackSize - m); + // if (sp < psStackSize - n) { + // error(errSyntaxWarning, -1, + // "Extra values on stack at end of PostScript function"); + // } + if (sp > psStackSize - n) { + error(errSyntaxError, -1, "Stack underflow in PostScript function"); + sp = psStackSize - n; + } + for (i = 0; i < n; ++i) { + x = stack[sp + n - 1 - i]; + if (x < range[i][0]) { out[i] = range[i][0]; - } else if (out[i] > range[i][1]) { + } else if (x > range[i][1]) { out[i] = range[i][1]; + } else { + out[i] = x; } } - // if (!stack->empty()) { - // error(errSyntaxWarning, -1, - // "Extra values on stack at end of PostScript function"); - // } - delete stack; // save current result in the cache for (i = 0; i < m; ++i) { @@ -1196,101 +1012,71 @@ void PostScriptFunction::transform(double *in, double *out) { } } -GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) { +GBool PostScriptFunction::parseCode(GList *tokens, int *tokPtr, int *codePtr) { GString *tok; char *p; - GBool isReal; - int opPtr, elsePtr; int a, b, mid, cmp; + int codePtr0, codePtr1; while (1) { - if (!(tok = getToken(str))) { + if (*tokPtr >= tokens->getLength()) { error(errSyntaxError, -1, "Unexpected end of PostScript function stream"); return gFalse; } + tok = (GString *)tokens->get((*tokPtr)++); p = tok->getCString(); if (isdigit(*p) || *p == '.' || *p == '-') { - isReal = gFalse; - for (; *p; ++p) { - if (*p == '.') { - isReal = gTrue; - break; - } - } - resizeCode(*codePtr); - if (isReal) { - code[*codePtr].type = psReal; - code[*codePtr].real = atof(tok->getCString()); - } else { - code[*codePtr].type = psInt; - code[*codePtr].intg = atoi(tok->getCString()); - } - ++*codePtr; - delete tok; + addCodeD(codePtr, psOpPush, atof(tok->getCString())); } else if (!tok->cmp("{")) { - delete tok; - opPtr = *codePtr; - *codePtr += 3; - resizeCode(opPtr + 2); - if (!parseCode(str, codePtr)) { + codePtr0 = *codePtr; + addCodeI(codePtr, psOpJz, 0); + if (!parseCode(tokens, tokPtr, codePtr)) { return gFalse; } - if (!(tok = getToken(str))) { + if (*tokPtr >= tokens->getLength()) { error(errSyntaxError, -1, "Unexpected end of PostScript function stream"); return gFalse; } - if (!tok->cmp("{")) { - elsePtr = *codePtr; - if (!parseCode(str, codePtr)) { + tok = (GString *)tokens->get((*tokPtr)++); + if (!tok->cmp("if")) { + code[codePtr0].val.i = *codePtr; + } else if (!tok->cmp("{")) { + codePtr1 = *codePtr; + addCodeI(codePtr, psOpJ, 0); + code[codePtr0].val.i = *codePtr; + if (!parseCode(tokens, tokPtr, codePtr)) { return gFalse; } - delete tok; - if (!(tok = getToken(str))) { + if (*tokPtr >= tokens->getLength()) { error(errSyntaxError, -1, "Unexpected end of PostScript function stream"); return gFalse; } - } else { - elsePtr = -1; - } - if (!tok->cmp("if")) { - if (elsePtr >= 0) { - error(errSyntaxError, -1, - "Got 'if' operator with two blocks in PostScript function"); - return gFalse; - } - code[opPtr].type = psOperator; - code[opPtr].op = psOpIf; - code[opPtr+2].type = psBlock; - code[opPtr+2].blk = *codePtr; - } else if (!tok->cmp("ifelse")) { - if (elsePtr < 0) { + tok = (GString *)tokens->get((*tokPtr)++); + if (!tok->cmp("ifelse")) { + code[codePtr1].val.i = *codePtr; + } else { error(errSyntaxError, -1, - "Got 'ifelse' operator with one block in PostScript function"); + "Expected 'ifelse' in PostScript function stream"); return gFalse; } - code[opPtr].type = psOperator; - code[opPtr].op = psOpIfelse; - code[opPtr+1].type = psBlock; - code[opPtr+1].blk = elsePtr; - code[opPtr+2].type = psBlock; - code[opPtr+2].blk = *codePtr; } else { error(errSyntaxError, -1, - "Expected if/ifelse operator in PostScript function"); - delete tok; + "Expected 'if' in PostScript function stream"); return gFalse; } - delete tok; } else if (!tok->cmp("}")) { - delete tok; - resizeCode(*codePtr); - code[*codePtr].type = psOperator; - code[*codePtr].op = psOpReturn; - ++*codePtr; break; + } else if (!tok->cmp("if")) { + error(errSyntaxError, -1, + "Unexpected 'if' in PostScript function stream"); + return gFalse; + } else if (!tok->cmp("ifelse")) { + error(errSyntaxError, -1, + "Unexpected 'ifelse' in PostScript function stream"); + return gFalse; } else { a = -1; b = nPSOps; @@ -1311,19 +1097,55 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) { error(errSyntaxError, -1, "Unknown operator '{0:t}' in PostScript function", tok); - delete tok; return gFalse; } - delete tok; - resizeCode(*codePtr); - code[*codePtr].type = psOperator; - code[*codePtr].op = (PSOp)a; - ++*codePtr; + addCode(codePtr, a); } } return gTrue; } +void PostScriptFunction::addCode(int *codePtr, int op) { + if (*codePtr >= codeSize) { + if (codeSize) { + codeSize *= 2; + } else { + codeSize = 16; + } + code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode)); + } + code[*codePtr].op = op; + ++(*codePtr); +} + +void PostScriptFunction::addCodeI(int *codePtr, int op, int x) { + if (*codePtr >= codeSize) { + if (codeSize) { + codeSize *= 2; + } else { + codeSize = 16; + } + code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode)); + } + code[*codePtr].op = op; + code[*codePtr].val.i = x; + ++(*codePtr); +} + +void PostScriptFunction::addCodeD(int *codePtr, int op, double x) { + if (*codePtr >= codeSize) { + if (codeSize) { + codeSize *= 2; + } else { + codeSize = 16; + } + code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode)); + } + code[*codePtr].op = op; + code[*codePtr].val.d = x; + ++(*codePtr); +} + GString *PostScriptFunction::getToken(Stream *str) { GString *s; int c; @@ -1333,7 +1155,8 @@ GString *PostScriptFunction::getToken(Stream *str) { comment = gFalse; while (1) { if ((c = str->getChar()) == EOF) { - break; + delete s; + return NULL; } codeString->append(c); if (comment) { @@ -1372,323 +1195,362 @@ GString *PostScriptFunction::getToken(Stream *str) { return s; } -void PostScriptFunction::resizeCode(int newSize) { - if (newSize >= codeSize) { - codeSize += 64; - code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject)); - } -} - -void PostScriptFunction::exec(PSStack *stack, int codePtr) { - int i1, i2; - double r1, r2; - GBool b1, b2; - - while (1) { - switch (code[codePtr].type) { - case psInt: - stack->pushInt(code[codePtr++].intg); +int PostScriptFunction::exec(double *stack, int sp0) { + PSCode *c; + double tmp[psStackSize]; + double t; + int sp, ip, nn, k, i; + + sp = sp0; + ip = 0; + while (ip < codeLen) { + c = &code[ip++]; + switch(c->op) { + case psOpAbs: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = fabs(stack[sp]); break; - case psReal: - stack->pushReal(code[codePtr++].real); + case psOpAdd: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] + stack[sp]; + ++sp; break; - case psOperator: - switch (code[codePtr++].op) { - case psOpAbs: - if (stack->topIsInt()) { - stack->pushInt(abs(stack->popInt())); - } else { - stack->pushReal(fabs(stack->popNum())); - } - break; - case psOpAdd: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 + i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 + r2); - } - break; - case psOpAnd: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 & i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 && b2); - } - break; - case psOpAtan: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(atan2(r1, r2)); - break; - case psOpBitshift: - i2 = stack->popInt(); - i1 = stack->popInt(); - if (i2 > 0) { - stack->pushInt(i1 << i2); - } else if (i2 < 0) { - stack->pushInt((int)((Guint)i1 >> -i2)); - } else { - stack->pushInt(i1); - } - break; - case psOpCeiling: - if (!stack->topIsInt()) { - stack->pushReal(ceil(stack->popNum())); - } - break; - case psOpCopy: - stack->copy(stack->popInt()); - break; - case psOpCos: - stack->pushReal(cos(stack->popNum())); - break; - case psOpCvi: - if (!stack->topIsInt()) { - stack->pushInt((int)stack->popNum()); - } - break; - case psOpCvr: - if (!stack->topIsReal()) { - stack->pushReal(stack->popNum()); - } - break; - case psOpDiv: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 / r2); - break; - case psOpDup: - stack->copy(1); - break; - case psOpEq: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 == i2); - } else if (stack->topTwoAreNums()) { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 == r2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 == b2); - } - break; - case psOpExch: - stack->roll(2, 1); - break; - case psOpExp: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(pow(r1, r2)); - break; - case psOpFalse: - stack->pushBool(gFalse); - break; - case psOpFloor: - if (!stack->topIsInt()) { - stack->pushReal(floor(stack->popNum())); - } - break; - case psOpGe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 >= i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 >= r2); - } - break; - case psOpGt: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 > i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 > r2); - } - break; - case psOpIdiv: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 / i2); - break; - case psOpIndex: - stack->index(stack->popInt()); - break; - case psOpLe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 <= i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 <= r2); - } - break; - case psOpLn: - stack->pushReal(log(stack->popNum())); - break; - case psOpLog: - stack->pushReal(log10(stack->popNum())); - break; - case psOpLt: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 < i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 < r2); - } - break; - case psOpMod: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 % i2); - break; - case psOpMul: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - //~ should check for out-of-range, and push a real instead - stack->pushInt(i1 * i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 * r2); - } - break; - case psOpNe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 != i2); - } else if (stack->topTwoAreNums()) { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 != r2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 != b2); - } - break; - case psOpNeg: - if (stack->topIsInt()) { - stack->pushInt(-stack->popInt()); - } else { - stack->pushReal(-stack->popNum()); - } - break; - case psOpNot: - if (stack->topIsInt()) { - stack->pushInt(~stack->popInt()); - } else { - stack->pushBool(!stack->popBool()); - } - break; - case psOpOr: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 | i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 || b2); - } - break; - case psOpPop: - stack->pop(); - break; - case psOpRoll: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->roll(i1, i2); - break; - case psOpRound: - if (!stack->topIsInt()) { - r1 = stack->popNum(); - stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); - } - break; - case psOpSin: - stack->pushReal(sin(stack->popNum())); - break; - case psOpSqrt: - stack->pushReal(sqrt(stack->popNum())); - break; - case psOpSub: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 - i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 - r2); - } - break; - case psOpTrue: - stack->pushBool(gTrue); - break; - case psOpTruncate: - if (!stack->topIsInt()) { - r1 = stack->popNum(); - stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1)); - } - break; - case psOpXor: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 ^ i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 ^ b2); - } - break; - case psOpIf: - b1 = stack->popBool(); - if (b1) { - exec(stack, codePtr + 2); - } - codePtr = code[codePtr + 1].blk; - break; - case psOpIfelse: - b1 = stack->popBool(); - if (b1) { - exec(stack, codePtr + 2); - } else { - exec(stack, code[codePtr].blk); + case psOpAnd: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] & (int)stack[sp]; + ++sp; + break; + case psOpAtan: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = atan2(stack[sp + 1], stack[sp]); + ++sp; + break; + case psOpBitshift: + if (sp + 1 >= psStackSize) { + goto underflow; + } + k = (int)stack[sp + 1]; + nn = (int)stack[sp]; + if (nn > 0) { + stack[sp + 1] = k << nn; + } else if (nn < 0) { + stack[sp + 1] = k >> -nn; + } else { + stack[sp + 1] = k; + } + ++sp; + break; + case psOpCeiling: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = ceil(stack[sp]); + break; + case psOpCopy: + if (sp >= psStackSize) { + goto underflow; + } + nn = (int)stack[sp++]; + if (nn < 0) { + goto invalidArg; + } + if (sp + nn > psStackSize) { + goto underflow; + } + if (sp - nn < 0) { + goto overflow; + } + for (i = 0; i < nn; ++i) { + stack[sp - nn + i] = stack[sp + i]; + } + sp -= nn; + break; + case psOpCos: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = cos(stack[sp]); + break; + case psOpCvi: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = (int)stack[sp]; + break; + case psOpCvr: + if (sp >= psStackSize) { + goto underflow; + } + break; + case psOpDiv: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] / stack[sp]; + ++sp; + break; + case psOpDup: + if (sp >= psStackSize) { + goto underflow; + } + if (sp < 1) { + goto overflow; + } + stack[sp - 1] = stack[sp]; + --sp; + break; + case psOpEq: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] == stack[sp] ? 1 : 0; + ++sp; + break; + case psOpExch: + if (sp + 1 >= psStackSize) { + goto underflow; + } + t = stack[sp]; + stack[sp] = stack[sp + 1]; + stack[sp + 1] = t; + break; + case psOpExp: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = pow(stack[sp + 1], stack[sp]); + ++sp; + break; + case psOpFalse: + if (sp < 1) { + goto overflow; + } + stack[sp - 1] = 0; + --sp; + break; + case psOpFloor: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = floor(stack[sp]); + break; + case psOpGe: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] >= stack[sp] ? 1 : 0; + ++sp; + break; + case psOpGt: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] > stack[sp] ? 1 : 0; + ++sp; + break; + case psOpIdiv: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] / (int)stack[sp]; + ++sp; + break; + case psOpIndex: + if (sp >= psStackSize) { + goto underflow; + } + k = (int)stack[sp]; + if (k < 0) { + goto invalidArg; + } + if (sp + 1 + k >= psStackSize) { + goto underflow; + } + stack[sp] = stack[sp + 1 + k]; + break; + case psOpLe: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] <= stack[sp] ? 1 : 0; + ++sp; + break; + case psOpLn: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = log(stack[sp]); + break; + case psOpLog: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = log10(stack[sp]); + break; + case psOpLt: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] < stack[sp] ? 1 : 0; + ++sp; + break; + case psOpMod: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] % (int)stack[sp]; + ++sp; + break; + case psOpMul: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] * stack[sp]; + ++sp; + break; + case psOpNe: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] != stack[sp] ? 1 : 0; + ++sp; + break; + case psOpNeg: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = -stack[sp]; + break; + case psOpNot: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = stack[sp] == 0 ? 1 : 0; + break; + case psOpOr: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] | (int)stack[sp]; + ++sp; + break; + case psOpPop: + if (sp >= psStackSize) { + goto underflow; + } + ++sp; + break; + case psOpRoll: + if (sp + 1 >= psStackSize) { + goto underflow; + } + k = (int)stack[sp++]; + nn = (int)stack[sp++]; + if (nn < 0) { + goto invalidArg; + } + if (sp + nn > psStackSize) { + goto underflow; + } + if (k >= 0) { + k %= nn; + } else { + k = -k % nn; + if (k) { + k = nn - k; } - codePtr = code[codePtr + 1].blk; - break; - case psOpReturn: - return; + } + for (i = 0; i < nn; ++i) { + tmp[i] = stack[sp + i]; + } + for (i = 0; i < nn; ++i) { + stack[sp + i] = tmp[(i + k) % nn]; } break; - default: - error(errSyntaxError, -1, - "Internal: bad object in PostScript function code"); + case psOpRound: + if (sp >= psStackSize) { + goto underflow; + } + t = stack[sp]; + stack[sp] = (t >= 0) ? floor(t + 0.5) : ceil(t - 0.5); + break; + case psOpSin: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = sin(stack[sp]); + break; + case psOpSqrt: + if (sp >= psStackSize) { + goto underflow; + } + stack[sp] = sqrt(stack[sp]); + break; + case psOpSub: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = stack[sp + 1] - stack[sp]; + ++sp; + break; + case psOpTrue: + if (sp < 1) { + goto overflow; + } + stack[sp - 1] = 1; + --sp; + break; + case psOpTruncate: + if (sp >= psStackSize) { + goto underflow; + } + t = stack[sp]; + stack[sp] = (t >= 0) ? floor(t) : ceil(t); + break; + case psOpXor: + if (sp + 1 >= psStackSize) { + goto underflow; + } + stack[sp + 1] = (int)stack[sp + 1] ^ (int)stack[sp]; + ++sp; + break; + case psOpPush: + if (sp < 1) { + goto overflow; + } + stack[--sp] = c->val.d; + break; + case psOpJ: + ip = c->val.i; + break; + case psOpJz: + if (sp >= psStackSize) { + goto underflow; + } + k = (int)stack[sp++]; + if (k == 0) { + ip = c->val.i; + } break; } } + return sp; + + underflow: + error(errSyntaxError, -1, "Stack underflow in PostScript function"); + return sp; + overflow: + error(errSyntaxError, -1, "Stack overflow in PostScript function"); + return sp; + invalidArg: + error(errSyntaxError, -1, "Invalid arg in PostScript function"); + return sp; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Function.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Function.h index 8852dca85c8..5cf45169a49 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Function.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Function.h @@ -18,10 +18,10 @@ #include "gtypes.h" #include "Object.h" +class GList; class Dict; class Stream; -struct PSObject; -class PSStack; +struct PSCode; //------------------------------------------------------------------------ // Function @@ -217,13 +217,16 @@ public: private: PostScriptFunction(PostScriptFunction *func); - GBool parseCode(Stream *str, int *codePtr); + GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); + void addCode(int *codePtr, int op); + void addCodeI(int *codePtr, int op, int x); + void addCodeD(int *codePtr, int op, double x); GString *getToken(Stream *str); - void resizeCode(int newSize); - void exec(PSStack *stack, int codePtr); + int exec(double *stack, int sp0); GString *codeString; - PSObject *code; + PSCode *code; + int codeLen; int codeSize; double cacheIn[funcMaxInputs]; double cacheOut[funcMaxOutputs]; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Gfx.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Gfx.cc index 1979f84c994..0fa48f8c8af 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Gfx.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Gfx.cc @@ -2,7 +2,7 @@ // // Gfx.cc // -// Copyright 1996-2003 Glyph & Cog, LLC +// Copyright 1996-2013 Glyph & Cog, LLC // //======================================================================== @@ -36,7 +36,7 @@ #include "Annot.h" #include "OptionalContent.h" #include "Error.h" -#include "PDFDocEncoding.h" +#include "TextString.h" #include "Gfx.h" // the MSVC math.h doesn't define this @@ -80,11 +80,15 @@ // fill. #define patchColorDelta (dblToCol(1 / 256.0)) +// Max errors (undefined operator, wrong number of args) allowed before +// giving up on a content stream. +#define contentStreamErrorLimit 500 + //------------------------------------------------------------------------ // Operator table //------------------------------------------------------------------------ -#ifdef WIN32 // this works around a bug in the VC7 compiler +#ifdef _WIN32 // this works around a bug in the VC7 compiler # pragma optimize("",off) #endif @@ -257,7 +261,7 @@ Operator Gfx::opTab[] = { &Gfx::opCurveTo2}, }; -#ifdef WIN32 // this works around a bug in the VC7 compiler +#ifdef _WIN32 // this works around a bug in the VC7 compiler # pragma optimize("",on) #endif @@ -337,15 +341,31 @@ GfxFont *GfxResources::lookupFont(char *name) { for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->fonts) { - if ((font = resPtr->fonts->lookup(name))) + if ((font = resPtr->fonts->lookup(name))) { return font; + } } } error(errSyntaxError, -1, "Unknown font tag '{0:s}'", name); return NULL; } -GBool GfxResources::lookupXObject(char *name, Object *obj) { +GfxFont *GfxResources::lookupFontByRef(Ref ref) { + GfxFont *font; + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->fonts) { + if ((font = resPtr->fonts->lookupByRef(ref))) { + return font; + } + } + } + error(errSyntaxError, -1, "Unknown font ref {0:d}.{1:d}", ref.num, ref.gen); + return NULL; +} + +GBool GfxResources::lookupXObject(const char *name, Object *obj) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { @@ -359,7 +379,7 @@ GBool GfxResources::lookupXObject(char *name, Object *obj) { return gFalse; } -GBool GfxResources::lookupXObjectNF(char *name, Object *obj) { +GBool GfxResources::lookupXObjectNF(const char *name, Object *obj) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { @@ -373,9 +393,16 @@ GBool GfxResources::lookupXObjectNF(char *name, Object *obj) { return gFalse; } -void GfxResources::lookupColorSpace(char *name, Object *obj) { +void GfxResources::lookupColorSpace(const char *name, Object *obj) { GfxResources *resPtr; + //~ should also test for G, RGB, and CMYK - but only in inline images (?) + if (!strcmp(name, "DeviceGray") || + !strcmp(name, "DeviceRGB") || + !strcmp(name, "DeviceCMYK")) { + obj->initNull(); + return; + } for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->colorSpaceDict.isDict()) { if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) { @@ -387,15 +414,19 @@ void GfxResources::lookupColorSpace(char *name, Object *obj) { obj->initNull(); } -GfxPattern *GfxResources::lookupPattern(char *name) { +GfxPattern *GfxResources::lookupPattern(const char *name + ) { GfxResources *resPtr; GfxPattern *pattern; - Object obj; + Object objRef, obj; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->patternDict.isDict()) { if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { - pattern = GfxPattern::parse(&obj); + resPtr->patternDict.dictLookupNF(name, &objRef); + pattern = GfxPattern::parse(&objRef, &obj + ); + objRef.free(); obj.free(); return pattern; } @@ -406,7 +437,8 @@ GfxPattern *GfxResources::lookupPattern(char *name) { return NULL; } -GfxShading *GfxResources::lookupShading(char *name) { +GfxShading *GfxResources::lookupShading(const char *name + ) { GfxResources *resPtr; GfxShading *shading; Object obj; @@ -414,7 +446,8 @@ GfxShading *GfxResources::lookupShading(char *name) { for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->shadingDict.isDict()) { if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) { - shading = GfxShading::parse(&obj); + shading = GfxShading::parse(&obj + ); obj.free(); return shading; } @@ -425,7 +458,7 @@ GfxShading *GfxResources::lookupShading(char *name) { return NULL; } -GBool GfxResources::lookupGState(char *name, Object *obj) { +GBool GfxResources::lookupGState(const char *name, Object *obj) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { @@ -440,7 +473,7 @@ GBool GfxResources::lookupGState(char *name, Object *obj) { return gFalse; } -GBool GfxResources::lookupPropertiesNF(char *name, Object *obj) { +GBool GfxResources::lookupPropertiesNF(const char *name, Object *obj) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { @@ -491,6 +524,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, markedContentStack = new GList(); ocState = gTrue; parser = NULL; + contentStreamStack = new GList(); abortCheckCbk = abortCheckCbkA; abortCheckCbkData = abortCheckCbkDataA; @@ -535,6 +569,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, markedContentStack = new GList(); ocState = gTrue; parser = NULL; + contentStreamStack = new GList(); abortCheckCbk = abortCheckCbkA; abortCheckCbkData = abortCheckCbkDataA; @@ -563,41 +598,99 @@ Gfx::~Gfx() { popResources(); } deleteGList(markedContentStack, GfxMarkedContent); + delete contentStreamStack; } -void Gfx::display(Object *obj, GBool topLevel) { - Object obj2; +void Gfx::display(Object *objRef, GBool topLevel) { + Object obj1, obj2; int i; - if (obj->isArray()) { - for (i = 0; i < obj->arrayGetLength(); ++i) { - obj->arrayGet(i, &obj2); + objRef->fetch(xref, &obj1); + if (obj1.isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + obj1.arrayGetNF(i, &obj2); + if (checkForContentStreamLoop(&obj2)) { + obj2.free(); + obj1.free(); + return; + } + obj2.free(); + } + for (i = 0; i < obj1.arrayGetLength(); ++i) { + obj1.arrayGet(i, &obj2); if (!obj2.isStream()) { - error(errSyntaxError, -1, "Weird page contents"); + error(errSyntaxError, -1, "Invalid object type for content stream"); obj2.free(); + obj1.free(); return; } obj2.free(); } - } else if (!obj->isStream()) { - error(errSyntaxError, -1, "Weird page contents"); + contentStreamStack->append(&obj1); + } else if (obj1.isStream()) { + if (checkForContentStreamLoop(objRef)) { + obj1.free(); + return; + } + contentStreamStack->append(objRef); + } else { + error(errSyntaxError, -1, "Invalid object type for content stream"); + obj1.free(); return; } - parser = new Parser(xref, new Lexer(xref, obj), gFalse); + parser = new Parser(xref, new Lexer(xref, &obj1), gFalse); go(topLevel); delete parser; parser = NULL; + contentStreamStack->del(contentStreamStack->getLength() - 1); + obj1.free(); +} + +// If <ref> is already on contentStreamStack, i.e., if there is a loop +// in the content streams, report an error, and return true. +GBool Gfx::checkForContentStreamLoop(Object *ref) { + Object *objPtr; + Object obj1; + int i, j; + + if (ref->isRef()) { + for (i = 0; i < contentStreamStack->getLength(); ++i) { + objPtr = (Object *)contentStreamStack->get(i); + if (objPtr->isRef()) { + if (ref->getRefNum() == objPtr->getRefNum() && + ref->getRefGen() == objPtr->getRefGen()) { + error(errSyntaxError, -1, "Loop in content streams"); + return gTrue; + } + } else if (objPtr->isArray()) { + for (j = 0; j < objPtr->arrayGetLength(); ++j) { + objPtr->arrayGetNF(j, &obj1); + if (obj1.isRef()) { + if (ref->getRefNum() == obj1.getRefNum() && + ref->getRefGen() == obj1.getRefGen()) { + error(errSyntaxError, -1, "Loop in content streams"); + obj1.free(); + return gTrue; + } + } + obj1.free(); + } + } + } + } + return gFalse; } void Gfx::go(GBool topLevel) { Object obj; Object args[maxArgs]; int numArgs, i; - int lastAbortCheck; + int lastAbortCheck, errCount; // scan a sequence of objects updateLevel = 1; // make sure even empty pages trigger a call to dump() lastAbortCheck = 0; + errCount = 0; numArgs = 0; parser->getObj(&obj); while (!obj.isEOF()) { @@ -613,7 +706,9 @@ void Gfx::go(GBool topLevel) { printf("\n"); fflush(stdout); } - execOp(&obj, args, numArgs); + if (!execOp(&obj, args, numArgs)) { + ++errCount; + } obj.free(); for (i = 0; i < numArgs; ++i) args[i].free(); @@ -635,6 +730,13 @@ void Gfx::go(GBool topLevel) { } } + // check for too many errors + if (errCount > contentStreamErrorLimit) { + error(errSyntaxError, -1, + "Too many errors - giving up on this content stream"); + break; + } + // got an argument - save it } else if (numArgs < maxArgs) { args[numArgs++] = obj; @@ -678,7 +780,8 @@ void Gfx::go(GBool topLevel) { } } -void Gfx::execOp(Object *cmd, Object args[], int numArgs) { +// Returns true if successful, false on error. +GBool Gfx::execOp(Object *cmd, Object args[], int numArgs) { Operator *op; char *name; Object *argPtr; @@ -687,9 +790,11 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) { // find operator name = cmd->getCmd(); if (!(op = findOp(name))) { - if (ignoreUndef == 0) - error(errSyntaxError, getPos(), "Unknown operator '{0:s}'", name); - return; + if (ignoreUndef > 0) { + return gTrue; + } + error(errSyntaxError, getPos(), "Unknown operator '{0:s}'", name); + return gFalse; } // type check args @@ -698,7 +803,7 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) { if (numArgs < op->numArgs) { error(errSyntaxError, getPos(), "Too few ({0:d}) args to '{1:s}' operator", numArgs, name); - return; + return gFalse; } if (numArgs > op->numArgs) { #if 0 @@ -713,7 +818,7 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) { error(errSyntaxError, getPos(), "Too many ({0:d}) args to '{1:s}' operator", numArgs, name); - return; + return gFalse; } } for (i = 0; i < numArgs; ++i) { @@ -721,12 +826,14 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) { error(errSyntaxError, getPos(), "Arg #{0:d} to '{1:s}' operator is wrong type ({2:s})", i, name, argPtr[i].getTypeName()); - return; + return gFalse; } } // do it (this->*op->func)(argPtr, numArgs); + + return gTrue; } Operator *Gfx::findOp(char *name) { @@ -766,7 +873,7 @@ GBool Gfx::checkArg(Object *arg, TchkType type) { return gFalse; } -int Gfx::getPos() { +GFileOffset Gfx::getPos() { return parser ? parser->getPos() : -1; } @@ -840,7 +947,7 @@ void Gfx::opSetLineWidth(Object args[], int numArgs) { } void Gfx::opSetExtGState(Object args[], int numArgs) { - Object obj1, obj2, obj3, obj4, obj5; + Object obj1, obj2, obj3, objRef3, obj4, obj5; Object args2[2]; GfxBlendMode mode; GBool haveFillOP; @@ -895,22 +1002,21 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { args2[1].free(); } obj2.free(); -#if 0 //~ need to add a new version of GfxResources::lookupFont() that - //~ takes an indirect ref instead of a name + if (obj1.dictLookup("FL", &obj2)->isNum()) { + opSetFlat(&obj2, 1); + } + obj2.free(); + + // font if (obj1.dictLookup("Font", &obj2)->isArray() && obj2.arrayGetLength() == 2) { - obj2.arrayGet(0, &args2[0]); - obj2.arrayGet(1, &args2[1]); - if (args2[0].isDict() && args2[1].isNum()) { - opSetFont(args2, 2); + obj2.arrayGetNF(0, &obj3); + obj2.arrayGetNF(1, &obj4); + if (obj3.isRef() && obj4.isNum()) { + doSetFont(res->lookupFontByRef(obj3.getRef()), obj4.getNum()); } - args2[0].free(); - args2[1].free(); - } - obj2.free(); -#endif - if (obj1.dictLookup("FL", &obj2)->isNum()) { - opSetFlat(&obj2, 1); + obj3.free(); + obj4.free(); } obj2.free(); @@ -1045,7 +1151,8 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { blendingColorSpace = NULL; isolated = knockout = gFalse; if (!obj4.dictLookup("CS", &obj5)->isNull()) { - blendingColorSpace = GfxColorSpace::parse(&obj5); + blendingColorSpace = GfxColorSpace::parse(&obj5 + ); } obj5.free(); if (obj4.dictLookup("I", &obj5)->isBool()) { @@ -1066,8 +1173,10 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { } } } - doSoftMask(&obj3, alpha, blendingColorSpace, + obj2.dictLookupNF("G", &objRef3); + doSoftMask(&obj3, &objRef3, alpha, blendingColorSpace, isolated, knockout, funcs[0], &backdropColor); + objRef3.free(); if (funcs[0]) { delete funcs[0]; } @@ -1090,7 +1199,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { obj1.free(); } -void Gfx::doSoftMask(Object *str, GBool alpha, +void Gfx::doSoftMask(Object *str, Object *strRef, GBool alpha, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout, Function *transferFunc, GfxColor *backdropColor) { @@ -1149,7 +1258,7 @@ void Gfx::doSoftMask(Object *str, GBool alpha, // draw it ++formDepth; - drawForm(str, resDict, m, bbox, gTrue, gTrue, + drawForm(strRef, resDict, m, bbox, gTrue, gTrue, blendingColorSpace, isolated, knockout, alpha, transferFunc, backdropColor); --formDepth; @@ -1171,7 +1280,7 @@ void Gfx::opSetFillGray(Object args[], int numArgs) { GfxColor color; state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceGrayColorSpace()); + state->setFillColorSpace(GfxColorSpace::create(csDeviceGray)); out->updateFillColorSpace(state); color.c[0] = dblToCol(args[0].getNum()); state->setFillColor(&color); @@ -1182,7 +1291,7 @@ void Gfx::opSetStrokeGray(Object args[], int numArgs) { GfxColor color; state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); out->updateStrokeColorSpace(state); color.c[0] = dblToCol(args[0].getNum()); state->setStrokeColor(&color); @@ -1194,7 +1303,7 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { int i; state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceCMYKColorSpace()); + state->setFillColorSpace(GfxColorSpace::create(csDeviceCMYK)); out->updateFillColorSpace(state); for (i = 0; i < 4; ++i) { color.c[i] = dblToCol(args[i].getNum()); @@ -1208,7 +1317,7 @@ void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { int i; state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace()); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceCMYK)); out->updateStrokeColorSpace(state); for (i = 0; i < 4; ++i) { color.c[i] = dblToCol(args[i].getNum()); @@ -1222,7 +1331,7 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) { int i; state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceRGBColorSpace()); + state->setFillColorSpace(GfxColorSpace::create(csDeviceRGB)); out->updateFillColorSpace(state); for (i = 0; i < 3; ++i) { color.c[i] = dblToCol(args[i].getNum()); @@ -1236,7 +1345,7 @@ void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { int i; state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceRGBColorSpace()); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceRGB)); out->updateStrokeColorSpace(state); for (i = 0; i < 3; ++i) { color.c[i] = dblToCol(args[i].getNum()); @@ -1253,9 +1362,11 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) { state->setFillPattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0]); + colorSpace = GfxColorSpace::parse(&args[0] + ); } else { - colorSpace = GfxColorSpace::parse(&obj); + colorSpace = GfxColorSpace::parse(&obj + ); } obj.free(); if (colorSpace) { @@ -1277,9 +1388,11 @@ void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0]); + colorSpace = GfxColorSpace::parse(&args[0] + ); } else { - colorSpace = GfxColorSpace::parse(&obj); + colorSpace = GfxColorSpace::parse(&obj + ); } obj.free(); if (colorSpace) { @@ -1350,7 +1463,8 @@ void Gfx::opSetFillColorN(Object args[], int numArgs) { out->updateFillColor(state); } if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { + (pattern = res->lookupPattern(args[numArgs-1].getName() + ))) { state->setFillPattern(pattern); } @@ -1395,7 +1509,8 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) { out->updateStrokeColor(state); } if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { + (pattern = res->lookupPattern(args[numArgs-1].getName() + ))) { state->setStrokePattern(pattern); } @@ -1751,11 +1866,11 @@ void Gfx::doPatternText() { } void Gfx::doPatternImageMask(Object *ref, Stream *str, int width, int height, - GBool invert, GBool inlineImg) { + GBool invert, GBool inlineImg, GBool interpolate) { saveState(); out->setSoftMaskFromImageMask(state, ref, str, - width, height, invert, inlineImg); + width, height, invert, inlineImg, interpolate); state->clearPath(); state->moveTo(0, 0); @@ -1773,11 +1888,11 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GfxPatternColorSpace *patCS; GfxColorSpace *cs; GfxState *savedState; - double xMin, yMin, xMax, yMax, x, y, x1, y1; + double xMin, yMin, xMax, yMax, x, y, x1, y1, t; double cxMin, cyMin, cxMax, cyMax; int xi0, yi0, xi1, yi1, xi, yi; double *ctm, *btm, *ptm; - double m[6], ictm[6], m1[6], imb[6]; + double bbox[4], m[6], ictm[6], m1[6], imb[6]; double det; double xstep, ystep; int i; @@ -1791,7 +1906,12 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, btm = baseMatrix; ptm = tPat->getMatrix(); // iCTM = invert CTM - det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; + if (fabs(det) < 0.000001) { + error(errSyntaxError, getPos(), "Singular matrix in tiling pattern fill"); + return; + } + det = 1 / det; ictm[0] = ctm[3] * det; ictm[1] = -ctm[1] * det; ictm[2] = -ctm[2] * det; @@ -1814,7 +1934,12 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; // construct a (device space) -> (pattern space) transform matrix - det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]); + det = m1[0] * m1[3] - m1[1] * m1[2]; + if (fabs(det) < 0.000001) { + error(errSyntaxError, getPos(), "Singular matrix in tiling pattern fill"); + return; + } + det = 1 / det; imb[0] = m1[3] * det; imb[1] = -m1[1] * det; imb[2] = -m1[2] * det; @@ -1839,9 +1964,9 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, out->updateFillColor(state); out->updateStrokeColor(state); } else { - state->setFillColorSpace(new GfxDeviceGrayColorSpace()); + state->setFillColorSpace(GfxColorSpace::create(csDeviceGray)); out->updateFillColorSpace(state); - state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); out->updateStrokeColorSpace(state); } if (!stroke) { @@ -1912,21 +2037,31 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, // draw the pattern //~ this should treat negative steps differently -- start at right/top //~ edge instead of left/bottom (?) + bbox[0] = tPat->getBBox()[0]; + bbox[1] = tPat->getBBox()[1]; + bbox[2] = tPat->getBBox()[2]; + bbox[3] = tPat->getBBox()[3]; + if (bbox[0] > bbox[2]) { + t = bbox[0]; bbox[0] = bbox[2]; bbox[2] = t; + } + if (bbox[1] > bbox[3]) { + t = bbox[1]; bbox[1] = bbox[3]; bbox[3] = t; + } xstep = fabs(tPat->getXStep()); ystep = fabs(tPat->getYStep()); - xi0 = (int)ceil((xMin - tPat->getBBox()[2]) / xstep); - xi1 = (int)floor((xMax - tPat->getBBox()[0]) / xstep) + 1; - yi0 = (int)ceil((yMin - tPat->getBBox()[3]) / ystep); - yi1 = (int)floor((yMax - tPat->getBBox()[1]) / ystep) + 1; + xi0 = (int)ceil((xMin - bbox[2]) / xstep); + xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; + yi0 = (int)ceil((yMin - bbox[3]) / ystep); + yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; for (i = 0; i < 4; ++i) { m1[i] = m[i]; } if (out->useTilingPatternFill()) { m1[4] = m[4]; m1[5] = m[5]; - out->tilingPatternFill(state, this, tPat->getContentStream(), + out->tilingPatternFill(state, this, tPat->getContentStreamRef(), tPat->getPaintType(), tPat->getResDict(), - m1, tPat->getBBox(), + m1, bbox, xi0, yi0, xi1, yi1, xstep, ystep); } else { for (yi = yi0; yi < yi1; ++yi) { @@ -1935,8 +2070,8 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, y = yi * ystep; m1[4] = x * m[0] + y * m[2] + m[4]; m1[5] = x * m[1] + y * m[3] + m[5]; - drawForm(tPat->getContentStream(), tPat->getResDict(), - m1, tPat->getBBox()); + drawForm(tPat->getContentStreamRef(), tPat->getResDict(), + m1, bbox); } } } @@ -1979,7 +2114,12 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, btm = baseMatrix; ptm = sPat->getMatrix(); // iCTM = invert CTM - det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; + if (fabs(det) < 0.000001) { + error(errSyntaxError, getPos(), "Singular matrix in shading pattern fill"); + return; + } + det = 1 / det; ictm[0] = ctm[3] * det; ictm[1] = -ctm[1] * det; ictm[2] = -ctm[2] * det; @@ -2074,11 +2214,16 @@ void Gfx::opShFill(Object args[], int numArgs) { GfxState *savedState; double xMin, yMin, xMax, yMax; + if (!out->needNonText()) { + return; + } + if (!ocState) { return; } - if (!(shading = res->lookupShading(args[0].getName()))) { + if (!(shading = res->lookupShading(args[0].getName() + ))) { return; } @@ -2487,7 +2632,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { GfxColor colorA, colorB; double xa, ya, xb, yb, ra, rb; double ta, tb, sa, sb; - double sz, sMin, sMax, h; + double sMin, sMax, h; double sLeft, sRight, sTop, sBottom, sZero, sDiag; GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero; GBool haveSMin, haveSMax; @@ -2513,18 +2658,14 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { if (h == 0) { enclosed = gTrue; theta = 0; // make gcc happy - sz = 0; // make gcc happy } else if (r1 - r0 == 0) { enclosed = gFalse; theta = 0; - sz = 0; // make gcc happy - } else if (fabs(r1 - r0) >= h) { + } else if (fabs(r1 - r0) >= h - 0.0001) { enclosed = gTrue; theta = 0; // make gcc happy - sz = 0; // make gcc happy } else { enclosed = gFalse; - sz = -r0 / (r1 - r0); theta = asin((r1 - r0) / h); } if (enclosed) { @@ -2598,7 +2739,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { haveSMin = gTrue; } } - if (haveSZero && sZero < 0) { + if (haveSZero && sZero <= 0) { if (!haveSMin || sZero > sMin) { sMin = sZero; } @@ -2865,34 +3006,56 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) { double x0, y0, x1, y1, x2, y2; - GfxColor color0, color1, color2; + double color0[gfxColorMaxComps]; + double color1[gfxColorMaxComps]; + double color2[gfxColorMaxComps]; int i; for (i = 0; i < shading->getNTriangles(); ++i) { - shading->getTriangle(i, &x0, &y0, &color0, - &x1, &y1, &color1, - &x2, &y2, &color2); - gouraudFillTriangle(x0, y0, &color0, x1, y1, &color1, x2, y2, &color2, - shading->getColorSpace()->getNComps(), 0); + shading->getTriangle(i, &x0, &y0, color0, + &x1, &y1, color1, + &x2, &y2, color2); + gouraudFillTriangle(x0, y0, color0, x1, y1, color1, x2, y2, color2, + shading, 0); } } -void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0, - double x1, double y1, GfxColor *color1, - double x2, double y2, GfxColor *color2, - int nComps, int depth) { +void Gfx::gouraudFillTriangle(double x0, double y0, double *color0, + double x1, double y1, double *color1, + double x2, double y2, double *color2, + GfxGouraudTriangleShading *shading, int depth) { + double dx0, dy0, dx1, dy1, dx2, dy2; double x01, y01, x12, y12, x20, y20; - GfxColor color01, color12, color20; - int i; - + double color01[gfxColorMaxComps]; + double color12[gfxColorMaxComps]; + double color20[gfxColorMaxComps]; + GfxColor c0, c1, c2; + int nComps, i; + + // recursion ends when: + // (1) color difference is smaller than gouraudColorDelta; or + // (2) triangles are smaller than 0.5 pixel (note that "device + // space" is 72dpi when generating PostScript); or + // (3) max recursion depth (gouraudMaxDepth) is hit. + nComps = shading->getColorSpace()->getNComps(); + shading->getColor(color0, &c0); + shading->getColor(color1, &c1); + shading->getColor(color2, &c2); for (i = 0; i < nComps; ++i) { - if (abs(color0->c[i] - color1->c[i]) > gouraudColorDelta || - abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) { + if (abs(c0.c[i] - c1.c[i]) > gouraudColorDelta || + abs(c1.c[i] - c2.c[i]) > gouraudColorDelta) { break; } } - if (i == nComps || depth == gouraudMaxDepth) { - state->setFillColor(color0); + state->transformDelta(x1 - x0, y1 - y0, &dx0, &dy0); + state->transformDelta(x2 - x1, y2 - y1, &dx1, &dy1); + state->transformDelta(x0 - x2, y0 - y2, &dx2, &dy2); + if (i == nComps || + depth == gouraudMaxDepth || + (fabs(dx0) < 0.5 && fabs(dy0) < 0.5 && + fabs(dx1) < 0.5 && fabs(dy1) < 0.5 && + fabs(dx2) < 0.5 && fabs(dy2) < 0.5)) { + state->setFillColor(&c0); out->updateFillColor(state); state->moveTo(x0, y0); state->lineTo(x1, y1); @@ -2907,21 +3070,19 @@ void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0, y12 = 0.5 * (y1 + y2); x20 = 0.5 * (x2 + x0); y20 = 0.5 * (y2 + y0); - //~ if the shading has a Function, this should interpolate on the - //~ function parameter, not on the color components - for (i = 0; i < nComps; ++i) { - color01.c[i] = (color0->c[i] + color1->c[i]) / 2; - color12.c[i] = (color1->c[i] + color2->c[i]) / 2; - color20.c[i] = (color2->c[i] + color0->c[i]) / 2; - } - gouraudFillTriangle(x0, y0, color0, x01, y01, &color01, - x20, y20, &color20, nComps, depth + 1); - gouraudFillTriangle(x01, y01, &color01, x1, y1, color1, - x12, y12, &color12, nComps, depth + 1); - gouraudFillTriangle(x01, y01, &color01, x12, y12, &color12, - x20, y20, &color20, nComps, depth + 1); - gouraudFillTriangle(x20, y20, &color20, x12, y12, &color12, - x2, y2, color2, nComps, depth + 1); + for (i = 0; i < shading->getNComps(); ++i) { + color01[i] = 0.5 * (color0[i] + color1[i]); + color12[i] = 0.5 * (color1[i] + color2[i]); + color20[i] = 0.5 * (color2[i] + color0[i]); + } + gouraudFillTriangle(x0, y0, color0, x01, y01, color01, + x20, y20, color20, shading, depth + 1); + gouraudFillTriangle(x01, y01, color01, x1, y1, color1, + x12, y12, color12, shading, depth + 1); + gouraudFillTriangle(x01, y01, color01, x12, y12, color12, + x20, y20, color20, shading, depth + 1); + gouraudFillTriangle(x20, y20, color20, x12, y12, color12, + x2, y2, color2, shading, depth + 1); } } @@ -2938,31 +3099,32 @@ void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) { start = 0; } for (i = 0; i < shading->getNPatches(); ++i) { - fillPatch(shading->getPatch(i), shading->getColorSpace()->getNComps(), - start); + fillPatch(shading->getPatch(i), shading, start); } } -void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) { +void Gfx::fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth) { GfxPatch patch00, patch01, patch10, patch11; + GfxColor c00, c01, c10, c11; double xx[4][8], yy[4][8]; double xxm, yym; - int i; + int nComps, i; + nComps = shading->getColorSpace()->getNComps(); + shading->getColor(patch->color[0][0], &c00); + shading->getColor(patch->color[0][1], &c01); + shading->getColor(patch->color[1][0], &c10); + shading->getColor(patch->color[1][1], &c11); for (i = 0; i < nComps; ++i) { - if (abs(patch->color[0][0].c[i] - patch->color[0][1].c[i]) - > patchColorDelta || - abs(patch->color[0][1].c[i] - patch->color[1][1].c[i]) - > patchColorDelta || - abs(patch->color[1][1].c[i] - patch->color[1][0].c[i]) - > patchColorDelta || - abs(patch->color[1][0].c[i] - patch->color[0][0].c[i]) - > patchColorDelta) { + if (abs(c00.c[i] - c01.c[i]) > patchColorDelta || + abs(c01.c[i] - c11.c[i]) > patchColorDelta || + abs(c11.c[i] - c10.c[i]) > patchColorDelta || + abs(c10.c[i] - c00.c[i]) > patchColorDelta) { break; } } if (i == nComps || depth == patchMaxDepth) { - state->setFillColor(&patch->color[0][0]); + state->setFillColor(&c00); out->updateFillColor(state); state->moveTo(patch->x[0][0], patch->y[0][0]); state->curveTo(patch->x[0][1], patch->y[0][1], @@ -3039,35 +3201,33 @@ void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) { patch11.x[3][i-4] = xx[3][i]; patch11.y[3][i-4] = yy[3][i]; } - //~ if the shading has a Function, this should interpolate on the - //~ function parameter, not on the color components - for (i = 0; i < nComps; ++i) { - patch00.color[0][0].c[i] = patch->color[0][0].c[i]; - patch00.color[0][1].c[i] = (patch->color[0][0].c[i] + - patch->color[0][1].c[i]) / 2; - patch01.color[0][0].c[i] = patch00.color[0][1].c[i]; - patch01.color[0][1].c[i] = patch->color[0][1].c[i]; - patch01.color[1][1].c[i] = (patch->color[0][1].c[i] + - patch->color[1][1].c[i]) / 2; - patch11.color[0][1].c[i] = patch01.color[1][1].c[i]; - patch11.color[1][1].c[i] = patch->color[1][1].c[i]; - patch11.color[1][0].c[i] = (patch->color[1][1].c[i] + - patch->color[1][0].c[i]) / 2; - patch10.color[1][1].c[i] = patch11.color[1][0].c[i]; - patch10.color[1][0].c[i] = patch->color[1][0].c[i]; - patch10.color[0][0].c[i] = (patch->color[1][0].c[i] + - patch->color[0][0].c[i]) / 2; - patch00.color[1][0].c[i] = patch10.color[0][0].c[i]; - patch00.color[1][1].c[i] = (patch00.color[1][0].c[i] + - patch01.color[1][1].c[i]) / 2; - patch01.color[1][0].c[i] = patch00.color[1][1].c[i]; - patch11.color[0][0].c[i] = patch00.color[1][1].c[i]; - patch10.color[0][1].c[i] = patch00.color[1][1].c[i]; - } - fillPatch(&patch00, nComps, depth + 1); - fillPatch(&patch10, nComps, depth + 1); - fillPatch(&patch01, nComps, depth + 1); - fillPatch(&patch11, nComps, depth + 1); + for (i = 0; i < shading->getNComps(); ++i) { + patch00.color[0][0][i] = patch->color[0][0][i]; + patch00.color[0][1][i] = 0.5 * (patch->color[0][0][i] + + patch->color[0][1][i]); + patch01.color[0][0][i] = patch00.color[0][1][i]; + patch01.color[0][1][i] = patch->color[0][1][i]; + patch01.color[1][1][i] = 0.5 * (patch->color[0][1][i] + + patch->color[1][1][i]); + patch11.color[0][1][i] = patch01.color[1][1][i]; + patch11.color[1][1][i] = patch->color[1][1][i]; + patch11.color[1][0][i] = 0.5 * (patch->color[1][1][i] + + patch->color[1][0][i]); + patch10.color[1][1][i] = patch11.color[1][0][i]; + patch10.color[1][0][i] = patch->color[1][0][i]; + patch10.color[0][0][i] = 0.5 * (patch->color[1][0][i] + + patch->color[0][0][i]); + patch00.color[1][0][i] = patch10.color[0][0][i]; + patch00.color[1][1][i] = 0.5 * (patch00.color[1][0][i] + + patch01.color[1][1][i]); + patch01.color[1][0][i] = patch00.color[1][1][i]; + patch11.color[0][0][i] = patch00.color[1][1][i]; + patch10.color[0][1][i] = patch00.color[1][1][i]; + } + fillPatch(&patch00, shading, depth + 1); + fillPatch(&patch10, shading, depth + 1); + fillPatch(&patch01, shading, depth + 1); + fillPatch(&patch11, shading, depth + 1); } } @@ -3123,19 +3283,22 @@ void Gfx::opSetCharSpacing(Object args[], int numArgs) { } void Gfx::opSetFont(Object args[], int numArgs) { - GfxFont *font; + doSetFont(res->lookupFont(args[0].getName()), args[1].getNum()); +} - if (!(font = res->lookupFont(args[0].getName()))) { +void Gfx::doSetFont(GfxFont *font, double size) { + if (!font) { + state->setFont(NULL, 0); return; } if (printCommands) { printf(" font: tag=%s name='%s' %g\n", font->getTag()->getCString(), font->getName() ? font->getName()->getCString() : "???", - args[1].getNum()); + size); fflush(stdout); } - state->setFont(font, args[1].getNum()); + state->setFont(font, size); fontChanged = gTrue; } @@ -3343,7 +3506,7 @@ void Gfx::doShowText(GString *s) { double x0, y0, x1, y1; double oldCTM[6], newCTM[6]; double *mat; - Object charProc; + Object charProcRef, charProc; Dict *resDict; Parser *oldParser; GfxState *savedState; @@ -3427,12 +3590,13 @@ void Gfx::doShowText(GString *s) { state->transformDelta(dx, dy, &ddx, &ddy); if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, code, u, uLen)) { - ((Gfx8BitFont *)font)->getCharProc(code, &charProc); + ((Gfx8BitFont *)font)->getCharProcNF(code, &charProcRef); + charProcRef.fetch(xref, &charProc); if ((resDict = ((Gfx8BitFont *)font)->getResources())) { pushResources(resDict); } if (charProc.isStream()) { - display(&charProc, gFalse); + display(&charProcRef, gFalse); } else { error(errSyntaxError, getPos(), "Missing or bad Type3 CharProc entry"); @@ -3442,6 +3606,7 @@ void Gfx::doShowText(GString *s) { popResources(); } charProc.free(); + charProcRef.free(); } restoreStateStack(savedState); curX += tdx; @@ -3592,44 +3757,53 @@ void Gfx::opXObject(Object args[], int numArgs) { obj1.free(); return; } +#if USE_EXCEPTIONS + try { +#endif #if OPI_SUPPORT - obj1.streamGetDict()->lookup("OPI", &opiDict); - if (opiDict.isDict()) { - out->opiBegin(state, opiDict.getDict()); - } + obj1.streamGetDict()->lookup("OPI", &opiDict); + if (opiDict.isDict()) { + out->opiBegin(state, opiDict.getDict()); + } #endif - obj1.streamGetDict()->lookup("Subtype", &obj2); - if (obj2.isName("Image")) { - if (out->needNonText()) { + obj1.streamGetDict()->lookup("Subtype", &obj2); + if (obj2.isName("Image")) { + if (out->needNonText()) { + res->lookupXObjectNF(name, &refObj); + doImage(&refObj, obj1.getStream(), gFalse); + refObj.free(); + } + } else if (obj2.isName("Form")) { res->lookupXObjectNF(name, &refObj); - doImage(&refObj, obj1.getStream(), gFalse); + if (out->useDrawForm() && refObj.isRef()) { + out->drawForm(refObj.getRef()); + } else { + doForm(&refObj, &obj1); + } refObj.free(); - } - } else if (obj2.isName("Form")) { - res->lookupXObjectNF(name, &refObj); - if (out->useDrawForm() && refObj.isRef()) { - out->drawForm(refObj.getRef()); + } else if (obj2.isName("PS")) { + obj1.streamGetDict()->lookup("Level1", &obj3); + out->psXObject(obj1.getStream(), + obj3.isStream() ? obj3.getStream() : (Stream *)NULL); + } else if (obj2.isName()) { + error(errSyntaxError, getPos(), + "Unknown XObject subtype '{0:s}'", obj2.getName()); } else { - doForm(&obj1); - } - refObj.free(); - } else if (obj2.isName("PS")) { - obj1.streamGetDict()->lookup("Level1", &obj3); - out->psXObject(obj1.getStream(), - obj3.isStream() ? obj3.getStream() : (Stream *)NULL); - } else if (obj2.isName()) { - error(errSyntaxError, getPos(), - "Unknown XObject subtype '{0:s}'", obj2.getName()); - } else { - error(errSyntaxError, getPos(), - "XObject subtype is missing or wrong type"); - } - obj2.free(); + error(errSyntaxError, getPos(), + "XObject subtype is missing or wrong type"); + } + obj2.free(); #if OPI_SUPPORT - if (opiDict.isDict()) { - out->opiEnd(state, opiDict.getDict()); + if (opiDict.isDict()) { + out->opiEnd(state, opiDict.getDict()); + } + opiDict.free(); +#endif +#if USE_EXCEPTIONS + } catch (GMemException e) { + obj1.free(); + throw; } - opiDict.free(); #endif obj1.free(); } @@ -3649,6 +3823,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { int maskWidth, maskHeight; GBool maskInvert; Stream *maskStr; + GBool interpolate; Object obj1, obj2; int i, n; @@ -3710,6 +3885,9 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } if (obj1.isInt()) { bits = obj1.getInt(); + if (bits < 1 || bits > 16) { + goto err2; + } } else if (mask) { bits = 1; } else { @@ -3718,6 +3896,15 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); } + // interpolate flag + dict->lookup("Interpolate", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("I", &obj1); + } + interpolate = obj1.isBool() && obj1.getBool(); + obj1.free(); + // display a mask if (mask) { @@ -3751,9 +3938,11 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { // draw it } else { if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternImageMask(ref, str, width, height, invert, inlineImg); + doPatternImageMask(ref, str, width, height, invert, inlineImg, + interpolate); } else { - out->drawImageMask(state, ref, str, width, height, invert, inlineImg); + out->drawImageMask(state, ref, str, width, height, invert, inlineImg, + interpolate); } } @@ -3775,13 +3964,14 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } } if (!obj1.isNull()) { - colorSpace = GfxColorSpace::parse(&obj1); + colorSpace = GfxColorSpace::parse(&obj1 + ); } else if (csMode == streamCSDeviceGray) { - colorSpace = new GfxDeviceGrayColorSpace(); + colorSpace = GfxColorSpace::create(csDeviceGray); } else if (csMode == streamCSDeviceRGB) { - colorSpace = new GfxDeviceRGBColorSpace(); + colorSpace = GfxColorSpace::create(csDeviceRGB); } else if (csMode == streamCSDeviceCMYK) { - colorSpace = new GfxDeviceCMYKColorSpace(); + colorSpace = GfxColorSpace::create(csDeviceCMYK); } else { colorSpace = NULL; } @@ -3860,7 +4050,8 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj2.free(); } } - maskColorSpace = GfxColorSpace::parse(&obj1); + maskColorSpace = GfxColorSpace::parse(&obj1 + ); obj1.free(); if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { goto err1; @@ -3977,14 +4168,17 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } else { if (haveSoftMask) { out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskColorMap); + maskStr, maskWidth, maskHeight, maskColorMap, + interpolate); delete maskColorMap; } else if (haveExplicitMask) { out->drawMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskInvert); + maskStr, maskWidth, maskHeight, maskInvert, + interpolate); } else { out->drawImage(state, ref, str, width, height, colorMap, - haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); + haveColorKeyMask ? maskColors : (int *)NULL, inlineImg, + interpolate); } } @@ -4006,7 +4200,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { error(errSyntaxError, getPos(), "Bad image parameters"); } -void Gfx::doForm(Object *str) { +void Gfx::doForm(Object *strRef, Object *str) { Dict *dict; GBool transpGroup, isolated, knockout; GfxColorSpace *blendingColorSpace; @@ -4087,7 +4281,8 @@ void Gfx::doForm(Object *str) { if (obj1.dictLookup("S", &obj2)->isName("Transparency")) { transpGroup = gTrue; if (!obj1.dictLookup("CS", &obj3)->isNull()) { - blendingColorSpace = GfxColorSpace::parse(&obj3); + blendingColorSpace = GfxColorSpace::parse(&obj3 + ); } obj3.free(); if (obj1.dictLookup("I", &obj3)->isBool()) { @@ -4105,7 +4300,7 @@ void Gfx::doForm(Object *str) { // draw it ++formDepth; - drawForm(str, resDict, m, bbox, + drawForm(strRef, resDict, m, bbox, transpGroup, gFalse, blendingColorSpace, isolated, knockout); --formDepth; @@ -4117,7 +4312,8 @@ void Gfx::doForm(Object *str) { ocState = ocSaved; } -void Gfx::drawForm(Object *str, Dict *resDict, double *matrix, double *bbox, +void Gfx::drawForm(Object *strRef, Dict *resDict, + double *matrix, double *bbox, GBool transpGroup, GBool softMask, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout, @@ -4181,7 +4377,7 @@ void Gfx::drawForm(Object *str, Dict *resDict, double *matrix, double *bbox, } // draw the form - display(str, gFalse); + display(strRef, gFalse); if (softMask || transpGroup) { out->endTransparencyGroup(state); @@ -4210,13 +4406,17 @@ void Gfx::drawForm(Object *str, Dict *resDict, double *matrix, double *bbox, return; } +void Gfx::takeContentStreamStack(Gfx *oldGfx) { + contentStreamStack->append(oldGfx->contentStreamStack); +} + //------------------------------------------------------------------------ // in-line image operators //------------------------------------------------------------------------ void Gfx::opBeginImage(Object args[], int numArgs) { Stream *str; - int c1, c2; + int c1, c2, c3; // NB: this function is run even if ocState is false -- doImage() is // responsible for skipping over the inline image data @@ -4231,9 +4431,11 @@ void Gfx::opBeginImage(Object args[], int numArgs) { // skip 'EI' tag c1 = str->getUndecodedStream()->getChar(); c2 = str->getUndecodedStream()->getChar(); - while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) { + c3 = str->getUndecodedStream()->lookChar(); + while (!(c1 == 'E' && c2 == 'I' && Lexer::isSpace(c3)) && c3 != EOF) { c1 = c2; c2 = str->getUndecodedStream()->getChar(); + c3 = str->getUndecodedStream()->lookChar(); } delete str; } @@ -4328,9 +4530,7 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { GfxMarkedContent *mc; Object obj; GBool ocStateNew; - GString *s; - Unicode *u; - int uLen, i; + TextString *s; GfxMarkedContentKind mcKind; if (printCommands) { @@ -4351,24 +4551,9 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { mcKind = gfxMCOptionalContent; } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) { if (args[1].dictLookup("ActualText", &obj)->isString()) { - s = obj.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - uLen = (s->getLength() - 2) / 2; - u = (Unicode *)gmallocn(uLen, sizeof(Unicode)); - for (i = 0; i < uLen; ++i) { - u[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | - (s->getChar(3 + 2*i) & 0xff); - } - } else { - uLen = s->getLength(); - u = (Unicode *)gmallocn(uLen, sizeof(Unicode)); - for (i = 0; i < uLen; ++i) { - u[i] = pdfDocEncoding[s->getChar(i) & 0xff]; - } - } - out->beginActualText(state, u, uLen); - gfree(u); + s = new TextString(obj.getString()); + out->beginActualText(state, s->getUnicode(), s->getLength()); + delete s; mcKind = gfxMCActualText; } obj.free(); @@ -4416,14 +4601,14 @@ void Gfx::opMarkPoint(Object args[], int numArgs) { // misc //------------------------------------------------------------------------ -void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle, +void Gfx::drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, double xMin, double yMin, double xMax, double yMax) { Dict *dict, *resDict; - Object matrixObj, bboxObj, resObj, obj1; + Object str, matrixObj, bboxObj, resObj, obj1; double formXMin, formYMin, formXMax, formYMax; double x, y, sx, sy, tx, ty; double m[6], bbox[4]; - double r, g, b; + double *borderColor; GfxColor color; double *dash, *dash2; int dashLength; @@ -4439,16 +4624,18 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle, } // draw the appearance stream (if there is one) - if (str->isStream()) { + strRef->fetch(xref, &str); + if (str.isStream()) { // get stream dict - dict = str->streamGetDict(); + dict = str.streamGetDict(); // get the form bounding box dict->lookup("BBox", &bboxObj); if (!bboxObj.isArray()) { - bboxObj.free(); error(errSyntaxError, getPos(), "Bad form bounding box"); + bboxObj.free(); + str.free(); return; } for (i = 0; i < 4; ++i) { @@ -4548,22 +4735,43 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle, resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; // draw it - drawForm(str, resDict, m, bbox); + drawForm(strRef, resDict, m, bbox); resObj.free(); } + str.free(); // draw the border - if (borderStyle && borderStyle->getWidth() > 0) { - if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) { - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceRGBColorSpace()); - out->updateStrokeColorSpace(state); - } - borderStyle->getColor(&r, &g, &b); - color.c[0] = dblToCol(r); - color.c[1] = dblToCol(g); - color.c[2] = dblToCol(b); + if (borderStyle && borderStyle->getWidth() > 0 && + borderStyle->getNumColorComps() > 0) { + borderColor = borderStyle->getColor(); + switch (borderStyle->getNumColorComps()) { + case 1: + if (state->getStrokeColorSpace()->getMode() != csDeviceGray) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); + out->updateStrokeColorSpace(state); + } + break; + case 3: + if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceRGB)); + out->updateStrokeColorSpace(state); + } + break; + case 4: + if (state->getStrokeColorSpace()->getMode() != csDeviceCMYK) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(GfxColorSpace::create(csDeviceCMYK)); + out->updateStrokeColorSpace(state); + } + break; + } + color.c[0] = dblToCol(borderColor[0]); + color.c[1] = dblToCol(borderColor[1]); + color.c[2] = dblToCol(borderColor[2]); + color.c[3] = dblToCol(borderColor[3]); state->setStrokeColor(&color); out->updateStrokeColor(state); state->setLineWidth(borderStyle->getWidth()); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Gfx.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Gfx.h index 2753766ad18..b7347771861 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Gfx.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Gfx.h @@ -16,6 +16,7 @@ #endif #include "gtypes.h" +#include "gfile.h" class GString; class GList; @@ -84,13 +85,16 @@ public: ~GfxResources(); GfxFont *lookupFont(char *name); - GBool lookupXObject(char *name, Object *obj); - GBool lookupXObjectNF(char *name, Object *obj); - void lookupColorSpace(char *name, Object *obj); - GfxPattern *lookupPattern(char *name); - GfxShading *lookupShading(char *name); - GBool lookupGState(char *name, Object *obj); - GBool lookupPropertiesNF(char *name, Object *obj); + GfxFont *lookupFontByRef(Ref ref); + GBool lookupXObject(const char *name, Object *obj); + GBool lookupXObjectNF(const char *name, Object *obj); + void lookupColorSpace(const char *name, Object *obj); + GfxPattern *lookupPattern(const char *name + ); + GfxShading *lookupShading(const char *name + ); + GBool lookupGState(const char *name, Object *obj); + GBool lookupPropertiesNF(const char *name, Object *obj); GfxResources *getNext() { return next; } @@ -152,12 +156,13 @@ public: ~Gfx(); - // Interpret a stream or array of streams. - void display(Object *obj, GBool topLevel = gTrue); + // Interpret a stream or array of streams. <objRef> should be a + // reference wherever possible (for loop-checking). + void display(Object *objRef, GBool topLevel = gTrue); // Display an annotation, given its appearance (a Form XObject), // border style, and bounding box (in default user space). - void drawAnnot(Object *str, AnnotBorderStyle *borderStyle, + void drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, double xMin, double yMin, double xMax, double yMax); // Save graphics state. @@ -169,13 +174,21 @@ public: // Get the current graphics state object. GfxState *getState() { return state; } - void drawForm(Object *str, Dict *resDict, double *matrix, double *bbox, + void drawForm(Object *strRef, Dict *resDict, double *matrix, double *bbox, GBool transpGroup = gFalse, GBool softMask = gFalse, GfxColorSpace *blendingColorSpace = NULL, GBool isolated = gFalse, GBool knockout = gFalse, GBool alpha = gFalse, Function *transferFunc = NULL, GfxColor *backdropColor = NULL); + // Take all of the content stream stack entries from <oldGfx>. This + // is useful when creating a new Gfx object to handle a pattern, + // etc., where it's useful to check for loops that span both Gfx + // objects. This function should be called immediately after the + // Gfx constructor, i.e., before processing any content streams with + // the new Gfx object. + void takeContentStreamStack(Gfx *oldGfx); + private: PDFDoc *doc; @@ -201,6 +214,8 @@ private: GList *markedContentStack; // BMC/BDC/EMC stack [GfxMarkedContent] Parser *parser; // parser for page content stream(s) + GList *contentStreamStack; // stack of open content streams, used + // for loop-checking GBool // callback to check for an abort (*abortCheckCbk)(void *data); @@ -208,11 +223,12 @@ private: static Operator opTab[]; // table of operators + GBool checkForContentStreamLoop(Object *ref); void go(GBool topLevel); - void execOp(Object *cmd, Object args[], int numArgs); + GBool execOp(Object *cmd, Object args[], int numArgs); Operator *findOp(char *name); GBool checkArg(Object *arg, TchkType type); - int getPos(); + GFileOffset getPos(); // graphics state operators void opSave(Object args[], int numArgs); @@ -225,7 +241,7 @@ private: void opSetMiterLimit(Object args[], int numArgs); void opSetLineWidth(Object args[], int numArgs); void opSetExtGState(Object args[], int numArgs); - void doSoftMask(Object *str, GBool alpha, + void doSoftMask(Object *str, Object *strRef, GBool alpha, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout, Function *transferFunc, GfxColor *backdropColor); @@ -268,7 +284,7 @@ private: void doPatternStroke(); void doPatternText(); void doPatternImageMask(Object *ref, Stream *str, int width, int height, - GBool invert, GBool inlineImg); + GBool invert, GBool inlineImg, GBool interpolate); void doTilingPatternFill(GfxTilingPattern *tPat, GBool stroke, GBool eoFill, GBool text); void doShadingPatternFill(GfxShadingPattern *sPat, @@ -282,12 +298,12 @@ private: void doAxialShFill(GfxAxialShading *shading); void doRadialShFill(GfxRadialShading *shading); void doGouraudTriangleShFill(GfxGouraudTriangleShading *shading); - void gouraudFillTriangle(double x0, double y0, GfxColor *color0, - double x1, double y1, GfxColor *color1, - double x2, double y2, GfxColor *color2, - int nComps, int depth); + void gouraudFillTriangle(double x0, double y0, double *color0, + double x1, double y1, double *color1, + double x2, double y2, double *color2, + GfxGouraudTriangleShading *shading, int depth); void doPatchMeshShFill(GfxPatchMeshShading *shading); - void fillPatch(GfxPatch *patch, int nComps, int depth); + void fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth); void doEndPath(); // path clipping operators @@ -301,6 +317,7 @@ private: // text state operators void opSetCharSpacing(Object args[], int numArgs); void opSetFont(Object args[], int numArgs); + void doSetFont(GfxFont *font, double size); void opSetTextLeading(Object args[], int numArgs); void opSetTextRender(Object args[], int numArgs); void opSetTextRise(Object args[], int numArgs); @@ -324,7 +341,7 @@ private: // XObject operators void opXObject(Object args[], int numArgs); void doImage(Object *ref, Stream *str, GBool inlineImg); - void doForm(Object *str); + void doForm(Object *strRef, Object *str); // in-line image operators void opBeginImage(Object args[], int numArgs); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxFont.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxFont.cc index aa88e78dea9..0ebb5b95cc8 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxFont.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxFont.cc @@ -146,6 +146,7 @@ static int readFromStream(void *data) { GfxFontLoc::GfxFontLoc() { path = NULL; fontNum = 0; + oblique = 0; encoding = NULL; substIdx = -1; } @@ -175,6 +176,8 @@ GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) { fontDict->lookup("BaseFont", &obj1); if (obj1.isName()) { nameA = new GString(obj1.getName()); + } else if (obj1.isString()) { + nameA = obj1.getString()->copy(); } obj1.free(); @@ -451,7 +454,7 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { } // some broken font descriptors set ascent and descent to 0; // others set it to ridiculous values (e.g., 32768) - if (t != 0 && t < 3) { + if (t != 0 && t < 1.9) { ascent = t; } } @@ -464,7 +467,7 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { t = -t; } // some broken font descriptors set ascent and descent to 0 - if (t != 0 && t > -3) { + if (t != 0 && t > -1.9) { descent = t; } } @@ -489,7 +492,8 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, CharCodeToUnicode *ctu) { GString *buf; Object obj1; - int c; + char buf2[4096]; + int n; if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) { obj1.free(); @@ -497,8 +501,8 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, } buf = new GString(); obj1.streamReset(); - while ((c = obj1.streamGetChar()) != EOF) { - buf->append(c); + while ((n = obj1.streamGetBlock(buf2, sizeof(buf2))) > 0) { + buf->append(buf2, n); } obj1.streamClose(); obj1.free(); @@ -518,6 +522,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { PSFontParam16 *psFont16; Object refObj, embFontObj; int substIdx, fontNum; + double oblique; GBool embed; if (type == fontType3) { @@ -570,7 +575,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { } //----- PS passthrough - if (ps && !isCIDFont() && globalParams->getPSFontPassthrough()) { + if (ps && name && !isCIDFont() && globalParams->getPSFontPassthrough()) { fontLoc = new GfxFontLoc(); fontLoc->locType = gfxFontLocResident; fontLoc->fontType = fontType1; @@ -578,6 +583,13 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { return fontLoc; } + //----- external font file (fontFile, fontDir) + if (name && (path = globalParams->findFontFile(name))) { + if ((fontLoc = getExternalFont(path, 0, 0, isCIDFont()))) { + return fontLoc; + } + } + //----- PS resident Base-14 font if (ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) { fontLoc = new GfxFontLoc(); @@ -587,28 +599,19 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { return fontLoc; } - //----- external font file (fontFile, fontDir) - if ((path = globalParams->findFontFile(name))) { - if ((fontLoc = getExternalFont(path, isCIDFont()))) { - return fontLoc; - } - } - //----- external font file for Base-14 font if (!ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) { base14Name = new GString(((Gfx8BitFont *)this)->base14->base14Name); - if ((path = globalParams->findFontFile(base14Name))) { - if ((fontLoc = getExternalFont(path, gFalse))) { - delete base14Name; - return fontLoc; - } - } + path = globalParams->findBase14FontFile(base14Name, &fontNum, &oblique); delete base14Name; + if (path && (fontLoc = getExternalFont(path, fontNum, oblique, gFalse))) { + return fontLoc; + } } //----- system font - if ((path = globalParams->findSystemFontFile(name, &sysFontType, - &fontNum))) { + if (name && (path = globalParams->findSystemFontFile(name, &sysFontType, + &fontNum))) { if (isCIDFont()) { if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) { fontLoc = new GfxFontLoc(); @@ -624,13 +627,13 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { fontLoc->locType = gfxFontLocExternal; fontLoc->fontType = fontTrueType; fontLoc->path = path; + fontLoc->fontNum = fontNum; return fontLoc; } else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) { fontLoc = new GfxFontLoc(); fontLoc->locType = gfxFontLocExternal; fontLoc->fontType = fontType1; fontLoc->path = path; - fontLoc->fontNum = fontNum; return fontLoc; } } @@ -641,7 +644,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { //----- 8-bit PS resident font if (ps) { - if ((path = globalParams->getPSResidentFont(name))) { + if (name && (path = globalParams->getPSResidentFont(name))) { fontLoc = new GfxFontLoc(); fontLoc->locType = gfxFontLocResident; fontLoc->fontType = fontType1; @@ -675,10 +678,10 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { fontLoc->substIdx = substIdx; return fontLoc; } else { - path = globalParams->findFontFile(substName); + path = globalParams->findBase14FontFile(substName, &fontNum, &oblique); delete substName; if (path) { - if ((fontLoc = getExternalFont(path, gFalse))) { + if ((fontLoc = getExternalFont(path, fontNum, oblique, gFalse))) { error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'", base14SubstFonts[substIdx], name); fontLoc->substIdx = substIdx; @@ -692,7 +695,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { } //----- 16-bit PS resident font - if (ps && ((psFont16 = globalParams->getPSResidentFont16( + if (ps && name && ((psFont16 = globalParams->getPSResidentFont16( name, ((GfxCIDFont *)this)->getWMode())))) { fontLoc = new GfxFontLoc(); @@ -720,7 +723,7 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { //----- CID font substitution if ((path = globalParams->findCCFontFile( ((GfxCIDFont *)this)->getCollection()))) { - if ((fontLoc = getExternalFont(path, gTrue))) { + if ((fontLoc = getExternalFont(path, 0, 0, gTrue))) { error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'", fontLoc->path, name); return fontLoc; @@ -733,15 +736,18 @@ GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) { GfxFontLoc *GfxFont::locateBase14Font(GString *base14Name) { GString *path; + int fontNum; + double oblique; - path = globalParams->findFontFile(base14Name); + path = globalParams->findBase14FontFile(base14Name, &fontNum, &oblique); if (!path) { return NULL; } - return getExternalFont(path, gFalse); + return getExternalFont(path, fontNum, oblique, gFalse); } -GfxFontLoc *GfxFont::getExternalFont(GString *path, GBool cid) { +GfxFontLoc *GfxFont::getExternalFont(GString *path, int fontNum, + double oblique, GBool cid) { FoFiIdentifierType fft; GfxFontType fontType; GfxFontLoc *fontLoc; @@ -768,6 +774,9 @@ GfxFontLoc *GfxFont::getExternalFont(GString *path, GBool cid) { case fofiIdOpenTypeCFFCID: fontType = fontCIDType0COT; break; + case fofiIdDfont: + fontType = cid ? fontCIDType2 : fontTrueType; + break; case fofiIdUnknown: case fofiIdError: default: @@ -784,6 +793,8 @@ GfxFontLoc *GfxFont::getExternalFont(GString *path, GBool cid) { fontLoc->locType = gfxFontLocExternal; fontLoc->fontType = fontType; fontLoc->path = path; + fontLoc->fontNum = fontNum; + fontLoc->oblique = oblique; return fontLoc; } @@ -791,8 +802,7 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) { char *buf; Object obj1, obj2; Stream *str; - int c; - int size, i; + int size, n; obj1.initRef(embFontID.num, embFontID.gen); obj1.fetch(xref, &obj2); @@ -805,21 +815,19 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) { } str = obj2.getStream(); + size = 0; buf = NULL; - i = size = 0; str->reset(); - while ((c = str->getChar()) != EOF) { - if (i == size) { - if (size > INT_MAX - 4096) { - error(errSyntaxError, -1, "Embedded font file is too large"); - break; - } - size += 4096; - buf = (char *)grealloc(buf, size); - } - buf[i++] = c; - } - *len = i; + do { + if (size > INT_MAX - 4096) { + error(errSyntaxError, -1, "Embedded font file is too large"); + break; + } + buf = (char *)grealloc(buf, size + 4096); + n = str->getBlock(buf + size, 4096); + size += n; + } while (n == 4096); + *len = size; str->close(); obj2.free(); @@ -908,8 +916,8 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, fontBBox[2] = 0.001 * builtinFont->bbox[2]; fontBBox[3] = 0.001 * builtinFont->bbox[3]; } else { - ascent = 0.95; - descent = -0.35; + ascent = 0.75; + descent = -0.25; fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; } @@ -1491,6 +1499,15 @@ Object *Gfx8BitFont::getCharProc(int code, Object *proc) { return proc; } +Object *Gfx8BitFont::getCharProcNF(int code, Object *proc) { + if (enc[code] && charProcs.isDict()) { + charProcs.dictLookupNF(enc[code], proc); + } else { + proc->initNull(); + } + return proc; +} + Dict *Gfx8BitFont::getResources() { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } @@ -1565,7 +1582,6 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, error(errSyntaxError, -1, "Missing or empty DescendantFonts entry in Type 0 font"); obj1.free(); - goto err1; } if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) { @@ -1661,6 +1677,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, } cidToGID[cidToGIDLen++] = (c1 << 8) + c2; } + obj1.streamClose(); } else if (!obj1.isName("Identity") && !obj1.isNull()) { error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font"); } @@ -1836,7 +1853,8 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, err2: obj1.free(); desFontDictObj.free(); - err1:; + err1: + error(errSyntaxError, -1, "Failed to parse font object for '{0:t}'", name); } GfxCIDFont::~GfxCIDFont() { @@ -2016,3 +2034,16 @@ GfxFont *GfxFontDict::lookup(char *tag) { } return NULL; } + +GfxFont *GfxFontDict::lookupByRef(Ref ref) { + int i; + + for (i = 0; i < numFonts; ++i) { + if (fonts[i] && + fonts[i]->getID()->num == ref.num && + fonts[i]->getID()->gen == ref.gen) { + return fonts[i]; + } + } + return NULL; +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxFont.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxFont.h index db45ef043da..1ec46ec5bf1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxFont.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxFont.h @@ -100,8 +100,11 @@ public: // (if locType == gfxFontLocExternal) // PS font name // (if locType == gfxFontLocResident) - int fontNum; // for TrueType collections + int fontNum; // for TrueType collections and Mac dfonts // (if locType == gfxFontLocExternal) + double oblique; // sheer factor to oblique this font + // (used when substituting a plain + // font for an oblique font) GString *encoding; // PS font encoding, only for 16-bit fonts // (if locType == gfxFontLocResident) int wMode; // writing mode, only for 16-bit fonts @@ -207,7 +210,8 @@ protected: void readFontDescriptor(XRef *xref, Dict *fontDict); CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits, CharCodeToUnicode *ctu); - static GfxFontLoc *getExternalFont(GString *path, GBool cid); + static GfxFontLoc *getExternalFont(GString *path, int fontNum, + double oblique, GBool cid); GString *tag; // PDF font tag Ref id; // reference (used as unique ID) @@ -267,6 +271,7 @@ public: // Return the Type 3 CharProc for the character associated with <code>. Object *getCharProc(int code, Object *proc); + Object *getCharProcNF(int code, Object *proc); // Return the Type 3 Resources dictionary, or NULL if none. Dict *getResources(); @@ -347,6 +352,7 @@ public: // Get the specified font. GfxFont *lookup(char *tag); + GfxFont *lookupByRef(Ref ref); // Iterative access. int getNumFonts() { return numFonts; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxState.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxState.cc index cf5e7c2570c..bdaa5e6a72f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxState.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxState.cc @@ -20,6 +20,7 @@ #include "Object.h" #include "Array.h" #include "Page.h" +#include "XRef.h" #include "GfxState.h" //------------------------------------------------------------------------ @@ -28,7 +29,6 @@ // loops in the color space object structure. #define colorSpaceRecursionLimit 8 - //------------------------------------------------------------------------ static inline GfxColorComp clip01(GfxColorComp x) { @@ -101,7 +101,8 @@ GfxColorSpace::GfxColorSpace() { GfxColorSpace::~GfxColorSpace() { } -GfxColorSpace *GfxColorSpace::parse(Object *csObj, int recursion) { +GfxColorSpace *GfxColorSpace::parse(Object *csObj, + int recursion) { GfxColorSpace *cs; Object obj1; @@ -112,11 +113,11 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj, int recursion) { cs = NULL; if (csObj->isName()) { if (csObj->isName("DeviceGray") || csObj->isName("G")) { - cs = new GfxDeviceGrayColorSpace(); + cs = GfxColorSpace::create(csDeviceGray); } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) { - cs = new GfxDeviceRGBColorSpace(); + cs = GfxColorSpace::create(csDeviceRGB); } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) { - cs = new GfxDeviceCMYKColorSpace(); + cs = GfxColorSpace::create(csDeviceCMYK); } else if (csObj->isName("Pattern")) { cs = new GfxPatternColorSpace(NULL); } else { @@ -125,11 +126,11 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj, int recursion) { } else if (csObj->isArray() && csObj->arrayGetLength() > 0) { csObj->arrayGet(0, &obj1); if (obj1.isName("DeviceGray") || obj1.isName("G")) { - cs = new GfxDeviceGrayColorSpace(); + cs = GfxColorSpace::create(csDeviceGray); } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) { - cs = new GfxDeviceRGBColorSpace(); + cs = GfxColorSpace::create(csDeviceRGB); } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) { - cs = new GfxDeviceCMYKColorSpace(); + cs = GfxColorSpace::create(csDeviceCMYK); } else if (obj1.isName("CalGray")) { cs = GfxCalGrayColorSpace::parse(csObj->getArray(), recursion); } else if (obj1.isName("CalRGB")) { @@ -137,15 +138,20 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj, int recursion) { } else if (obj1.isName("Lab")) { cs = GfxLabColorSpace::parse(csObj->getArray(), recursion); } else if (obj1.isName("ICCBased")) { - cs = GfxICCBasedColorSpace::parse(csObj->getArray(), recursion); + cs = GfxICCBasedColorSpace::parse(csObj->getArray(), + recursion); } else if (obj1.isName("Indexed") || obj1.isName("I")) { - cs = GfxIndexedColorSpace::parse(csObj->getArray(), recursion); + cs = GfxIndexedColorSpace::parse(csObj->getArray(), + recursion); } else if (obj1.isName("Separation")) { - cs = GfxSeparationColorSpace::parse(csObj->getArray(), recursion); + cs = GfxSeparationColorSpace::parse(csObj->getArray(), + recursion); } else if (obj1.isName("DeviceN")) { - cs = GfxDeviceNColorSpace::parse(csObj->getArray(), recursion); + cs = GfxDeviceNColorSpace::parse(csObj->getArray(), + recursion); } else if (obj1.isName("Pattern")) { - cs = GfxPatternColorSpace::parse(csObj->getArray(), recursion); + cs = GfxPatternColorSpace::parse(csObj->getArray(), + recursion); } else { error(errSyntaxError, -1, "Bad color space"); } @@ -156,6 +162,20 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj, int recursion) { return cs; } +GfxColorSpace *GfxColorSpace::create(GfxColorSpaceMode mode) { + GfxColorSpace *cs; + + cs = NULL; + if (mode == csDeviceGray) { + cs = new GfxDeviceGrayColorSpace(); + } else if (mode == csDeviceRGB) { + cs = new GfxDeviceRGBColorSpace(); + } else if (mode == csDeviceCMYK) { + cs = new GfxDeviceCMYKColorSpace(); + } + return cs; +} + void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) { int i; @@ -185,9 +205,13 @@ GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { } GfxColorSpace *GfxDeviceGrayColorSpace::copy() { - return new GfxDeviceGrayColorSpace(); + GfxDeviceGrayColorSpace *cs; + + cs = new GfxDeviceGrayColorSpace(); + return cs; } + void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) { *gray = clip01(color->c[0]); } @@ -233,6 +257,7 @@ GfxColorSpace *GfxCalGrayColorSpace::copy() { return cs; } + GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, int recursion) { GfxCalGrayColorSpace *cs; Object obj1, obj2, obj3; @@ -311,9 +336,13 @@ GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { } GfxColorSpace *GfxDeviceRGBColorSpace::copy() { - return new GfxDeviceRGBColorSpace(); + GfxDeviceRGBColorSpace *cs; + + cs = new GfxDeviceRGBColorSpace(); + return cs; } + void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { *gray = clip01((GfxColorComp)(0.3 * color->c[0] + 0.59 * color->c[1] + @@ -456,6 +485,7 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, int recursion) { return cs; } + void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { *gray = clip01((GfxColorComp)(0.299 * color->c[0] + 0.587 * color->c[1] + @@ -505,9 +535,13 @@ GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { } GfxColorSpace *GfxDeviceCMYKColorSpace::copy() { - return new GfxDeviceCMYKColorSpace(); + GfxDeviceCMYKColorSpace *cs; + + cs = new GfxDeviceCMYKColorSpace(); + return cs; } + void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray) { *gray = clip01((GfxColorComp)(gfxColorComp1 - color->c[3] - 0.3 * color->c[0] @@ -706,6 +740,7 @@ GfxColorSpace *GfxLabColorSpace::parse(Array *arr, int recursion) { return cs; } + void GfxLabColorSpace::getGray(GfxColor *color, GfxGray *gray) { GfxRGB rgb; @@ -720,6 +755,7 @@ void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { double t1, t2; double r, g, b; + // convert L*a*b* to CIE 1931 XYZ color space t1 = (colToDbl(color->c[0]) + 16) / 116; t2 = t1 + colToDbl(color->c[1]) / 500; @@ -756,6 +792,7 @@ void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { GfxRGB rgb; GfxColorComp c, m, y, k; + getRGB(color, &rgb); c = clip01(gfxColorComp1 - rgb.r); m = clip01(gfxColorComp1 - rgb.g); @@ -831,7 +868,8 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() { return cs; } -GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, int recursion) { +GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, + int recursion) { GfxICCBasedColorSpace *cs; Ref iccProfileStreamA; int nCompsA; @@ -874,16 +912,17 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, int recursion) { nCompsA = 4; } if (dict->lookup("Alternate", &obj2)->isNull() || - !(altA = GfxColorSpace::parse(&obj2, recursion + 1))) { + !(altA = GfxColorSpace::parse(&obj2, + recursion + 1))) { switch (nCompsA) { case 1: - altA = new GfxDeviceGrayColorSpace(); + altA = GfxColorSpace::create(csDeviceGray); break; case 3: - altA = new GfxDeviceRGBColorSpace(); + altA = GfxColorSpace::create(csDeviceRGB); break; case 4: - altA = new GfxDeviceCMYKColorSpace(); + altA = GfxColorSpace::create(csDeviceCMYK); break; default: error(errSyntaxError, -1, "Bad ICCBased color space - invalid N"); @@ -910,6 +949,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, int recursion) { return cs; } + void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray) { alt->getGray(color, gray); } @@ -981,7 +1021,8 @@ GfxColorSpace *GfxIndexedColorSpace::copy() { return cs; } -GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, int recursion) { +GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, + int recursion) { GfxIndexedColorSpace *cs; GfxColorSpace *baseA; int indexHighA; @@ -995,7 +1036,8 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, int recursion) { goto err1; } arr->get(1, &obj1); - if (!(baseA = GfxColorSpace::parse(&obj1, recursion + 1))) { + if (!(baseA = GfxColorSpace::parse(&obj1, + recursion + 1))) { error(errSyntaxError, -1, "Bad Indexed color space (base color space)"); goto err2; } @@ -1060,6 +1102,7 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, int recursion) { return NULL; } + GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color, GfxColor *baseColor) { Guchar *p; @@ -1146,12 +1189,16 @@ GfxSeparationColorSpace::~GfxSeparationColorSpace() { } GfxColorSpace *GfxSeparationColorSpace::copy() { - return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(), - nonMarking, overprintMask); + GfxSeparationColorSpace *cs; + + cs = new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(), + nonMarking, overprintMask); + return cs; } //~ handle the 'All' and 'None' colorants -GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, int recursion) { +GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, + int recursion) { GfxSeparationColorSpace *cs; GString *nameA; GfxColorSpace *altA; @@ -1169,7 +1216,8 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, int recursion) { nameA = new GString(obj1.getName()); obj1.free(); arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1, recursion + 1))) { + if (!(altA = GfxColorSpace::parse(&obj1, + recursion + 1))) { error(errSyntaxError, -1, "Bad Separation color space (alternate color space)"); goto err3; @@ -1193,6 +1241,7 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, int recursion) { return NULL; } + void GfxSeparationColorSpace::getGray(GfxColor *color, GfxGray *gray) { double x; double c[gfxColorMaxComps]; @@ -1303,12 +1352,16 @@ GfxDeviceNColorSpace::~GfxDeviceNColorSpace() { } GfxColorSpace *GfxDeviceNColorSpace::copy() { - return new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(), - nonMarking, overprintMask); + GfxDeviceNColorSpace *cs; + + cs = new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(), + nonMarking, overprintMask); + return cs; } //~ handle the 'None' colorant -GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, int recursion) { +GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, + int recursion) { GfxDeviceNColorSpace *cs; int nCompsA; GString *namesA[gfxColorMaxComps]; @@ -1343,7 +1396,8 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, int recursion) { } obj1.free(); arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1, recursion + 1))) { + if (!(altA = GfxColorSpace::parse(&obj1, + recursion + 1))) { error(errSyntaxError, -1, "Bad DeviceN color space (alternate color space)"); goto err3; @@ -1369,6 +1423,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, int recursion) { return NULL; } + void GfxDeviceNColorSpace::getGray(GfxColor *color, GfxGray *gray) { double x[gfxColorMaxComps], c[gfxColorMaxComps]; GfxColor color2; @@ -1438,11 +1493,15 @@ GfxPatternColorSpace::~GfxPatternColorSpace() { } GfxColorSpace *GfxPatternColorSpace::copy() { - return new GfxPatternColorSpace(under ? under->copy() : - (GfxColorSpace *)NULL); + GfxPatternColorSpace *cs; + + cs = new GfxPatternColorSpace(under ? under->copy() : + (GfxColorSpace *)NULL); + return cs; } -GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, int recursion) { +GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, + int recursion) { GfxPatternColorSpace *cs; GfxColorSpace *underA; Object obj1; @@ -1454,7 +1513,8 @@ GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, int recursion) { underA = NULL; if (arr->getLength() == 2) { arr->get(1, &obj1); - if (!(underA = GfxColorSpace::parse(&obj1, recursion + 1))) { + if (!(underA = GfxColorSpace::parse(&obj1, + recursion + 1))) { error(errSyntaxError, -1, "Bad Pattern color space (underlying color space)"); obj1.free(); @@ -1466,6 +1526,7 @@ GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, int recursion) { return cs; } + void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray) { *gray = 0; } @@ -1495,24 +1556,26 @@ GfxPattern::GfxPattern(int typeA) { GfxPattern::~GfxPattern() { } -GfxPattern *GfxPattern::parse(Object *obj) { +GfxPattern *GfxPattern::parse(Object *objRef, Object *obj + ) { GfxPattern *pattern; - Object obj1; + Object typeObj; if (obj->isDict()) { - obj->dictLookup("PatternType", &obj1); + obj->dictLookup("PatternType", &typeObj); } else if (obj->isStream()) { - obj->streamGetDict()->lookup("PatternType", &obj1); + obj->streamGetDict()->lookup("PatternType", &typeObj); } else { return NULL; } pattern = NULL; - if (obj1.isInt() && obj1.getInt() == 1) { - pattern = GfxTilingPattern::parse(obj); - } else if (obj1.isInt() && obj1.getInt() == 2) { - pattern = GfxShadingPattern::parse(obj); + if (typeObj.isInt() && typeObj.getInt() == 1) { + pattern = GfxTilingPattern::parse(objRef, obj); + } else if (typeObj.isInt() && typeObj.getInt() == 2) { + pattern = GfxShadingPattern::parse(obj + ); } - obj1.free(); + typeObj.free(); return pattern; } @@ -1520,7 +1583,7 @@ GfxPattern *GfxPattern::parse(Object *obj) { // GfxTilingPattern //------------------------------------------------------------------------ -GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) { +GfxTilingPattern *GfxTilingPattern::parse(Object *patObjRef, Object *patObj) { GfxTilingPattern *pat; Dict *dict; int paintTypeA, tilingTypeA; @@ -1597,7 +1660,7 @@ GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) { obj1.free(); pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA, - &resDictA, matrixA, patObj); + &resDictA, matrixA, patObjRef); resDictA.free(); return pat; } @@ -1605,7 +1668,7 @@ GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) { GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA, double *bboxA, double xStepA, double yStepA, Object *resDictA, double *matrixA, - Object *contentStreamA): + Object *contentStreamRefA): GfxPattern(1) { int i; @@ -1621,24 +1684,25 @@ GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA, for (i = 0; i < 6; ++i) { matrix[i] = matrixA[i]; } - contentStreamA->copy(&contentStream); + contentStreamRefA->copy(&contentStreamRef); } GfxTilingPattern::~GfxTilingPattern() { resDict.free(); - contentStream.free(); + contentStreamRef.free(); } GfxPattern *GfxTilingPattern::copy() { return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep, - &resDict, matrix, &contentStream); + &resDict, matrix, &contentStreamRef); } //------------------------------------------------------------------------ // GfxShadingPattern //------------------------------------------------------------------------ -GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) { +GfxShadingPattern *GfxShadingPattern::parse(Object *patObj + ) { Dict *dict; GfxShading *shadingA; double matrixA[6]; @@ -1651,7 +1715,8 @@ GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) { dict = patObj->getDict(); dict->lookup("Shading", &obj1); - shadingA = GfxShading::parse(&obj1); + shadingA = GfxShading::parse(&obj1 + ); obj1.free(); if (!shadingA) { return NULL; @@ -1724,7 +1789,8 @@ GfxShading::~GfxShading() { } } -GfxShading *GfxShading::parse(Object *obj) { +GfxShading *GfxShading::parse(Object *obj + ) { GfxShading *shading; Dict *dict; int typeA; @@ -1748,17 +1814,21 @@ GfxShading *GfxShading::parse(Object *obj) { switch (typeA) { case 1: - shading = GfxFunctionShading::parse(dict); + shading = GfxFunctionShading::parse(dict + ); break; case 2: - shading = GfxAxialShading::parse(dict); + shading = GfxAxialShading::parse(dict + ); break; case 3: - shading = GfxRadialShading::parse(dict); + shading = GfxRadialShading::parse(dict + ); break; case 4: if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream()); + shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream() + ); } else { error(errSyntaxError, -1, "Invalid Type 4 shading object"); goto err1; @@ -1766,7 +1836,8 @@ GfxShading *GfxShading::parse(Object *obj) { break; case 5: if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream()); + shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream() + ); } else { error(errSyntaxError, -1, "Invalid Type 5 shading object"); goto err1; @@ -1774,7 +1845,8 @@ GfxShading *GfxShading::parse(Object *obj) { break; case 6: if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(6, dict, obj->getStream()); + shading = GfxPatchMeshShading::parse(6, dict, obj->getStream() + ); } else { error(errSyntaxError, -1, "Invalid Type 6 shading object"); goto err1; @@ -1782,7 +1854,8 @@ GfxShading *GfxShading::parse(Object *obj) { break; case 7: if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(7, dict, obj->getStream()); + shading = GfxPatchMeshShading::parse(7, dict, obj->getStream() + ); } else { error(errSyntaxError, -1, "Invalid Type 7 shading object"); goto err1; @@ -1799,12 +1872,14 @@ GfxShading *GfxShading::parse(Object *obj) { return NULL; } -GBool GfxShading::init(Dict *dict) { +GBool GfxShading::init(Dict *dict + ) { Object obj1, obj2; int i; dict->lookup("ColorSpace", &obj1); - if (!(colorSpace = GfxColorSpace::parse(&obj1))) { + if (!(colorSpace = GfxColorSpace::parse(&obj1 + ))) { error(errSyntaxError, -1, "Bad color space in shading dictionary"); obj1.free(); return gFalse; @@ -1901,7 +1976,8 @@ GfxFunctionShading::~GfxFunctionShading() { } } -GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) { +GfxFunctionShading *GfxFunctionShading::parse(Dict *dict + ) { GfxFunctionShading *shading; double x0A, y0A, x1A, y1A; double matrixA[6]; @@ -1916,9 +1992,9 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) { obj1.arrayGetLength() == 4) { x0A = obj1.arrayGet(0, &obj2)->getNum(); obj2.free(); - y0A = obj1.arrayGet(1, &obj2)->getNum(); + x1A = obj1.arrayGet(1, &obj2)->getNum(); obj2.free(); - x1A = obj1.arrayGet(2, &obj2)->getNum(); + y0A = obj1.arrayGet(2, &obj2)->getNum(); obj2.free(); y1A = obj1.arrayGet(3, &obj2)->getNum(); obj2.free(); @@ -1970,7 +2046,8 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) { shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA, funcsA, nFuncsA); - if (!shading->init(dict)) { + if (!shading->init(dict + )) { delete shading; return NULL; } @@ -2060,7 +2137,8 @@ GfxAxialShading::~GfxAxialShading() { } } -GfxAxialShading *GfxAxialShading::parse(Dict *dict) { +GfxAxialShading *GfxAxialShading::parse(Dict *dict + ) { GfxAxialShading *shading; double x0A, y0A, x1A, y1A; double t0A, t1A; @@ -2137,7 +2215,8 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict) { shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A, funcsA, nFuncsA, extend0A, extend1A); - if (!shading->init(dict)) { + if (!shading->init(dict + )) { delete shading; return NULL; } @@ -2226,7 +2305,8 @@ GfxRadialShading::~GfxRadialShading() { } } -GfxRadialShading *GfxRadialShading::parse(Dict *dict) { +GfxRadialShading *GfxRadialShading::parse(Dict *dict + ) { GfxRadialShading *shading; double x0A, y0A, r0A, x1A, y1A, r1A; double t0A, t1A; @@ -2307,7 +2387,8 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict) { shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A, funcsA, nFuncsA, extend0A, extend1A); - if (!shading->init(dict)) { + if (!shading->init(dict + )) { delete shading; return NULL; } @@ -2413,7 +2494,7 @@ GfxGouraudTriangleShading::GfxGouraudTriangleShading( int typeA, GfxGouraudVertex *verticesA, int nVerticesA, int (*trianglesA)[3], int nTrianglesA, - Function **funcsA, int nFuncsA): + int nCompsA, Function **funcsA, int nFuncsA): GfxShading(typeA) { int i; @@ -2422,6 +2503,7 @@ GfxGouraudTriangleShading::GfxGouraudTriangleShading( nVertices = nVerticesA; triangles = trianglesA; nTriangles = nTrianglesA; + nComps = nCompsA; nFuncs = nFuncsA; for (i = 0; i < nFuncs; ++i) { funcs[i] = funcsA[i]; @@ -2440,6 +2522,7 @@ GfxGouraudTriangleShading::GfxGouraudTriangleShading( nTriangles = shading->nTriangles; triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int)); memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int)); + nComps = shading->nComps; nFuncs = shading->nFuncs; for (i = 0; i < nFuncs; ++i) { funcs[i] = shading->funcs[i]->copy(); @@ -2456,9 +2539,9 @@ GfxGouraudTriangleShading::~GfxGouraudTriangleShading() { } } -GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, - Dict *dict, - Stream *str) { +GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse( + int typeA, Dict *dict, Stream *str + ) { GfxGouraudTriangleShading *shading; Function *funcsA[gfxColorMaxComps]; int nFuncsA; @@ -2469,7 +2552,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, double cMul[gfxColorMaxComps]; GfxGouraudVertex *verticesA; int (*trianglesA)[3]; - int nComps, nVerticesA, nTrianglesA, vertSize, triSize; + int nCompsA, nVerticesA, nTrianglesA, vertSize, triSize; Guint x, y, flag; Guint c[gfxColorMaxComps]; GfxShadingBitBuf *bitBuf; @@ -2531,7 +2614,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, obj2.free(); cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); } - nComps = i; + nCompsA = i; } else { error(errSyntaxError, -1, "Missing or invalid Decode array in shading dictionary"); @@ -2585,12 +2668,12 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, !bitBuf->getBits(coordBits, &y)) { break; } - for (i = 0; i < nComps; ++i) { + for (i = 0; i < nCompsA; ++i) { if (!bitBuf->getBits(compBits, &c[i])) { break; } } - if (i < nComps) { + if (i < nCompsA) { break; } if (nVerticesA == vertSize) { @@ -2600,9 +2683,8 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, } verticesA[nVerticesA].x = xMin + xMul * (double)x; verticesA[nVerticesA].y = yMin + yMul * (double)y; - for (i = 0; i < nComps; ++i) { - verticesA[nVerticesA].color.c[i] = - dblToCol(cMin[i] + cMul[i] * (double)c[i]); + for (i = 0; i < nCompsA; ++i) { + verticesA[nVerticesA].color[i] = cMin[i] + cMul[i] * (double)c[i]; } ++nVerticesA; bitBuf->flushBits(); @@ -2657,8 +2739,9 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA, trianglesA, nTrianglesA, - funcsA, nFuncsA); - if (!shading->init(dict)) { + nCompsA, funcsA, nFuncsA); + if (!shading->init(dict + )) { delete shading; return NULL; } @@ -2676,54 +2759,46 @@ GfxShading *GfxGouraudTriangleShading::copy() { void GfxGouraudTriangleShading::getTriangle( int i, - double *x0, double *y0, GfxColor *color0, - double *x1, double *y1, GfxColor *color1, - double *x2, double *y2, GfxColor *color2) { - double in; - double out[gfxColorMaxComps]; + double *x0, double *y0, double *color0, + double *x1, double *y1, double *color1, + double *x2, double *y2, double *color2) { int v, j; v = triangles[i][0]; *x0 = vertices[v].x; *y0 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color0->c[j] = dblToCol(out[j]); - } - } else { - *color0 = vertices[v].color; + for (j = 0; j < nComps; ++j) { + color0[j] = vertices[v].color[j]; } v = triangles[i][1]; *x1 = vertices[v].x; *y1 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color1->c[j] = dblToCol(out[j]); - } - } else { - *color1 = vertices[v].color; + for (j = 0; j < nComps; ++j) { + color1[j] = vertices[v].color[j]; } v = triangles[i][2]; *x2 = vertices[v].x; *y2 = vertices[v].y; + for (j = 0; j < nComps; ++j) { + color2[j] = vertices[v].color[j]; + } +} + +void GfxGouraudTriangleShading::getColor(double *in, GfxColor *out) { + double c[gfxColorMaxComps]; + int i; + if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(in, &c[i]); } - for (j = 0; j < gfxColorMaxComps; ++j) { - color2->c[j] = dblToCol(out[j]); + for (i = 0; i < colorSpace->getNComps(); ++i) { + out->c[i] = dblToCol(c[i]); } } else { - *color2 = vertices[v].color; + for (i = 0; i < nComps; ++i) { + out->c[i] = dblToCol(in[i]); + } } } @@ -2733,6 +2808,7 @@ void GfxGouraudTriangleShading::getTriangle( GfxPatchMeshShading::GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, + int nCompsA, Function **funcsA, int nFuncsA): GfxShading(typeA) { @@ -2740,6 +2816,7 @@ GfxPatchMeshShading::GfxPatchMeshShading(int typeA, patches = patchesA; nPatches = nPatchesA; + nComps = nCompsA; nFuncs = nFuncsA; for (i = 0; i < nFuncs; ++i) { funcs[i] = funcsA[i]; @@ -2754,6 +2831,7 @@ GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading): nPatches = shading->nPatches; patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch)); memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch)); + nComps = shading->nComps; nFuncs = shading->nFuncs; for (i = 0; i < nFuncs; ++i) { funcs[i] = shading->funcs[i]->copy(); @@ -2770,7 +2848,8 @@ GfxPatchMeshShading::~GfxPatchMeshShading() { } GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, - Stream *str) { + Stream *str + ) { GfxPatchMeshShading *shading; Function *funcsA[gfxColorMaxComps]; int nFuncsA; @@ -2780,11 +2859,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, double xMul, yMul; double cMul[gfxColorMaxComps]; GfxPatch *patchesA, *p; - int nComps, nPatchesA, patchesSize, nPts, nColors; + int nCompsA, nPatchesA, patchesSize, nPts, nColors; Guint flag; double x[16], y[16]; Guint xi, yi; - GfxColorComp c[4][gfxColorMaxComps]; + double c[4][gfxColorMaxComps]; Guint ci; GfxShadingBitBuf *bitBuf; Object obj1, obj2; @@ -2833,7 +2912,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, obj2.free(); cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); } - nComps = i; + nCompsA = i; } else { error(errSyntaxError, -1, "Missing or invalid Decode array in shading dictionary"); @@ -2907,13 +2986,13 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, break; } for (i = 0; i < nColors; ++i) { - for (j = 0; j < nComps; ++j) { + for (j = 0; j < nCompsA; ++j) { if (!bitBuf->getBits(compBits, &ci)) { break; } - c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci); + c[i][j] = cMin[j] + cMul[j] * (double)ci; } - if (j < nComps) { + if (j < nCompsA) { break; } } @@ -2953,11 +3032,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][0] = y[10]; p->x[1][0] = x[11]; p->y[1][0] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = c[0][j]; - p->color[0][1].c[j] = c[1][j]; - p->color[1][1].c[j] = c[2][j]; - p->color[1][0].c[j] = c[3][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = c[0][j]; + p->color[0][1][j] = c[1][j]; + p->color[1][1][j] = c[2][j]; + p->color[1][0][j] = c[3][j]; } break; case 1: @@ -2985,11 +3064,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][0] = y[6]; p->x[1][0] = x[7]; p->y[1][0] = y[7]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[0][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; } break; case 2: @@ -3017,11 +3096,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][0] = y[6]; p->x[1][0] = x[7]; p->y[1][0] = y[7]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; } break; case 3: @@ -3049,11 +3128,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][0] = y[6]; p->x[1][0] = x[7]; p->y[1][0] = y[7]; - for (j = 0; j < nComps; ++j) { - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[0][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; } break; } @@ -3092,11 +3171,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][2] = y[14]; p->x[2][1] = x[15]; p->y[2][1] = y[15]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = c[0][j]; - p->color[0][1].c[j] = c[1][j]; - p->color[1][1].c[j] = c[2][j]; - p->color[1][0].c[j] = c[3][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = c[0][j]; + p->color[0][1][j] = c[1][j]; + p->color[1][1][j] = c[2][j]; + p->color[1][0][j] = c[3][j]; } break; case 1: @@ -3132,11 +3211,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][2] = y[10]; p->x[2][1] = x[11]; p->y[2][1] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[0][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; } break; case 2: @@ -3172,11 +3251,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][2] = y[10]; p->x[2][1] = x[11]; p->y[2][1] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][1][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; } break; case 3: @@ -3212,11 +3291,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, p->y[2][2] = y[10]; p->x[2][1] = x[11]; p->y[2][1] = y[11]; - for (j = 0; j < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; + for (j = 0; j < nCompsA; ++j) { + p->color[0][0][j] = patchesA[nPatchesA-1].color[1][0][j]; + p->color[0][1][j] = patchesA[nPatchesA-1].color[0][0][j]; + p->color[1][1][j] = c[0][j]; + p->color[1][0][j] = c[1][j]; } break; } @@ -3273,8 +3352,9 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, } shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA, - funcsA, nFuncsA); - if (!shading->init(dict)) { + nCompsA, funcsA, nFuncsA); + if (!shading->init(dict + )) { delete shading; return NULL; } @@ -3290,6 +3370,24 @@ GfxShading *GfxPatchMeshShading::copy() { return new GfxPatchMeshShading(this); } +void GfxPatchMeshShading::getColor(double *in, GfxColor *out) { + double c[gfxColorMaxComps]; + int i; + + if (nFuncs > 0) { + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(in, &c[i]); + } + for (i = 0; i < colorSpace->getNComps(); ++i) { + out->c[i] = dblToCol(c[i]); + } + } else { + for (i = 0; i < nComps; ++i) { + out->c[i] = dblToCol(in[i]); + } + } +} + //------------------------------------------------------------------------ // GfxImageColorMap //------------------------------------------------------------------------ @@ -3310,7 +3408,11 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, // bits per component and color space bits = bitsA; - maxPixel = (1 << bits) - 1; + if (bits <= 8) { + maxPixel = (1 << bits) - 1; + } else { + maxPixel = 0xff; + } colorSpace = colorSpaceA; // initialize @@ -3431,7 +3533,11 @@ GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) { lookup[k] = NULL; lookup2[k] = NULL; } - n = 1 << bits; + if (bits <= 8) { + n = 1 << bits; + } else { + n = 256; + } for (k = 0; k < nComps; ++k) { lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); @@ -3521,7 +3627,11 @@ void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) { void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) { int maxPixel, i; - maxPixel = (1 << bits) - 1; + if (bits <= 8) { + maxPixel = (1 << bits) - 1; + } else { + maxPixel = 0xff; + } for (i = 0; i < nComps; ++i) { color->c[i] = dblToCol(decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel); } @@ -3811,7 +3921,8 @@ void GfxPath::offset(double dx, double dy) { //------------------------------------------------------------------------ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, - int rotateA, GBool upsideDown) { + int rotateA, GBool upsideDown + ) { double kx, ky; hDPI = hDPIA; @@ -3861,8 +3972,8 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, pageHeight = ky * (py2 - py1); } - fillColorSpace = new GfxDeviceGrayColorSpace(); - strokeColorSpace = new GfxDeviceGrayColorSpace(); + fillColorSpace = GfxColorSpace::create(csDeviceGray); + strokeColorSpace = GfxColorSpace::create(csDeviceGray); fillColor.c[0] = 0; strokeColor.c[0] = 0; fillPattern = NULL; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxState.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxState.h index 5d57de9f959..74ab5eb1c51 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GfxState.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GfxState.h @@ -140,7 +140,13 @@ public: virtual GfxColorSpaceMode getMode() = 0; // Construct a color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Object *csObj, int recursion = 0); + static GfxColorSpace *parse(Object *csObj, + int recursion = 0); + + // Construct a simple color space. The <mode> argument can be + // csDeviceGray, csDeviceRGB, or csDeviceCMYK. + static GfxColorSpace *create(GfxColorSpaceMode mode); + // Convert to gray, RGB, or CMYK. virtual void getGray(GfxColor *color, GfxGray *gray) = 0; @@ -381,7 +387,8 @@ public: virtual GfxColorSpaceMode getMode() { return csICCBased; } // Construct an ICCBased color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, int recursion); + static GfxColorSpace *parse(Array *arr, + int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -418,7 +425,8 @@ public: virtual GfxColorSpaceMode getMode() { return csIndexed; } // Construct an Indexed color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, int recursion); + static GfxColorSpace *parse(Array *arr, + int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -457,7 +465,8 @@ public: virtual GfxColorSpaceMode getMode() { return csSeparation; } // Construct a Separation color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, int recursion); + static GfxColorSpace *parse(Array *arr, + int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -499,7 +508,8 @@ public: virtual GfxColorSpaceMode getMode() { return csDeviceN; } // Construct a DeviceN color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, int recursion); + static GfxColorSpace *parse(Array *arr, + int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -542,7 +552,8 @@ public: virtual GfxColorSpaceMode getMode() { return csPattern; } // Construct a Pattern color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, int recursion); + static GfxColorSpace *parse(Array *arr, + int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -570,7 +581,8 @@ public: GfxPattern(int typeA); virtual ~GfxPattern(); - static GfxPattern *parse(Object *obj); + static GfxPattern *parse(Object *objRef, Object *obj + ); virtual GfxPattern *copy() = 0; @@ -588,7 +600,7 @@ private: class GfxTilingPattern: public GfxPattern { public: - static GfxTilingPattern *parse(Object *patObj); + static GfxTilingPattern *parse(Object *patObjRef, Object *patObj); virtual ~GfxTilingPattern(); virtual GfxPattern *copy(); @@ -601,7 +613,7 @@ public: Dict *getResDict() { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; } double *getMatrix() { return matrix; } - Object *getContentStream() { return &contentStream; } + Object *getContentStreamRef() { return &contentStreamRef; } private: @@ -616,7 +628,7 @@ private: double xStep, yStep; Object resDict; double matrix[6]; - Object contentStream; + Object contentStreamRef; }; //------------------------------------------------------------------------ @@ -626,7 +638,8 @@ private: class GfxShadingPattern: public GfxPattern { public: - static GfxShadingPattern *parse(Object *patObj); + static GfxShadingPattern *parse(Object *patObj + ); virtual ~GfxShadingPattern(); virtual GfxPattern *copy(); @@ -653,7 +666,8 @@ public: GfxShading(GfxShading *shading); virtual ~GfxShading(); - static GfxShading *parse(Object *obj); + static GfxShading *parse(Object *obj + ); virtual GfxShading *copy() = 0; @@ -667,7 +681,8 @@ public: protected: - GBool init(Dict *dict); + GBool init(Dict *dict + ); int type; GfxColorSpace *colorSpace; @@ -691,7 +706,8 @@ public: GfxFunctionShading(GfxFunctionShading *shading); virtual ~GfxFunctionShading(); - static GfxFunctionShading *parse(Dict *dict); + static GfxFunctionShading *parse(Dict *dict + ); virtual GfxShading *copy(); @@ -725,7 +741,8 @@ public: GfxAxialShading(GfxAxialShading *shading); virtual ~GfxAxialShading(); - static GfxAxialShading *parse(Dict *dict); + static GfxAxialShading *parse(Dict *dict + ); virtual GfxShading *copy(); @@ -763,7 +780,8 @@ public: GfxRadialShading(GfxRadialShading *shading); virtual ~GfxRadialShading(); - static GfxRadialShading *parse(Dict *dict); + static GfxRadialShading *parse(Dict *dict + ); virtual GfxShading *copy(); @@ -793,7 +811,7 @@ private: struct GfxGouraudVertex { double x, y; - GfxColor color; + double color[gfxColorMaxComps]; }; class GfxGouraudTriangleShading: public GfxShading { @@ -802,18 +820,21 @@ public: GfxGouraudTriangleShading(int typeA, GfxGouraudVertex *verticesA, int nVerticesA, int (*trianglesA)[3], int nTrianglesA, - Function **funcsA, int nFuncsA); + int nCompsA, Function **funcsA, int nFuncsA); GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading); virtual ~GfxGouraudTriangleShading(); - static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str); + static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str + ); virtual GfxShading *copy(); + int getNComps() { return nComps; } int getNTriangles() { return nTriangles; } - void getTriangle(int i, double *x0, double *y0, GfxColor *color0, - double *x1, double *y1, GfxColor *color1, - double *x2, double *y2, GfxColor *color2); + void getTriangle(int i, double *x0, double *y0, double *color0, + double *x1, double *y1, double *color1, + double *x2, double *y2, double *color2); + void getColor(double *in, GfxColor *out); private: @@ -822,6 +843,7 @@ private: int (*triangles)[3]; int nTriangles; Function *funcs[gfxColorMaxComps]; + int nComps; // number of color components (1 if nFuncs > 0) int nFuncs; }; @@ -832,29 +854,33 @@ private: struct GfxPatch { double x[4][4]; double y[4][4]; - GfxColor color[2][2]; + double color[2][2][gfxColorMaxComps]; }; class GfxPatchMeshShading: public GfxShading { public: GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, - Function **funcsA, int nFuncsA); + int nCompsA, Function **funcsA, int nFuncsA); GfxPatchMeshShading(GfxPatchMeshShading *shading); virtual ~GfxPatchMeshShading(); - static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str); + static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str + ); virtual GfxShading *copy(); + int getNComps() { return nComps; } int getNPatches() { return nPatches; } GfxPatch *getPatch(int i) { return &patches[i]; } + void getColor(double *in, GfxColor *out); private: GfxPatch *patches; int nPatches; Function *funcs[gfxColorMaxComps]; + int nComps; // number of color components (1 if nFuncs > 0) int nFuncs; }; @@ -1040,7 +1066,8 @@ public: // x <vDPI>, page box <pageBox>, page rotation <rotateA>, and // coordinate system specified by <upsideDown>. GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, - int rotateA, GBool upsideDown); + int rotateA, GBool upsideDown + ); // Destructor. ~GfxState(); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GlobalParams.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GlobalParams.cc index aa3b2337931..57caf162d47 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GlobalParams.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GlobalParams.cc @@ -15,15 +15,19 @@ #pragma implementation #endif +#ifdef _WIN32 +# define _WIN32_WINNT 0x0500 // for GetSystemWindowsDirectory +# include <windows.h> +#endif #include <string.h> #include <stdio.h> #include <ctype.h> #ifdef ENABLE_PLUGINS -# ifndef WIN32 +# ifndef _WIN32 # include <dlfcn.h> # endif #endif -#ifdef WIN32 +#ifdef _WIN32 # include <shlobj.h> #endif #if HAVE_PAPER_H @@ -34,6 +38,7 @@ #include "GList.h" #include "GHash.h" #include "gfile.h" +#include "FoFiIdentifier.h" #include "Error.h" #include "NameToCharCode.h" #include "CharCodeToUnicode.h" @@ -46,9 +51,11 @@ #endif #include "GlobalParams.h" -#ifdef WIN32 +#ifdef _WIN32 # undef strcasecmp +# undef strncasecmp # define strcasecmp stricmp +# define strncasecmp strnicmp #else # include <strings.h> #endif @@ -74,7 +81,7 @@ #include "UTF8.h" #ifdef ENABLE_PLUGINS -# ifdef WIN32 +# ifdef _WIN32 extern XpdfPluginVecTable xpdfPluginVecTable; # endif #endif @@ -90,25 +97,29 @@ static struct { const char *name; const char *t1FileName; const char *ttFileName; + const char *macFileName; // may be .dfont, .ttf, or .ttc + const char *macFontName; // font name inside .dfont or .ttc + const char *obliqueFont; // name of font to oblique + double obliqueFactor; // oblique sheer factor } displayFontTab[] = { - {"Courier", "n022003l.pfb", "cour.ttf"}, - {"Courier-Bold", "n022004l.pfb", "courbd.ttf"}, - {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"}, - {"Courier-Oblique", "n022023l.pfb", "couri.ttf"}, - {"Helvetica", "n019003l.pfb", "arial.ttf"}, - {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"}, - {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"}, - {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"}, - {"Symbol", "s050000l.pfb", NULL}, - {"Times-Bold", "n021004l.pfb", "timesbd.ttf"}, - {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"}, - {"Times-Italic", "n021023l.pfb", "timesi.ttf"}, - {"Times-Roman", "n021003l.pfb", "times.ttf"}, - {"ZapfDingbats", "d050000l.pfb", NULL}, + {"Courier", "n022003l.pfb", "cour.ttf", "Courier", "Courier", NULL, 0}, + {"Courier-Bold", "n022004l.pfb", "courbd.ttf", "Courier", "Courier Bold", NULL, 0}, + {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf", "Courier", "Courier Bold Oblique", "Courier-Bold", 0.212557}, + {"Courier-Oblique", "n022023l.pfb", "couri.ttf", "Courier", "Courier Oblique", "Courier", 0.212557}, + {"Helvetica", "n019003l.pfb", "arial.ttf", "Helvetica", "Helvetica", NULL, 0}, + {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf", "Helvetica", "Helvetica-Bold", NULL, 0}, + {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf", "Helvetica", "Helvetica Bold Oblique", "Helvetica-Bold", 0.212557}, + {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf", "Helvetica", "Helvetica Oblique", "Helvetica", 0.212557}, + {"Symbol", "s050000l.pfb", NULL, "Symbol", "Symbol", NULL, 0}, + {"Times-Bold", "n021004l.pfb", "timesbd.ttf", "Times", "Times-Bold", NULL, 0}, + {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf", "Times", "Times-BoldItalic", NULL, 0}, + {"Times-Italic", "n021023l.pfb", "timesi.ttf", "Times", "Times-Italic", NULL, 0}, + {"Times-Roman", "n021003l.pfb", "times.ttf", "Times", "Times-Roman", NULL, 0}, + {"ZapfDingbats", "d050000l.pfb", NULL, "ZapfDingbats", "Zapf Dingbats", NULL, 0}, {NULL} }; -#ifdef WIN32 +#ifdef _WIN32 static const char *displayFontDirs[] = { "c:/windows/fonts", "c:/winnt/fonts", @@ -121,10 +132,31 @@ static const char *displayFontDirs[] = { "/usr/share/fonts/default/Type1", "/usr/share/fonts/default/ghostscript", "/usr/share/fonts/type1/gsfonts", +#if defined(__sun) && defined(__SVR4) + "/usr/sfw/share/ghostscript/fonts", +#endif NULL }; #endif +#ifdef __APPLE__ +static const char *macSystemFontPath = "/System/Library/Fonts"; +#endif + +struct Base14FontInfo { + Base14FontInfo(GString *fileNameA, int fontNumA, double obliqueA) { + fileName = fileNameA; + fontNum = fontNumA; + oblique = obliqueA; + } + ~Base14FontInfo() { + delete fileName; + } + GString *fileName; + int fontNum; + double oblique; +}; + //------------------------------------------------------------------------ GlobalParams *globalParams = NULL; @@ -204,13 +236,13 @@ public: ~SysFontList(); SysFontInfo *find(GString *name); -#ifdef WIN32 +#ifdef _WIN32 void scanWindowsFonts(char *winFontDir); #endif private: -#ifdef WIN32 +#ifdef _WIN32 SysFontInfo *makeWindowsFont(char *name, int fontNum, char *path); #endif @@ -247,40 +279,36 @@ SysFontInfo *SysFontList::find(GString *name) { } n = name2->getLength(); - // remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.) - if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) { - name2->del(n - 2, 2); - n -= 2; - } + // font names like "Arial-BoldMT,Bold" are occasionally used, + // so run this loop twice + bold = italic = gFalse; + for (i = 0; i < 2; ++i) { - // look for "Regular" - if (n > 7 && !strcmp(name2->getCString() + n - 7, "Regular")) { - name2->del(n - 7, 7); - n -= 7; - } + // remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.) + if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) { + name2->del(n - 2, 2); + n -= 2; + } - // look for "Italic" - if (n > 6 && !strcmp(name2->getCString() + n - 6, "Italic")) { - name2->del(n - 6, 6); - italic = gTrue; - n -= 6; - } else { - italic = gFalse; - } + // look for "Regular" + if (n > 7 && !strcmp(name2->getCString() + n - 7, "Regular")) { + name2->del(n - 7, 7); + n -= 7; + } - // look for "Bold" - if (n > 4 && !strcmp(name2->getCString() + n - 4, "Bold")) { - name2->del(n - 4, 4); - bold = gTrue; - n -= 4; - } else { - bold = gFalse; - } + // look for "Italic" + if (n > 6 && !strcmp(name2->getCString() + n - 6, "Italic")) { + name2->del(n - 6, 6); + italic = gTrue; + n -= 6; + } - // remove trailing "MT" (FooMT-Bold, etc.) - if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) { - name2->del(n - 2, 2); - n -= 2; + // look for "Bold" + if (n > 4 && !strcmp(name2->getCString() + n - 4, "Bold")) { + name2->del(n - 4, 4); + bold = gTrue; + n -= 4; + } } // remove trailing "PS" @@ -329,7 +357,7 @@ SysFontInfo *SysFontList::find(GString *name) { return fi; } -#ifdef WIN32 +#ifdef _WIN32 void SysFontList::scanWindowsFonts(char *winFontDir) { OSVERSIONINFO version; char *path; @@ -347,15 +375,15 @@ void SysFontList::scanWindowsFonts(char *winFontDir) { } else { path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\"; } - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, - ®Key) == ERROR_SUCCESS) { + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, + ®Key) == ERROR_SUCCESS) { idx = 0; while (1) { valNameLen = sizeof(valName) - 1; dataLen = sizeof(data) - 1; - if (RegEnumValue(regKey, idx, valName, &valNameLen, NULL, - &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) { + if (RegEnumValueA(regKey, idx, valName, &valNameLen, NULL, + &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) { break; } if (type == REG_SZ && @@ -363,7 +391,7 @@ void SysFontList::scanWindowsFonts(char *winFontDir) { dataLen > 0 && dataLen < sizeof(data)) { valName[valNameLen] = '\0'; data[dataLen] = '\0'; - n = strlen(data); + n = (int)strlen(data); if (!strcasecmp(data + n - 4, ".ttf") || !strcasecmp(data + n - 4, ".ttc")) { fontPath = new GString(data); @@ -404,7 +432,7 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum, int i; SysFontType type; - n = strlen(name); + n = (int)strlen(name); bold = italic = gFalse; // remove trailing ' (TrueType)' @@ -425,7 +453,7 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum, } // remove trailing ' Regular' - if (n > 5 && !strncmp(name + n - 8, " Regular", 8)) { + if (n > 8 && !strncmp(name + n - 8, " Regular", 8)) { n -= 8; } @@ -496,7 +524,7 @@ public: private: -#ifdef WIN32 +#ifdef _WIN32 Plugin(HMODULE libA); HMODULE lib; #else @@ -510,7 +538,7 @@ Plugin *Plugin::load(char *type, char *name) { Plugin *plugin; XpdfPluginVecTable *vt; XpdfBool (*xpdfInitPlugin)(void); -#ifdef WIN32 +#ifdef _WIN32 HMODULE libA; #else void *dlA; @@ -521,9 +549,9 @@ Plugin *Plugin::load(char *type, char *name) { appendToPath(path, type); appendToPath(path, name); -#ifdef WIN32 +#ifdef _WIN32 path->append(".dll"); - if (!(libA = LoadLibrary(path->getCString()))) { + if (!(libA = LoadLibraryA(path->getCString()))) { error(errIO, -1, "Failed to load plugin '{0:t}'", path); goto err1; } @@ -554,7 +582,7 @@ Plugin *Plugin::load(char *type, char *name) { } memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable)); -#ifdef WIN32 +#ifdef _WIN32 if (!(xpdfInitPlugin = (XpdfBool (*)(void)) GetProcAddress(libA, "xpdfInitPlugin"))) { error(errIO, -1, "Failed to find xpdfInitPlugin in plugin '{0:t}'", @@ -574,7 +602,7 @@ Plugin *Plugin::load(char *type, char *name) { goto err2; } -#ifdef WIN32 +#ifdef _WIN32 plugin = new Plugin(libA); #else plugin = new Plugin(dlA); @@ -584,7 +612,7 @@ Plugin *Plugin::load(char *type, char *name) { return plugin; err2: -#ifdef WIN32 +#ifdef _WIN32 FreeLibrary(libA); #else dlclose(dlA); @@ -594,7 +622,7 @@ Plugin *Plugin::load(char *type, char *name) { return NULL; } -#ifdef WIN32 +#ifdef _WIN32 Plugin::Plugin(HMODULE libA) { lib = libA; } @@ -607,7 +635,7 @@ Plugin::Plugin(void *dlA) { Plugin::~Plugin() { void (*xpdfFreePlugin)(void); -#ifdef WIN32 +#ifdef _WIN32 if ((xpdfFreePlugin = (void (*)(void)) GetProcAddress(lib, "xpdfFreePlugin"))) { (*xpdfFreePlugin)(); @@ -627,7 +655,7 @@ Plugin::~Plugin() { // parsing //------------------------------------------------------------------------ -GlobalParams::GlobalParams(char *cfgFileName) { +GlobalParams::GlobalParams(const char *cfgFileName) { UnicodeMap *map; GString *fileName; FILE *f; @@ -650,7 +678,7 @@ GlobalParams::GlobalParams(char *cfgFileName) { } } -#ifdef WIN32 +#ifdef _WIN32 // baseDir will be set by a call to setBaseDir baseDir = new GString(); #else @@ -666,6 +694,7 @@ GlobalParams::GlobalParams(char *cfgFileName) { fontFiles = new GHash(gTrue); fontDirs = new GList(); ccFontFiles = new GHash(gTrue); + base14SysFonts = new GHash(gTrue); sysFonts = new SysFontList(); #if HAVE_PAPER_H char *paperName; @@ -689,6 +718,7 @@ GlobalParams::GlobalParams(char *cfgFileName) { psImageableURX = psPaperWidth; psImageableURY = psPaperHeight; psCrop = gTrue; + psUseCropBoxAsPage = gFalse; psExpandSmaller = gFalse; psShrinkLarger = gTrue; psCenter = gTrue; @@ -706,12 +736,15 @@ GlobalParams::GlobalParams(char *cfgFileName) { psPreload = gFalse; psOPI = gFalse; psASCIIHex = gFalse; + psLZW = gTrue; psUncompressPreloadedImages = gFalse; + psMinLineWidth = 0; psRasterResolution = 300; psRasterMono = gFalse; + psRasterSliceSize = 20000000; psAlwaysRasterize = gFalse; textEncoding = new GString("Latin1"); -#if defined(WIN32) +#if defined(_WIN32) textEOL = eolDOS; #elif defined(MACOS) textEOL = eolMac; @@ -719,10 +752,9 @@ GlobalParams::GlobalParams(char *cfgFileName) { textEOL = eolUnix; #endif textPageBreaks = gTrue; - textKeepTinyChars = gFalse; + textKeepTinyChars = gTrue; initialZoom = new GString("125"); continuousView = gFalse; - enableT1lib = gTrue; enableFreeType = gTrue; disableFreeTypeHinting = gFalse; antialias = gTrue; @@ -743,6 +775,8 @@ GlobalParams::GlobalParams(char *cfgFileName) { movieCommand = NULL; mapNumericCharNames = gTrue; mapUnknownCharNames = gFalse; + mapExtTrueTypeFontsViaUnicode = gTrue; + enableXFA = gTrue; createDefaultKeyBindings(); printCommands = gFalse; errQuiet = gFalse; @@ -798,9 +832,9 @@ GlobalParams::GlobalParams(char *cfgFileName) { } } if (!f) { -#ifdef WIN32 +#ifdef _WIN32 char buf[512]; - i = GetModuleFileName(NULL, buf, sizeof(buf)); + i = GetModuleFileNameA(NULL, buf, sizeof(buf)); if (i <= 0 || i >= sizeof(buf)) { // error or path too long for buffer - just use the current dir buf[0] = '\0'; @@ -936,7 +970,7 @@ void GlobalParams::createDefaultKeyBindings() { keyBindings->append(new KeyBinding('l', xpdfKeyModCtrl, xpdfKeyContextAny, "redraw")); keyBindings->append(new KeyBinding('w', xpdfKeyModCtrl, - xpdfKeyContextAny, "closeWindow")); + xpdfKeyContextAny, "closeWindowOrQuit")); keyBindings->append(new KeyBinding('?', xpdfKeyModNone, xpdfKeyContextAny, "about")); keyBindings->append(new KeyBinding('q', xpdfKeyModNone, @@ -1025,6 +1059,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parsePSImageableArea(tokens, fileName, line); } else if (!cmd->cmp("psCrop")) { parseYesNo("psCrop", &psCrop, tokens, fileName, line); + } else if (!cmd->cmp("psUseCropBoxAsPage")) { + parseYesNo("psUseCropBoxAsPage", &psUseCropBoxAsPage, + tokens, fileName, line); } else if (!cmd->cmp("psExpandSmaller")) { parseYesNo("psExpandSmaller", &psExpandSmaller, tokens, fileName, line); @@ -1062,14 +1099,22 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parseYesNo("psOPI", &psOPI, tokens, fileName, line); } else if (!cmd->cmp("psASCIIHex")) { parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line); + } else if (!cmd->cmp("psLZW")) { + parseYesNo("psLZW", &psLZW, tokens, fileName, line); } else if (!cmd->cmp("psUncompressPreloadedImages")) { parseYesNo("psUncompressPreloadedImages", &psUncompressPreloadedImages, tokens, fileName, line); + } else if (!cmd->cmp("psMinLineWidth")) { + parseFloat("psMinLineWidth", &psMinLineWidth, + tokens, fileName, line); } else if (!cmd->cmp("psRasterResolution")) { parseFloat("psRasterResolution", &psRasterResolution, tokens, fileName, line); } else if (!cmd->cmp("psRasterMono")) { parseYesNo("psRasterMono", &psRasterMono, tokens, fileName, line); + } else if (!cmd->cmp("psRasterSliceSize")) { + parseInteger("psRasterSliceSize", &psRasterSliceSize, + tokens, fileName, line); } else if (!cmd->cmp("psAlwaysRasterize")) { parseYesNo("psAlwaysRasterize", &psAlwaysRasterize, tokens, fileName, line); @@ -1087,8 +1132,6 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parseInitialZoom(tokens, fileName, line); } else if (!cmd->cmp("continuousView")) { parseYesNo("continuousView", &continuousView, tokens, fileName, line); - } else if (!cmd->cmp("enableT1lib")) { - parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line); } else if (!cmd->cmp("enableFreeType")) { parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line); } else if (!cmd->cmp("disableFreeTypeHinting")) { @@ -1141,6 +1184,12 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("mapUnknownCharNames")) { parseYesNo("mapUnknownCharNames", &mapUnknownCharNames, tokens, fileName, line); + } else if (!cmd->cmp("mapExtTrueTypeFontsViaUnicode")) { + parseYesNo("mapExtTrueTypeFontsViaUnicode", + &mapExtTrueTypeFontsViaUnicode, + tokens, fileName, line); + } else if (!cmd->cmp("enableXFA")) { + parseYesNo("enableXFA", &enableXFA, tokens, fileName, line); } else if (!cmd->cmp("bind")) { parseBind(tokens, fileName, line); } else if (!cmd->cmp("unbind")) { @@ -1156,6 +1205,8 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { !cmd->cmp("displayNamedCIDFontX") || !cmd->cmp("displayCIDFontX")) { error(errConfig, -1, "Xpdf no longer supports X fonts"); + } else if (!cmd->cmp("enableT1lib")) { + error(errConfig, -1, "Xpdf no longer uses t1lib"); } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) { error(errConfig, -1, "The t1libControl and freetypeControl options have been replaced by the enableT1lib, enableFreeType, and antialias options"); @@ -1528,6 +1579,7 @@ void GlobalParams::parseScreenType(GList *tokens, GString *fileName, } } + void GlobalParams::parseBind(GList *tokens, GString *fileName, int line) { KeyBinding *binding; GList *cmds; @@ -1844,6 +1896,7 @@ GlobalParams::~GlobalParams() { deleteGHash(fontFiles, GString); deleteGList(fontDirs, GString); deleteGHash(ccFontFiles, GString); + deleteGHash(base14SysFonts, Base14FontInfo); delete sysFonts; if (psFile) { delete psFile; @@ -1894,35 +1947,77 @@ void GlobalParams::setBaseDir(char *dir) { baseDir = new GString(dir); } -void GlobalParams::setupBaseFonts(char *dir) { - GString *fontName; - GString *fileName; -#ifdef WIN32 +#ifdef _WIN32 +static void getWinFontDir(char *winFontDir) { HMODULE shell32Lib; BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner, - LPTSTR lpszPath, + LPSTR lpszPath, int nFolder, BOOL fCreate); - char winFontDir[MAX_PATH]; -#endif - FILE *f; - int i, j; + char *p; + int i; -#ifdef WIN32 // SHGetSpecialFolderPath isn't available in older versions of // shell32.dll (Win95 and WinNT4), so do a dynamic load winFontDir[0] = '\0'; - if ((shell32Lib = LoadLibrary("shell32.dll"))) { + if ((shell32Lib = LoadLibraryA("shell32.dll"))) { if ((SHGetSpecialFolderPathFunc = - (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath, + (BOOL (__stdcall *)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate)) GetProcAddress(shell32Lib, "SHGetSpecialFolderPathA"))) { if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir, CSIDL_FONTS, FALSE)) { winFontDir[0] = '\0'; } + // kludge: Terminal Server changes CSIDL_FONTS to something like + // "C:\Users\whatever\Windows\Fonts", which doesn't actually + // contain any fonts -- kill that, so we hit the fallback code + // below. + for (p = winFontDir; *p; ++p) { + if (!strncasecmp(p, "\\Users\\", 7)) { + winFontDir[0] = '\0'; + break; + } + } + } + } + // if something went wrong, or we're on a Terminal Server, try using + // %SYSTEMROOT%\Fonts + if (!winFontDir[0]) { + GetSystemWindowsDirectoryA(winFontDir, MAX_PATH - 6); + winFontDir[MAX_PATH - 7] = '\0'; + i = (int)strlen(winFontDir); + if (winFontDir[i-1] != '\\') { + winFontDir[i++] = '\\'; } + strcpy(winFontDir + i, "Fonts"); } +} +#endif + +void GlobalParams::setupBaseFonts(char *dir) { + GString *fontName; + GString *fileName; + int fontNum; + const char *s; + Base14FontInfo *base14; +#ifdef _WIN32 + char winFontDir[MAX_PATH]; +#endif +#ifdef __APPLE__ + static const char *macFontExts[3] = { "dfont", "ttc", "ttf" }; + GList *dfontFontNames; + GBool found; + int k; +#endif + FILE *f; + int i, j; + +#ifdef _WIN32 + getWinFontDir(winFontDir); +#endif +#ifdef __APPLE__ + dfontFontNames = NULL; #endif for (i = 0; displayFontTab[i].name; ++i) { if (fontFiles->lookup(displayFontTab[i].name)) { @@ -1930,6 +2025,7 @@ void GlobalParams::setupBaseFonts(char *dir) { } fontName = new GString(displayFontTab[i].name); fileName = NULL; + fontNum = 0; if (dir) { fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName); if ((f = fopen(fileName->getCString(), "rb"))) { @@ -1939,7 +2035,7 @@ void GlobalParams::setupBaseFonts(char *dir) { fileName = NULL; } } -#ifdef WIN32 +#ifdef _WIN32 if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) { fileName = appendToPath(new GString(winFontDir), displayFontTab[i].ttFileName); @@ -1950,13 +2046,67 @@ void GlobalParams::setupBaseFonts(char *dir) { fileName = NULL; } } - // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server - // or Win2003 Server, or with older versions of shell32.dll, so check - // the "standard" directories - if (displayFontTab[i].ttFileName) { +#endif +#ifdef __APPLE__ + // Check for Mac OS X system fonts. + s = displayFontTab[i].macFileName; + if (dfontFontNames && i > 0 && + (!s || strcmp(s, displayFontTab[i-1].macFileName))) { + deleteGList(dfontFontNames, GString); + dfontFontNames = NULL; + } + if (!fileName && s) { + for (j = 0; j < 3; ++j) { + fileName = GString::format("{0:s}/{1:s}.{2:s}", + macSystemFontPath, s, macFontExts[j]); + if (!(f = fopen(fileName->getCString(), "rb"))) { + delete fileName; + fileName = NULL; + } else { + fclose(f); + found = gFalse; + // for .dfont or .ttc, we need to scan the font list + if (j < 2) { + if (!dfontFontNames) { + dfontFontNames = + FoFiIdentifier::getFontList(fileName->getCString()); + } + if (dfontFontNames) { + for (k = 0; k < dfontFontNames->getLength(); ++k) { + if (!((GString *)dfontFontNames->get(k)) + ->cmp(displayFontTab[i].macFontName)) { + fontNum = k; + found = gTrue; + break; + } + } + } + // for .ttf, we just use the font + } else { + found = gTrue; + } + if (!found) { + delete fileName; + fileName = NULL; + } + break; + } + } + } +#endif // __APPLE__ + // On Linux, this checks the "standard" ghostscript font + // directories. On Windows, it checks the "standard" system font + // directories (because SHGetSpecialFolderPath(CSIDL_FONTS) + // doesn't work on Win 2k Server or Win2003 Server, or with older + // versions of shell32.dll). +#ifdef _WIN32 + s = displayFontTab[i].ttFileName; +#else + s = displayFontTab[i].t1FileName; +#endif + if (!fileName && s) { for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].ttFileName); + fileName = appendToPath(new GString(displayFontDirs[j]), s); if ((f = fopen(fileName->getCString(), "rb"))) { fclose(f); } else { @@ -1965,28 +2115,35 @@ void GlobalParams::setupBaseFonts(char *dir) { } } } -#else // WIN32 - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].t1FileName); - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } -#endif // WIN32 if (!fileName) { - error(errConfig, -1, "No display font for '{0:s}'", - displayFontTab[i].name); delete fontName; continue; } - addFontFile(fontName, fileName); + base14SysFonts->add(fontName, new Base14FontInfo(fileName, fontNum, 0)); } - -#ifdef WIN32 +#ifdef __APPLE__ + if (dfontFontNames) { + deleteGList(dfontFontNames, GString); + } +#endif + for (i = 0; displayFontTab[i].name; ++i) { + if (!base14SysFonts->lookup(displayFontTab[i].name) && + !fontFiles->lookup(displayFontTab[i].name)) { + if (displayFontTab[i].obliqueFont && + ((base14 = (Base14FontInfo *)base14SysFonts + ->lookup(displayFontTab[i].obliqueFont)))) { + base14SysFonts->add( + new GString(displayFontTab[i].name), + new Base14FontInfo(base14->fileName->copy(), + base14->fontNum, + displayFontTab[i].obliqueFactor)); + } else { + error(errConfig, -1, "No display font for '{0:s}'", + displayFontTab[i].name); + } + } + } +#ifdef _WIN32 if (winFontDir[0]) { sysFonts->scanWindowsFonts(winFontDir); } @@ -2091,7 +2248,7 @@ FILE *GlobalParams::findToUnicodeFile(GString *name) { GString *GlobalParams::findFontFile(GString *fontName) { static const char *exts[] = { ".pfa", ".pfb", ".ttf", ".ttc" }; GString *path, *dir; -#ifdef WIN32 +#ifdef _WIN32 GString *fontNameU; #endif const char *ext; @@ -2108,7 +2265,7 @@ GString *GlobalParams::findFontFile(GString *fontName) { dir = (GString *)fontDirs->get(i); for (j = 0; j < (int)(sizeof(exts) / sizeof(exts[0])); ++j) { ext = exts[j]; -#ifdef WIN32 +#ifdef _WIN32 fontNameU = fileNameToUTF8(fontName->getCString()); path = appendToPath(dir->copy(), fontNameU->getCString()); delete fontNameU; @@ -2128,6 +2285,25 @@ GString *GlobalParams::findFontFile(GString *fontName) { return NULL; } +GString *GlobalParams::findBase14FontFile(GString *fontName, int *fontNum, + double *oblique) { + Base14FontInfo *fi; + GString *path; + + lockGlobalParams; + if ((fi = (Base14FontInfo *)base14SysFonts->lookup(fontName))) { + path = fi->fileName->copy(); + *fontNum = fi->fontNum; + *oblique = fi->oblique; + unlockGlobalParams; + return path; + } + unlockGlobalParams; + *fontNum = 0; + *oblique = 0; + return findFontFile(fontName); +} + GString *GlobalParams::findSystemFontFile(GString *fontName, SysFontType *type, int *fontNum) { @@ -2201,6 +2377,15 @@ GBool GlobalParams::getPSCrop() { return f; } +GBool GlobalParams::getPSUseCropBoxAsPage() { + GBool f; + + lockGlobalParams; + f = psUseCropBoxAsPage; + unlockGlobalParams; + return f; +} + GBool GlobalParams::getPSExpandSmaller() { GBool f; @@ -2250,7 +2435,9 @@ GString *GlobalParams::getPSResidentFont(GString *fontName) { GString *psName; lockGlobalParams; - psName = (GString *)psResidentFonts->lookup(fontName); + if ((psName = (GString *)psResidentFonts->lookup(fontName))) { + psName = psName->copy(); + } unlockGlobalParams; return psName; } @@ -2379,6 +2566,15 @@ GBool GlobalParams::getPSASCIIHex() { return ah; } +GBool GlobalParams::getPSLZW() { + GBool ah; + + lockGlobalParams; + ah = psLZW; + unlockGlobalParams; + return ah; +} + GBool GlobalParams::getPSUncompressPreloadedImages() { GBool ah; @@ -2388,6 +2584,15 @@ GBool GlobalParams::getPSUncompressPreloadedImages() { return ah; } +double GlobalParams::getPSMinLineWidth() { + double w; + + lockGlobalParams; + w = psMinLineWidth; + unlockGlobalParams; + return w; +} + double GlobalParams::getPSRasterResolution() { double res; @@ -2406,6 +2611,15 @@ GBool GlobalParams::getPSRasterMono() { return mono; } +int GlobalParams::getPSRasterSliceSize() { + int slice; + + lockGlobalParams; + slice = psRasterSliceSize; + unlockGlobalParams; + return slice; +} + GBool GlobalParams::getPSAlwaysRasterize() { GBool rast; @@ -2469,15 +2683,6 @@ GBool GlobalParams::getContinuousView() { return f; } -GBool GlobalParams::getEnableT1lib() { - GBool f; - - lockGlobalParams; - f = enableT1lib; - unlockGlobalParams; - return f; -} - GBool GlobalParams::getEnableFreeType() { GBool f; @@ -2605,6 +2810,7 @@ GBool GlobalParams::getDrawAnnotations() { return draw; } + GBool GlobalParams::getMapNumericCharNames() { GBool map; @@ -2623,6 +2829,24 @@ GBool GlobalParams::getMapUnknownCharNames() { return map; } +GBool GlobalParams::getMapExtTrueTypeFontsViaUnicode() { + GBool map; + + lockGlobalParams; + map = mapExtTrueTypeFontsViaUnicode; + unlockGlobalParams; + return map; +} + +GBool GlobalParams::getEnableXFA() { + GBool enable; + + lockGlobalParams; + enable = enableXFA; + unlockGlobalParams; + return enable; +} + GList *GlobalParams::getKeyBinding(int code, int mods, int context) { KeyBinding *binding; GList *cmds; @@ -2812,6 +3036,12 @@ void GlobalParams::setPSCrop(GBool crop) { unlockGlobalParams; } +void GlobalParams::setPSUseCropBoxAsPage(GBool crop) { + lockGlobalParams; + psUseCropBoxAsPage = crop; + unlockGlobalParams; +} + void GlobalParams::setPSExpandSmaller(GBool expand) { lockGlobalParams; psExpandSmaller = expand; @@ -2890,7 +3120,7 @@ void GlobalParams::setPSASCIIHex(GBool hex) { unlockGlobalParams; } -void GlobalParams::setTextEncoding(char *encodingName) { +void GlobalParams::setTextEncoding(const char *encodingName) { lockGlobalParams; delete textEncoding; textEncoding = new GString(encodingName); @@ -2938,15 +3168,6 @@ void GlobalParams::setContinuousView(GBool cont) { unlockGlobalParams; } -GBool GlobalParams::setEnableT1lib(char *s) { - GBool ok; - - lockGlobalParams; - ok = parseYesNo2(s, &enableT1lib); - unlockGlobalParams; - return ok; -} - GBool GlobalParams::setEnableFreeType(char *s) { GBool ok; @@ -3023,6 +3244,18 @@ void GlobalParams::setMapUnknownCharNames(GBool map) { unlockGlobalParams; } +void GlobalParams::setMapExtTrueTypeFontsViaUnicode(GBool map) { + lockGlobalParams; + mapExtTrueTypeFontsViaUnicode = map; + unlockGlobalParams; +} + +void GlobalParams::setEnableXFA(GBool enable) { + lockGlobalParams; + enableXFA = enable; + unlockGlobalParams; +} + void GlobalParams::setPrintCommands(GBool printCommandsA) { lockGlobalParams; printCommands = printCommandsA; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GlobalParams.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GlobalParams.h index 068e6459a52..6764d8431bf 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/GlobalParams.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/GlobalParams.h @@ -176,7 +176,7 @@ public: // Initialize the global parameters by attempting to read a config // file. - GlobalParams(char *cfgFileName = NULL); + GlobalParams(const char *cfgFileName = NULL); ~GlobalParams(); @@ -196,6 +196,8 @@ public: FILE *findCMapFile(GString *collection, GString *cMapName); FILE *findToUnicodeFile(GString *name); GString *findFontFile(GString *fontName); + GString *findBase14FontFile(GString *fontName, int *fontNum, + double *oblique); GString *findSystemFontFile(GString *fontName, SysFontType *type, int *fontNum); GString *findCCFontFile(GString *collection); @@ -205,6 +207,7 @@ public: void getPSImageableArea(int *llx, int *lly, int *urx, int *ury); GBool getPSDuplex(); GBool getPSCrop(); + GBool getPSUseCropBoxAsPage(); GBool getPSExpandSmaller(); GBool getPSShrinkLarger(); GBool getPSCenter(); @@ -221,9 +224,12 @@ public: GBool getPSPreload(); GBool getPSOPI(); GBool getPSASCIIHex(); + GBool getPSLZW(); GBool getPSUncompressPreloadedImages(); + double getPSMinLineWidth(); double getPSRasterResolution(); GBool getPSRasterMono(); + int getPSRasterSliceSize(); GBool getPSAlwaysRasterize(); GString *getTextEncodingName(); EndOfLineKind getTextEOL(); @@ -231,7 +237,6 @@ public: GBool getTextKeepTinyChars(); GString *getInitialZoom(); GBool getContinuousView(); - GBool getEnableT1lib(); GBool getEnableFreeType(); GBool getDisableFreeTypeHinting(); GBool getAntialias(); @@ -252,6 +257,8 @@ public: GString *getMovieCommand() { return movieCommand; } GBool getMapNumericCharNames(); GBool getMapUnknownCharNames(); + GBool getMapExtTrueTypeFontsViaUnicode(); + GBool getEnableXFA(); GList *getKeyBinding(int code, int mods, int context); GBool getPrintCommands(); GBool getErrQuiet(); @@ -272,6 +279,7 @@ public: void setPSImageableArea(int llx, int lly, int urx, int ury); void setPSDuplex(GBool duplex); void setPSCrop(GBool crop); + void setPSUseCropBoxAsPage(GBool crop); void setPSExpandSmaller(GBool expand); void setPSShrinkLarger(GBool shrink); void setPSCenter(GBool center); @@ -284,13 +292,12 @@ public: void setPSPreload(GBool preload); void setPSOPI(GBool opi); void setPSASCIIHex(GBool hex); - void setTextEncoding(char *encodingName); + void setTextEncoding(const char *encodingName); GBool setTextEOL(char *s); void setTextPageBreaks(GBool pageBreaks); void setTextKeepTinyChars(GBool keep); void setInitialZoom(char *s); void setContinuousView(GBool cont); - GBool setEnableT1lib(char *s); GBool setEnableFreeType(char *s); GBool setAntialias(char *s); GBool setVectorAntialias(char *s); @@ -302,6 +309,8 @@ public: void setScreenWhiteThreshold(double thresh); void setMapNumericCharNames(GBool map); void setMapUnknownCharNames(GBool map); + void setMapExtTrueTypeFontsViaUnicode(GBool map); + void setEnableXFA(GBool enable); void setPrintCommands(GBool printCommandsA); void setErrQuiet(GBool errQuietA); @@ -382,6 +391,8 @@ private: GList *fontDirs; // list of font dirs [GString] GHash *ccFontFiles; // character collection font files: // collection name mapped to path [GString] + GHash *base14SysFonts; // Base-14 system font files: font name + // mapped to path [Base14FontInfo] SysFontList *sysFonts; // system fonts GString *psFile; // PostScript file or command (for xpdf) int psPaperWidth; // paper size, in PostScript points, for @@ -391,6 +402,7 @@ private: psImageableURX, psImageableURY; GBool psCrop; // crop PS output to CropBox + GBool psUseCropBoxAsPage; // use CropBox as page size GBool psExpandSmaller; // expand smaller pages to fill paper GBool psShrinkLarger; // shrink larger pages to fit paper GBool psCenter; // center pages on the paper @@ -414,11 +426,15 @@ private: // memory GBool psOPI; // generate PostScript OPI comments? GBool psASCIIHex; // use ASCIIHex instead of ASCII85? + GBool psLZW; // false to use RLE instead of LZW GBool psUncompressPreloadedImages; // uncompress all preloaded images + double psMinLineWidth; // minimum line width for PostScript output double psRasterResolution; // PostScript rasterization resolution (dpi) GBool psRasterMono; // true to do PostScript rasterization // in monochrome (gray); false to do it // in color (RGB/CMYK) + int psRasterSliceSize; // maximum size (pixels) of PostScript + // rasterization slice GBool psAlwaysRasterize; // force PostScript rasterization GString *textEncoding; // encoding (unicodeMap) to use for text // output @@ -428,7 +444,6 @@ private: GBool textKeepTinyChars; // keep all characters in text output GString *initialZoom; // initial zoom level GBool continuousView; // continuous view mode - GBool enableT1lib; // t1lib enable flag GBool enableFreeType; // FreeType enable flag GBool disableFreeTypeHinting; // FreeType hinting disable flag GBool antialias; // font anti-aliasing enable flag @@ -449,6 +464,9 @@ private: GString *movieCommand; // command executed for movie annotations GBool mapNumericCharNames; // map numeric char names (from font subsets)? GBool mapUnknownCharNames; // map unknown char names? + GBool mapExtTrueTypeFontsViaUnicode; // map char codes to GID via Unicode + // for external TrueType fonts? + GBool enableXFA; // enable XFA form rendering GList *keyBindings; // key & mouse button bindings [KeyBinding] GBool printCommands; // print the drawing commands GBool errQuiet; // suppress error messages? diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.cc new file mode 100644 index 00000000000..6372e131e54 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.cc @@ -0,0 +1,583 @@ +//======================================================================== +// +// HTMLGen.cc +// +// Copyright 2010 Glyph & Cog, LLC +// +//======================================================================== + +//~ to do: +//~ - fonts +//~ - underlined? (underlines are present in the background image) +//~ - include the original font name in the CSS entry (before the +//~ 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 +//~ - rotated text should go in the background image +//~ - metadata +//~ - PDF outline + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <png.h> +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "SplashBitmap.h" +#include "PDFDoc.h" +#include "TextOutputDev.h" +#include "SplashOutputDev.h" +#include "ErrorCodes.h" +#if EVAL_MODE +# include "SplashMath.h" +# include "Splash.h" +# include "BuiltinFontTables.h" +# include "FontEncodingTables.h" +#endif +#include "HTMLGen.h" + +#ifdef _WIN32 +# define strcasecmp stricmp +# define strncasecmp strnicmp +#endif + +//------------------------------------------------------------------------ + +struct FontStyleTagInfo { + const char *tag; + int tagLen; + GBool bold; + GBool italic; +}; + +// NB: these are compared, in order, against the tail of the font +// name, so "BoldItalic" must come before "Italic", etc. +static FontStyleTagInfo fontStyleTags[] = { + {"Roman", 5, gFalse, gFalse}, + {"Regular", 7, gFalse, gFalse}, + {"Condensed", 9, gFalse, gFalse}, + {"CondensedBold", 13, gTrue, gFalse}, + {"CondensedLight", 14, gFalse, gFalse}, + {"SemiBold", 8, gTrue, gFalse}, + {"BoldItalic", 10, gTrue, gTrue}, + {"Bold_Italic", 11, gTrue, gTrue}, + {"BoldOblique", 11, gTrue, gTrue}, + {"Bold_Oblique", 12, gTrue, gTrue}, + {"Bold", 4, gTrue, gFalse}, + {"Italic", 6, gFalse, gTrue}, + {"Oblique", 7, gFalse, gTrue}, + {NULL, 0, gFalse, gFalse} +}; + +struct StandardFontInfo { + const char *name; + GBool fixedWidth; + GBool serif; +}; + +static StandardFontInfo standardFonts[] = { + {"Arial", gFalse, gFalse}, + {"Courier", gTrue, gFalse}, + {"Futura", gFalse, gFalse}, + {"Helvetica", gFalse, gFalse}, + {"Minion", gFalse, gTrue}, + {"NewCenturySchlbk", gFalse, gTrue}, + {"Times", gFalse, gTrue}, + {"TimesNew", gFalse, gTrue}, + {"Times_New", gFalse, gTrue}, + {"Verdana", gFalse, gFalse}, + {"LucidaSans", gFalse, gFalse}, + {NULL, gFalse, gFalse} +}; + +struct SubstFontInfo { + double mWidth; +}; + +// index: {fixed:8, serif:4, sans-serif:0} + bold*2 + italic +static SubstFontInfo substFonts[16] = { + {0.833}, + {0.833}, + {0.889}, + {0.889}, + {0.788}, + {0.722}, + {0.833}, + {0.778}, + {0.600}, + {0.600}, + {0.600}, + {0.600} +}; + +// Map Unicode indexes from the private use area, following the Adobe +// Glyph list. +#define privateUnicodeMapStart 0xf6f9 +#define privateUnicodeMapEnd 0xf7ff +static int +privateUnicodeMap[privateUnicodeMapEnd - privateUnicodeMapStart + 1] = { + 0x0141, 0x0152, 0, 0, 0x0160, 0, 0x017d, // f6f9 + 0, 0, 0, 0, 0, 0, 0, 0, // f700 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f710 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x0021, 0, 0, 0x0024, 0, 0x0026, 0, // f720 + 0, 0, 0, 0, 0, 0, 0, 0, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // f730 + 0x0038, 0x0039, 0, 0, 0, 0, 0, 0x003f, + 0, 0, 0, 0, 0, 0, 0, 0, // f740 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f750 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // f760 + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // f770 + 0x0058, 0x0059, 0x005a, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f780 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f790 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x00a1, 0x00a2, 0, 0, 0, 0, 0, // f7a0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f7b0 + 0, 0, 0, 0, 0, 0, 0, 0x00bf, + 0, 0, 0, 0, 0, 0, 0, 0, // f7c0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // f7d0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // f7e0 + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0, // f7f0 + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178 +}; + +//------------------------------------------------------------------------ + +#if EVAL_MODE + +#define EVAL_MODE_MSG "XpdfHTML evaluation - www.glyphandcog.com" + +static void drawEvalModeMsg(SplashOutputDev *out) { + BuiltinFont *bf; + SplashFont *font; + GString *fontName; + char *msg; + SplashCoord mat[4], ident[6]; + SplashCoord diag, size, textW, x, y; + Gushort cw; + int w, h, n, i; + + // get the Helvetica font info + bf = builtinFontSubst[4]; + + msg = EVAL_MODE_MSG; + n = strlen(msg); + + w = out->getBitmap()->getWidth(); + h = out->getBitmap()->getHeight(); + + ident[0] = 1; ident[1] = 0; + ident[2] = 0; ident[3] = -1; + ident[4] = 0; ident[5] = h; + out->getSplash()->setMatrix(ident); + + diag = splashSqrt((SplashCoord)(w*w + h*h)); + size = diag / (0.67 * n); + if (size < 8) { + size = 8; + } + mat[0] = size * (SplashCoord)w / diag; + mat[3] = mat[0]; + mat[1] = size * (SplashCoord)h / diag; + mat[2] = -mat[1]; + fontName = new GString(bf->name); + font = out->getFont(fontName, mat); + delete fontName; + if (!font) { + return; + } + + textW = 0; + for (i = 0; i < n; ++i) { + bf->widths->getWidth(winAnsiEncoding[msg[i] & 0xff], &cw); + textW += size * cw * 0.001; + } + + out->setFillColor(255, 0, 0); + x = 0.5 * (diag - textW) * (SplashCoord)w / diag; + y = 0.5 * (diag - textW) * (SplashCoord)h / diag; + for (i = 0; i < n; ++i) { + out->getSplash()->fillChar(x, y, msg[i], font); + bf->widths->getWidth(winAnsiEncoding[msg[i] & 0xff], &cw); + x += mat[0] * cw * 0.001; + y += mat[1] * cw * 0.001; + } +} +#endif + +//------------------------------------------------------------------------ + +HTMLGen::HTMLGen(double backgroundResolutionA) { + TextOutputControl textOutControl; + SplashColor paperColor; + + ok = gTrue; + + backgroundResolution = backgroundResolutionA; + drawInvisibleText = gTrue; + + // set up the TextOutputDev + textOutControl.mode = textOutReadingOrder; + textOutControl.html = gTrue; + textOut = new TextOutputDev(NULL, &textOutControl, gFalse); + if (!textOut->isOk()) { + ok = gFalse; + } + + // set up the SplashOutputDev + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + splashOut->setSkipText(gTrue, gFalse); +} + +HTMLGen::~HTMLGen() { + delete textOut; + delete splashOut; +} + +void HTMLGen::startDoc(PDFDoc *docA) { + doc = docA; + splashOut->startDoc(doc->getXRef()); +} + +static inline int pr(int (*writeFunc)(void *stream, const char *data, int size), + void *stream, const char *data) { + return writeFunc(stream, data, (int)strlen(data)); +} + +static int pf(int (*writeFunc)(void *stream, const char *data, int size), + void *stream, const char *fmt, ...) { + va_list args; + GString *s; + int ret; + + va_start(args, fmt); + s = GString::formatv(fmt, args); + va_end(args); + ret = writeFunc(stream, s->getCString(), s->getLength()); + delete s; + return ret; +} + +struct PNGWriteInfo { + 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); +} + +int HTMLGen::convertPage( + int pg, const char *pngURL, + int (*writeHTML)(void *stream, const char *data, int size), + void *htmlStream, + int (*writePNG)(void *stream, const char *data, int size), + void *pngStream) { + png_structp png; + png_infop pngInfo; + PNGWriteInfo writeInfo; + SplashBitmap *bitmap; + Guchar *p; + double pageW, pageH; + TextPage *text; + GList *fonts, *cols, *pars, *lines, *words; + double *fontScales; + TextFontInfo *font; + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word0, *word1; + GString *s; + double base, base1; + int subSuper0, subSuper1; + double r0, g0, b0, r1, g1, b1; + int colIdx, parIdx, lineIdx, wordIdx; + int y, i, u; + + // generate the background bitmap + doc->displayPage(splashOut, pg, backgroundResolution, backgroundResolution, + 0, gFalse, gTrue, gFalse); +#if EVAL_MODE + drawEvalModeMsg(splashOut); +#endif + 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 + pageW = doc->getPageCropWidth(pg); + pageH = doc->getPageCropHeight(pg); + + // get the PDF text + doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + doc->processLinks(textOut, pg); + text = textOut->takeText(); + + // HTML header + pr(writeHTML, htmlStream, "<html>\n"); + pr(writeHTML, htmlStream, "<head>\n"); + pr(writeHTML, htmlStream, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); + pr(writeHTML, htmlStream, "<style type=\"text/css\">\n"); + pr(writeHTML, htmlStream, ".txt { white-space:nowrap; }\n"); + fonts = text->getFonts(); + fontScales = (double *)gmallocn(fonts->getLength(), sizeof(double)); + for (i = 0; i < fonts->getLength(); ++i) { + font = (TextFontInfo *)fonts->get(i); + s = getFontDefn(font, &fontScales[i]); + pf(writeHTML, htmlStream, "#f{0:d} {{ {1:t} }}\n", i, s); + delete s; + } + pr(writeHTML, htmlStream, "</style>\n"); + pr(writeHTML, htmlStream, "</head>\n"); + pr(writeHTML, htmlStream, "<body onload=\"start()\">\n"); + 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, (int)pageH, pngURL); + + // generate the HTML text + cols = text->makeColumns(); + for (colIdx = 0; colIdx < cols->getLength(); ++colIdx) { + col = (TextColumn *)cols->get(colIdx); + pars = col->getParagraphs(); + for (parIdx = 0; parIdx < pars->getLength(); ++parIdx) { + par = (TextParagraph *)pars->get(parIdx); + lines = par->getLines(); + for (lineIdx = 0; lineIdx < lines->getLength(); ++lineIdx) { + line = (TextLine *)lines->get(lineIdx); + if (line->getRotation() != 0) { + continue; + } + words = line->getWords(); + base = line->getBaseline(); + s = new GString(); + word0 = NULL; + subSuper0 = 0; // make gcc happy + r0 = g0 = b0 = 0; // make gcc happy + for (wordIdx = 0; wordIdx < words->getLength(); ++wordIdx) { + word1 = (TextWord *)words->get(wordIdx); + if (!drawInvisibleText && word1->isInvisible()) { + continue; + } + word1->getColor(&r1, &g1, &b1); + base1 = word1->getBaseline(); + if (base1 - base < -1) { + subSuper1 = -1; // superscript + } else if (base1 - base > 1) { + subSuper1 = 1; // subscript + } else { + subSuper1 = 0; + } + if (!word0 || + word1->getFontInfo() != word0->getFontInfo() || + word1->getFontSize() != word0->getFontSize() || + subSuper1 != subSuper0 || + 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; + } + } + s->appendf("<span id=\"f{0:d}\" style=\"font-size:{1:d}px;vertical-align:{2:s};color:#{3:02x}{4:02x}{5:02x};\">", + i, (int)(fontScales[i] * word1->getFontSize()), + subSuper1 < 0 ? "super" + : subSuper1 > 0 ? "sub" + : "baseline", + (int)(r1 * 255), (int)(g1 * 255), (int)(b1 * 255)); + } + for (i = 0; i < word1->getLength(); ++i) { + u = word1->getChar(i); + if (u >= privateUnicodeMapStart && + u <= privateUnicodeMapEnd && + privateUnicodeMap[u - privateUnicodeMapStart]) { + u = privateUnicodeMap[u - privateUnicodeMapStart]; + } + if (u <= 0x7f) { + if (u == '&') { + s->append("&"); + } else if (u == '<') { + s->append("<"); + } else if (u == '>') { + s->append(">"); + } else { + s->append((char)u); + } + } else if (u <= 0x7ff) { + s->append((char)(0xc0 + (u >> 6))); + s->append((char)(0x80 + (u & 0x3f))); + } else if (u <= 0xffff) { + s->append((char)0xe0 + (u >> 12)); + s->append((char)0x80 + ((u >> 6) & 0x3f)); + s->append((char)0x80 + (u & 0x3f)); + } else if (u <= 0x1fffff) { + s->append((char)0xf0 + (u >> 18)); + s->append((char)0x80 + ((u >> 12) & 0x3f)); + s->append((char)0x80 + ((u >> 6) & 0x3f)); + s->append((char)0x80 + (u & 0x3f)); + } else if (u <= 0x3ffffff) { + s->append((char)0xf8 + (u >> 24)); + s->append((char)0x80 + ((u >> 18) & 0x3f)); + s->append((char)0x80 + ((u >> 12) & 0x3f)); + s->append((char)0x80 + ((u >> 6) & 0x3f)); + s->append((char)0x80 + (u & 0x3f)); + } else if (u <= 0x7fffffff) { + s->append((char)0xfc + (u >> 30)); + s->append((char)0x80 + ((u >> 24) & 0x3f)); + s->append((char)0x80 + ((u >> 18) & 0x3f)); + s->append((char)0x80 + ((u >> 12) & 0x3f)); + s->append((char)0x80 + ((u >> 6) & 0x3f)); + s->append((char)0x80 + (u & 0x3f)); + } + } + if (word1->getSpaceAfter()) { + s->append(' '); + } + word0 = word1; + subSuper0 = subSuper1; + r0 = r1; + g0 = g1; + b0 = b1; + } + s->append("</span>"); + pf(writeHTML, htmlStream, "<div class=\"txt\" style=\"position:absolute; left:{0:d}px; top:{1:d}px;\">{2:t}</div>\n", + (int)line->getXMin(), (int)line->getYMin(), s); + delete s; + } + } + } + gfree(fontScales); + delete text; + deleteGList(cols, TextColumn); + + // HTML trailer + pr(writeHTML, htmlStream, "</body>\n"); + pr(writeHTML, htmlStream, "</html>\n"); + + return errNone; +} + +GString *HTMLGen::getFontDefn(TextFontInfo *font, double *scale) { + GString *fontName; + char *fontName2; + FontStyleTagInfo *fst; + StandardFontInfo *sf; + GBool fixedWidth, serif, bold, italic; + double s; + int n, i; + + // get the font name, remove any subset tag + fontName = font->getFontName(); + if (fontName) { + fontName2 = fontName->getCString(); + n = fontName->getLength(); + for (i = 0; i < n && i < 7; ++i) { + if (fontName2[i] < 'A' || fontName2[i] > 'Z') { + break; + } + } + if (i == 6 && n > 7 && fontName2[6] == '+') { + fontName2 += 7; + n -= 7; + } + } else { + fontName2 = NULL; + n = 0; + } + + // get the style info from the font descriptor flags + fixedWidth = font->isFixedWidth(); + serif = font->isSerif(); + bold = font->isBold(); + italic = font->isItalic(); + + if (fontName2) { + + // look for a style tag at the end of the font name -- this + // overrides the font descriptor bold/italic flags + for (fst = fontStyleTags; fst->tag; ++fst) { + if (n > fst->tagLen && + !strcasecmp(fontName2 + n - fst->tagLen, fst->tag)) { + bold = fst->bold; + italic = fst->italic; + n -= fst->tagLen; + if (n > 1 && (fontName2[n-1] == '-' || + fontName2[n-1] == ',' || + fontName2[n-1] == '.' || + fontName2[n-1] == '_')) { + --n; + } + break; + } + } + + // look for a known font name -- this overrides the font descriptor + // fixedWidth/serif flags + for (sf = standardFonts; sf->name; ++sf) { + if (!strncasecmp(fontName2, sf->name, n)) { + fixedWidth = sf->fixedWidth; + serif = sf->serif; + break; + } + } + } + + // compute the scaling factor + *scale = 1; + if ((s = font->getMWidth())) { + i = (fixedWidth ? 8 : serif ? 4 : 0) + (bold ? 2 : 0) + (italic ? 1 : 0); + if (s < substFonts[i].mWidth) { + *scale = s / substFonts[i].mWidth; + } + } + + // generate the CSS markup + return GString::format("font-family:{0:s}; font-weight:{1:s}; font-style:{2:s};", + fixedWidth ? "monospace" + : serif ? "serif" + : "sans-serif", + bold ? "bold" : "normal", + italic ? "italic" : "normal"); +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.h new file mode 100644 index 00000000000..7271c67bc32 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/HTMLGen.h @@ -0,0 +1,63 @@ +//======================================================================== +// +// HTMLGen.h +// +// Copyright 2010 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef HTMLGEN_H +#define HTMLGEN_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class GString; +class PDFDoc; +class TextOutputDev; +class TextFontInfo; +class SplashOutputDev; + +//------------------------------------------------------------------------ + +class HTMLGen { +public: + + HTMLGen(double backgroundResolutionA); + ~HTMLGen(); + + GBool isOk() { return ok; } + + double getBackgroundResolution() { return backgroundResolution; } + void setBackgroundResolution(double backgroundResolutionA) + { backgroundResolution = backgroundResolutionA; } + + GBool getDrawInvisibleText() { return drawInvisibleText; } + void setDrawInvisibleText(GBool drawInvisibleTextA) + { drawInvisibleText = drawInvisibleTextA; } + + void startDoc(PDFDoc *docA); + int convertPage(int pg, const char *pngURL, + int (*writeHTML)(void *stream, const char *data, int size), + void *htmlStream, + int (*writePNG)(void *stream, const char *data, int size), + void *pngStream); + +private: + + GString *getFontDefn(TextFontInfo *font, double *scale); + + double backgroundResolution; + GBool drawInvisibleText; + + PDFDoc *doc; + TextOutputDev *textOut; + SplashOutputDev *splashOut; + + GBool ok; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/ImageOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/ImageOutputDev.cc index a5c931475f8..3f6b1a1d49f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/ImageOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/ImageOutputDev.cc @@ -37,7 +37,8 @@ ImageOutputDev::~ImageOutputDev() { gfree(fileRoot); } -void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, +void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, + Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -47,16 +48,16 @@ void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { + GBool inlineImg, GBool interpolate) { FILE *f; - int c; - int size, i; + char buf[4096]; + int size, n, i; // dump JPEG file if (dumpJPEG && str->getKind() == strDCT && !inlineImg) { // open the image file - sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum); + sprintf(fileName, "%s-%04d.jpg", fileRoot, imgNum); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(errIO, -1, "Couldn't open image file '{0:s}'", fileName); @@ -68,8 +69,9 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, str->reset(); // copy the stream - while ((c = str->getChar()) != EOF) - fputc(c, f); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } str->close(); fclose(f); @@ -78,7 +80,7 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, } else { // open the image file and write the PBM header - sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum); + sprintf(fileName, "%s-%04d.pbm", fileRoot, imgNum); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(errIO, -1, "Couldn't open image file '{0:s}'", fileName); @@ -92,8 +94,14 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, // copy the stream size = height * ((width + 7) / 8); - for (i = 0; i < size; ++i) { - fputc(str->getChar(), f); + while (size > 0) { + i = size < (int)sizeof(buf) ? size : (int)sizeof(buf); + n = str->getBlock(buf, i); + fwrite(buf, 1, n, f); + if (n < i) { + break; + } + size -= n; } str->close(); @@ -104,14 +112,15 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { + int *maskColors, GBool inlineImg, + GBool interpolate) { FILE *f; ImageStream *imgStr; Guchar *p; GfxRGB rgb; int x, y; - int c; - int size, i; + char buf[4096]; + int size, n, i; // dump JPEG file if (dumpJPEG && str->getKind() == strDCT && @@ -120,7 +129,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, !inlineImg) { // open the image file - sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum); + sprintf(fileName, "%s-%04d.jpg", fileRoot, imgNum); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(errIO, -1, "Couldn't open image file '{0:s}'", fileName); @@ -132,8 +141,9 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, str->reset(); // copy the stream - while ((c = str->getChar()) != EOF) - fputc(c, f); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); + } str->close(); fclose(f); @@ -143,7 +153,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, colorMap->getBits() == 1) { // open the image file and write the PBM header - sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum); + sprintf(fileName, "%s-%04d.pbm", fileRoot, imgNum); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(errIO, -1, "Couldn't open image file '{0:s}'", fileName); @@ -157,8 +167,14 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, // copy the stream size = height * ((width + 7) / 8); - for (i = 0; i < size; ++i) { - fputc(str->getChar() ^ 0xff, f); + while (size > 0) { + i = size < (int)sizeof(buf) ? size : (int)sizeof(buf); + n = str->getBlock(buf, i); + fwrite(buf, 1, n, f); + if (n < i) { + break; + } + size -= n; } str->close(); @@ -168,7 +184,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, } else { // open the image file and write the PPM header - sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum); + sprintf(fileName, "%s-%04d.ppm", fileRoot, imgNum); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(errIO, -1, "Couldn't open image file '{0:s}'", fileName); @@ -203,8 +219,36 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, } } } + + imgStr->close(); delete imgStr; fclose(f); } } + +void ImageOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, + NULL, gFalse, interpolate); + drawImageMask(state, ref, maskStr, maskWidth, maskHeight, maskInvert, + gFalse, interpolate); +} + +void ImageOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, + NULL, gFalse, interpolate); + drawImage(state, ref, maskStr, maskWidth, maskHeight, maskColorMap, + NULL, gFalse, interpolate); +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/ImageOutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/ImageOutputDev.h index 5496225daeb..29846865773 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/ImageOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/ImageOutputDev.h @@ -62,7 +62,7 @@ public: virtual GBool useDrawChar() { return gFalse; } //----- path painting - virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -71,10 +71,22 @@ public: //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + GBool interpolate); private: diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JArithmeticDecoder.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JArithmeticDecoder.cc index 56ddc312059..92db3265ede 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JArithmeticDecoder.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JArithmeticDecoder.cc @@ -92,10 +92,18 @@ JArithmeticDecoder::JArithmeticDecoder() { dataLen = 0; limitStream = gFalse; nBytesRead = 0; + readBuf = -1; } inline Guint JArithmeticDecoder::readByte() { + Guint x; + if (limitStream) { + if (readBuf >= 0) { + x = (Guint)readBuf; + readBuf = -1; + return x; + } --dataLen; if (dataLen < 0) { return 0xff; @@ -162,9 +170,15 @@ void JArithmeticDecoder::restart(int dataLenA) { void JArithmeticDecoder::cleanup() { if (limitStream) { + // This saves one extra byte of data from the end of packet i, to + // be used in packet i+1. It's not clear from the JPEG 2000 spec + // exactly how this should work, but this kludge does seem to fix + // decode of some problematic JPEG 2000 streams. It may actually + // be necessary to buffer an arbitrary number of bytes (not just + // one byte), but I haven't run into that case yet. while (dataLen > 0) { - buf0 = buf1; - buf1 = readByte(); + readBuf = -1; + readBuf = readByte(); } } } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JArithmeticDecoder.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JArithmeticDecoder.h index 7217984df7b..c0f773fb107 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JArithmeticDecoder.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JArithmeticDecoder.h @@ -108,6 +108,7 @@ private: Guint nBytesRead; int dataLen; GBool limitStream; + int readBuf; }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JBIG2Stream.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JBIG2Stream.cc index eb2719a1641..8588931c9fe 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JBIG2Stream.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JBIG2Stream.cc @@ -623,11 +623,11 @@ Guint JBIG2MMRDecoder::get24Bits() { } void JBIG2MMRDecoder::skipTo(Guint length) { - while (nBytesRead < length) { - str->getChar(); - ++nBytesRead; - ++byteCounter; - } + int n; + + n = str->discardChars(length - nBytesRead); + nBytesRead += n; + byteCounter += n; } //------------------------------------------------------------------------ @@ -1310,10 +1310,9 @@ void JBIG2Stream::readSegments() { } refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3; nRefSegs = refFlags & 0x1fffffff; - for (i = 0; i < (nRefSegs + 9) >> 3; ++i) { - if ((c1 = curStr->getChar()) == EOF) { - goto eofError1; - } + i = (nRefSegs + 9) >> 3; + if (curStr->discardChars(i) != i) { + goto eofError1; } } @@ -1436,10 +1435,8 @@ void JBIG2Stream::readSegments() { break; default: error(errSyntaxError, getPos(), "Unknown segment type in JBIG2 stream"); - for (i = 0; i < segLength; ++i) { - if ((c1 = curStr->getChar()) == EOF) { - goto eofError2; - } + if (curStr->discardChars(segLength) != segLength) { + goto eofError2; } break; } @@ -1460,12 +1457,7 @@ void JBIG2Stream::readSegments() { gfree(refSegs); break; } - while (byteCounter < segLength) { - if (curStr->getChar() == EOF) { - break; - } - ++byteCounter; - } + byteCounter += curStr->discardChars(segLength - byteCounter); } gfree(refSegs); @@ -1502,9 +1494,8 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, Guint symHeight, symWidth, totalWidth, x, symID; int dh, dw, refAggNum, refDX, refDY, bmSize; GBool ex; - int run, cnt, c; + int run, cnt; Guint i, j, k; - Guchar *p; symWidths = NULL; @@ -1814,14 +1805,8 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, if (bmSize == 0) { collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight); bmSize = symHeight * ((totalWidth + 7) >> 3); - p = collBitmap->getDataPtr(); - for (k = 0; k < (Guint)bmSize; ++k) { - if ((c = curStr->getChar()) == EOF) { - break; - } - *p++ = (Guchar)c; - ++byteCounter; - } + byteCounter += curStr->getBlock((char *)collBitmap->getDataPtr(), + bmSize); } else { collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight, 0, gFalse, gFalse, NULL, NULL, NULL, @@ -2781,7 +2766,6 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, Guchar mask; int x, y, x0, x1, a0i, b1i, blackPixels, pix, i; - bitmap = new JBIG2Bitmap(0, w, h); bitmap->clearToZero(); @@ -2994,7 +2978,7 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, ltpCX = 0x0e3; // 001 1100 01 1 break; case 3: - ltpCX = 0x18a; // 01100 0101 1 + ltpCX = 0x18b; // 01100 0101 1 break; } } @@ -3821,27 +3805,13 @@ void JBIG2Stream::readPageInfoSeg(Guint length) { } void JBIG2Stream::readEndOfStripeSeg(Guint length) { - Guint i; - // skip the segment - for (i = 0; i < length; ++i) { - if (curStr->getChar() == EOF) { - break; - } - ++byteCounter; - } + byteCounter += curStr->discardChars(length); } void JBIG2Stream::readProfilesSeg(Guint length) { - Guint i; - // skip the segment - for (i = 0; i < length; ++i) { - if (curStr->getChar() == EOF) { - break; - } - ++byteCounter; - } + byteCounter += curStr->discardChars(length); } void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { @@ -3909,15 +3879,8 @@ void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { } void JBIG2Stream::readExtensionSeg(Guint length) { - Guint i; - // skip the segment - for (i = 0; i < length; ++i) { - if (curStr->getChar() == EOF) { - break; - } - ++byteCounter; - } + byteCounter += curStr->discardChars(length); } JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) { diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JBIG2Stream.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JBIG2Stream.h index 660f5827f31..660f5827f31 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JBIG2Stream.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JBIG2Stream.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JPXStream.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JPXStream.cc index 98dcfefba4e..7e2bc6b4c6d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JPXStream.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JPXStream.cc @@ -42,7 +42,7 @@ #define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup #define jpxContextSign 9 // 9 - 13: sign -#define jpxContextMagRef 14 // 14 -16: magnitude refinement +#define jpxContextMagRef 14 // 14 - 16: magnitude refinement #define jpxContextRunLength 17 // cleanup: run length #define jpxContextUniform 18 // cleanup: first signif coeff @@ -152,9 +152,10 @@ static Guint signContext[5][5][2] = { #define idwtKappa 1.230174104914001 #define idwtIKappa (1.0 / idwtKappa) -// number of bits to the right of the decimal point for the fixed -// point arithmetic used in the IDWT -#define fracBits 16 +// sum of the sample size (number of bits) and the number of bits to +// the right of the decimal point for the fixed point arithmetic used +// in the IDWT +#define fracBits 24 //------------------------------------------------------------------------ @@ -233,12 +234,25 @@ JPXStream::JPXStream(Stream *strA): nComps = 0; bpc = NULL; width = height = 0; + reduction = 0; haveCS = gFalse; + + palette.bpc = NULL; + palette.c = NULL; havePalette = gFalse; + + compMap.comp = NULL; + compMap.type = NULL; + compMap.pComp = NULL; haveCompMap = gFalse; + + channelDefn.idx = NULL; + channelDefn.type = NULL; + channelDefn.assoc = NULL; haveChannelDefn = gFalse; img.tiles = NULL; + bitBuf = 0; bitBufLen = 0; bitBufSkip = gFalse; @@ -252,13 +266,13 @@ JPXStream::~JPXStream() { void JPXStream::reset() { bufStr->reset(); - if (readBoxes()) { - curY = img.yOffset; - } else { + if (readBoxes() == jpxDecodeFatalError) { // readBoxes reported an error, so we go immediately to EOF - curY = img.ySize; + curY = img.ySizeR; + } else { + curY = img.yOffsetR; } - curX = img.xOffset; + curX = img.xOffsetR; curComp = 0; readBufLen = 0; } @@ -387,23 +401,25 @@ int JPXStream::lookChar() { void JPXStream::fillReadBuf() { JPXTileComp *tileComp; Guint tileIdx, tx, ty; - int pix, pixBits; + int pix, pixBits, k; + GBool eol; do { - if (curY >= img.ySize) { + if (curY >= img.ySizeR) { return; } - tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles - + (curX - img.xTileOffset) / img.xTileSize; + tileIdx = ((curY - img.yTileOffsetR) / img.yTileSizeR) * img.nXTiles + + (curX - img.xTileOffsetR) / img.xTileSizeR; #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid tileComp = &img.tiles[tileIdx].tileComps[curComp]; #else tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp]; #endif - tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep); - ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep); - pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx]; + tx = jpxCeilDiv((curX - img.xTileOffsetR) % img.xTileSizeR, tileComp->hSep); + ty = jpxCeilDiv((curY - img.yTileOffsetR) % img.yTileSizeR, tileComp->vSep); + pix = (int)tileComp->data[ty * tileComp->w + tx]; pixBits = tileComp->prec; + eol = gFalse; #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid if (++curComp == img.nComps) { #else @@ -418,13 +434,10 @@ void JPXStream::fillReadBuf() { if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) { #endif curComp = 0; - if (++curX == img.xSize) { - curX = img.xOffset; + if (++curX == img.xSizeR) { + curX = img.xOffsetR; ++curY; - if (pixBits < 8) { - pix <<= 8 - pixBits; - pixBits = 8; - } + eol = gTrue; } } if (pixBits == 8) { @@ -433,6 +446,10 @@ void JPXStream::fillReadBuf() { readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1)); } readBufLen += pixBits; + if (eol && (k = readBufLen & 7)) { + readBuf <<= 8 - k; + readBufLen += 8 - k; + } } while (readBufLen < 8); } @@ -447,7 +464,7 @@ GBool JPXStream::isBinary(GBool last) { void JPXStream::getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode) { Guint boxType, boxLen, dataLen, csEnum; - Guint bpc1, dummy, i; + Guint bpc1, dummy; int csMeth, csPrec, csPrec1, dummy2; StreamColorSpaceMode csMode1; GBool haveBPC, haveCSMode; @@ -498,13 +515,13 @@ void JPXStream::getImageParams(int *bitsPerComponent, csPrec = csPrec1; haveCSMode = gTrue; } - for (i = 0; i < dataLen - 7; ++i) { - bufStr->getChar(); + if (dataLen > 7) { + bufStr->discardChars(dataLen - 7); } } } else { - for (i = 0; i < dataLen - 3; ++i) { - bufStr->getChar(); + if (dataLen > 3) { + bufStr->discardChars(dataLen - 3); } } } @@ -516,9 +533,7 @@ void JPXStream::getImageParams(int *bitsPerComponent, break; } else { cover(4); - for (i = 0; i < dataLen; ++i) { - bufStr->getChar(); - } + bufStr->discardChars(dataLen); } } } @@ -529,7 +544,7 @@ void JPXStream::getImageParams(int *bitsPerComponent, void JPXStream::getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode) { int segType; - Guint segLen, nComps1, bpc1, dummy, i; + Guint segLen, nComps1, bpc1, dummy; while (readMarkerHdr(&segType, &segLen)) { if (segType == 0x51) { // SIZ - image and tile size @@ -559,15 +574,14 @@ void JPXStream::getImageParams2(int *bitsPerComponent, } else { cover(6); if (segLen > 2) { - for (i = 0; i < segLen - 2; ++i) { - bufStr->getChar(); - } + bufStr->discardChars(segLen - 2); } } } } -GBool JPXStream::readBoxes() { +JPXDecodeResult JPXStream::readBoxes() { + JPXDecodeResult result; Guint boxType, boxLen, dataLen; Guint bpc1, compression, unknownColorspace, ipr; Guint i, j; @@ -581,8 +595,8 @@ GBool JPXStream::readBoxes() { cover(7); error(errSyntaxWarning, getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper"); - if (!readCodestream(0)) { - return gFalse; + if ((result = readCodestream(0)) == jpxDecodeFatalError) { + return result; } nComps = img.nComps; bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); @@ -591,7 +605,7 @@ GBool JPXStream::readBoxes() { } width = img.xSize - img.xOffset; height = img.ySize - img.yOffset; - return gTrue; + return result; } while (readBoxHdr(&boxType, &boxLen, &dataLen)) { @@ -614,12 +628,12 @@ GBool JPXStream::readBoxes() { !readUByte(&unknownColorspace) || !readUByte(&ipr)) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } if (compression != 7) { error(errSyntaxError, getPos(), "Unknown compression type in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); for (i = 0; i < nComps; ++i) { @@ -632,24 +646,24 @@ GBool JPXStream::readBoxes() { if (!haveImgHdr) { error(errSyntaxError, getPos(), "Found bits per component box before image header box in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } if (dataLen != nComps) { error(errSyntaxError, getPos(), "Invalid bits per component box in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } for (i = 0; i < nComps; ++i) { if (!readUByte(&bpc[i])) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } } break; case 0x636F6C72: // color specification cover(11); if (!readColorSpecBox(dataLen)) { - return gFalse; + return jpxDecodeFatalError; } break; case 0x70636c72: // palette @@ -657,15 +671,16 @@ GBool JPXStream::readBoxes() { if (!readUWord(&palette.nEntries) || !readUByte(&palette.nComps)) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } + havePalette = gTrue; palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint)); palette.c = (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int)); for (i = 0; i < palette.nComps; ++i) { if (!readUByte(&palette.bpc[i])) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } ++palette.bpc[i]; } @@ -675,14 +690,14 @@ GBool JPXStream::readBoxes() { (palette.bpc[j] & 0x80) ? gTrue : gFalse, &palette.c[i * palette.nComps + j])) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } } } - havePalette = gTrue; break; case 0x636d6170: // component mapping cover(13); + haveCompMap = gTrue; compMap.nChannels = dataLen / 4; compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); @@ -692,17 +707,17 @@ GBool JPXStream::readBoxes() { !readUByte(&compMap.type[i]) || !readUByte(&compMap.pComp[i])) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } } - haveCompMap = gTrue; break; case 0x63646566: // channel definition cover(14); if (!readUWord(&channelDefn.nChannels)) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } + haveChannelDefn = gTrue; channelDefn.idx = (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); channelDefn.type = @@ -714,10 +729,9 @@ GBool JPXStream::readBoxes() { !readUWord(&channelDefn.type[i]) || !readUWord(&channelDefn.assoc[i])) { error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } } - haveChannelDefn = gTrue; break; case 0x6A703263: // contiguous codestream cover(15); @@ -729,28 +743,25 @@ GBool JPXStream::readBoxes() { error(errSyntaxError, getPos(), "JPX stream has no supported color spec"); } - if (!readCodestream(dataLen)) { - return gFalse; + if ((result = readCodestream(dataLen)) != jpxDecodeOk) { + return result; } break; default: cover(16); - for (i = 0; i < dataLen; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } + if (bufStr->discardChars(dataLen) != dataLen) { + error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream"); + return jpxDecodeFatalError; } break; } } - return gTrue; + return jpxDecodeOk; } GBool JPXStream::readColorSpecBox(Guint dataLen) { JPXColorSpec newCS; Guint csApprox, csEnum; - Guint i; GBool ok; ok = gFalse; @@ -852,10 +863,9 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) { case 3: // any ICC profile (JPX) case 4: // vendor color (JPX) cover(18); - for (i = 0; i < dataLen - 3; ++i) { - if (bufStr->getChar() == EOF) { - goto err; - } + if (dataLen > 3 && + bufStr->discardChars(dataLen - 3) != dataLen - 3) { + goto err; } break; } @@ -872,11 +882,11 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) { return gFalse; } -GBool JPXStream::readCodestream(Guint len) { +JPXDecodeResult JPXStream::readCodestream(Guint len) { JPXTile *tile; JPXTileComp *tileComp; int segType; - GBool haveSIZ, haveCOD, haveQCD, haveSOT; + GBool haveSIZ, haveCOD, haveQCD, haveSOT, ok; Guint precinctSize, style; Guint segLen, capabilities, comp, i, j, r; @@ -885,7 +895,7 @@ GBool JPXStream::readCodestream(Guint len) { do { if (!readMarkerHdr(&segType, &segLen)) { error(errSyntaxError, getPos(), "Error in JPX codestream"); - return gFalse; + return jpxDecodeFatalError; } switch (segType) { case 0x4f: // SOC - start of codestream @@ -897,7 +907,7 @@ GBool JPXStream::readCodestream(Guint len) { if (haveSIZ) { error(errSyntaxError, getPos(), "Duplicate SIZ marker segment in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } if (!readUWord(&capabilities) || !readULong(&img.xSize) || @@ -910,12 +920,12 @@ GBool JPXStream::readCodestream(Guint len) { !readULong(&img.yTileOffset) || !readUWord(&img.nComps)) { error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); - return gFalse; + return jpxDecodeFatalError; } if (haveImgHdr && img.nComps != nComps) { error(errSyntaxError, getPos(), "Different number of components in JPX SIZ marker segment"); - return gFalse; + return jpxDecodeFatalError; } if (img.xSize == 0 || img.ySize == 0 || img.xOffset >= img.xSize || img.yOffset >= img.ySize || @@ -925,8 +935,16 @@ GBool JPXStream::readCodestream(Guint len) { img.xTileSize + img.xTileOffset <= img.xOffset || img.yTileSize + img.yTileOffset <= img.yOffset) { error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); - return gFalse; - } + return jpxDecodeFatalError; + } + img.xSizeR = img.xSize >> reduction; + img.ySizeR = img.ySize >> reduction; + img.xOffsetR = img.xOffset >> reduction; + img.yOffsetR = img.yOffset >> reduction; + img.xTileSizeR = img.xTileSize >> reduction; + img.yTileSizeR = img.yTileSize >> reduction; + img.xTileOffsetR = img.xTileOffset >> reduction; + img.yTileOffsetR = img.yTileOffset >> reduction; img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) / img.xTileSize; img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) @@ -936,12 +954,16 @@ GBool JPXStream::readCodestream(Guint len) { img.nXTiles >= INT_MAX / img.nYTiles) { error(errSyntaxError, getPos(), "Bad tile count in JPX SIZ marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles, sizeof(JPXTile)); for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { img.tiles[i].init = gFalse; + img.tiles[i].nextTilePart = 0; + img.tiles[i].tileComps = NULL; + } + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps, sizeof(JPXTileComp)); for (comp = 0; comp < img.nComps; ++comp) { @@ -956,12 +978,12 @@ GBool JPXStream::readCodestream(Guint len) { !readUByte(&img.tiles[0].tileComps[comp].hSep) || !readUByte(&img.tiles[0].tileComps[comp].vSep)) { error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); - return gFalse; + return jpxDecodeFatalError; } if (img.tiles[0].tileComps[comp].hSep == 0 || img.tiles[0].tileComps[comp].vSep == 0) { error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[comp].sgned = (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse; @@ -978,7 +1000,7 @@ GBool JPXStream::readCodestream(Guint len) { if (!haveSIZ) { error(errSyntaxError, getPos(), "JPX COD marker segment before SIZ segment"); - return gFalse; + return jpxDecodeFatalError; } if (!readUByte(&img.tiles[0].tileComps[0].style) || !readUByte(&img.tiles[0].progOrder) || @@ -990,14 +1012,21 @@ GBool JPXStream::readCodestream(Guint len) { !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) || !readUByte(&img.tiles[0].tileComps[0].transform)) { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); - return gFalse; + return jpxDecodeFatalError; } if (img.tiles[0].tileComps[0].nDecompLevels > 32 || img.tiles[0].tileComps[0].codeBlockW > 8 || img.tiles[0].tileComps[0].codeBlockH > 8) { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); - return gFalse; + return jpxDecodeFatalError; } +#if 1 //~ progression orders 2-4 are unimplemented + if (img.tiles[0].progOrder >= 2) { + error(errUnimplemented, -1, + "JPX progression order {0:d} is unimplemented", + img.tiles[0].progOrder); + } +#endif img.tiles[0].tileComps[0].codeBlockW += 2; img.tiles[0].tileComps[0].codeBlockH += 2; for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { @@ -1035,7 +1064,7 @@ GBool JPXStream::readCodestream(Guint len) { cover(91); if (!readUByte(&precinctSize)) { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[0].resLevels[r].precinctWidth = precinctSize & 0x0f; @@ -1065,7 +1094,7 @@ GBool JPXStream::readCodestream(Guint len) { if (!haveCOD) { error(errSyntaxError, getPos(), "JPX COC marker segment before COD segment"); - return gFalse; + return jpxDecodeFatalError; } if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || @@ -1077,13 +1106,13 @@ GBool JPXStream::readCodestream(Guint len) { !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) || !readUByte(&img.tiles[0].tileComps[comp].transform)) { error(errSyntaxError, getPos(), "Error in JPX COC marker segment"); - return gFalse; + return jpxDecodeFatalError; } if (img.tiles[0].tileComps[comp].nDecompLevels > 32 || img.tiles[0].tileComps[comp].codeBlockW > 8 || img.tiles[0].tileComps[comp].codeBlockH > 8) { error(errSyntaxError, getPos(), "Error in JPX COC marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[comp].style = (img.tiles[0].tileComps[comp].style & ~1) | (style & 1); @@ -1117,7 +1146,7 @@ GBool JPXStream::readCodestream(Guint len) { if (img.tiles[0].tileComps[comp].style & 0x01) { if (!readUByte(&precinctSize)) { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = precinctSize & 0x0f; @@ -1142,16 +1171,16 @@ GBool JPXStream::readCodestream(Guint len) { if (!haveSIZ) { error(errSyntaxError, getPos(), "JPX QCD marker segment before SIZ segment"); - return gFalse; + return jpxDecodeFatalError; } if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) { if (segLen <= 3) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[0].nQuantSteps = segLen - 3; img.tiles[0].tileComps[0].quantSteps = @@ -1161,7 +1190,7 @@ GBool JPXStream::readCodestream(Guint len) { for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } } } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) { @@ -1172,12 +1201,12 @@ GBool JPXStream::readCodestream(Guint len) { sizeof(Guint)); if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) { if (segLen < 5) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2; img.tiles[0].tileComps[0].quantSteps = @@ -1187,12 +1216,12 @@ GBool JPXStream::readCodestream(Guint len) { for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } } } else { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { for (comp = 0; comp < img.nComps; ++comp) { @@ -1219,19 +1248,19 @@ GBool JPXStream::readCodestream(Guint len) { if (!haveQCD) { error(errSyntaxError, getPos(), "JPX QCC marker segment before QCD segment"); - return gFalse; + return jpxDecodeFatalError; } if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) { error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); - return gFalse; + return jpxDecodeFatalError; } if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) { if (segLen <= (img.nComps > 256 ? 5U : 4U)) { error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[comp].nQuantSteps = segLen - (img.nComps > 256 ? 5 : 4); @@ -1242,7 +1271,7 @@ GBool JPXStream::readCodestream(Guint len) { for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) { error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); - return gFalse; + return jpxDecodeFatalError; } } } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) { @@ -1253,12 +1282,12 @@ GBool JPXStream::readCodestream(Guint len) { sizeof(Guint)); if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) { error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); - return gFalse; + return jpxDecodeFatalError; } } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) { if (segLen < (img.nComps > 256 ? 5U : 4U) + 2) { error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); - return gFalse; + return jpxDecodeFatalError; } img.tiles[0].tileComps[comp].nQuantSteps = (segLen - (img.nComps > 256 ? 5 : 4)) / 2; @@ -1269,12 +1298,12 @@ GBool JPXStream::readCodestream(Guint len) { for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) { error(errSyntaxError, getPos(), "Error in JPX QCD marker segment"); - return gFalse; + return jpxDecodeFatalError; } } } else { error(errSyntaxError, getPos(), "Error in JPX QCC marker segment"); - return gFalse; + return jpxDecodeFatalError; } for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { img.tiles[i].tileComps[comp].quantStyle = @@ -1295,11 +1324,10 @@ GBool JPXStream::readCodestream(Guint len) { cover(25); #if 1 //~ ROI is unimplemented error(errUnimplemented, -1, "got a JPX RGN segment"); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); + return jpxDecodeFatalError; } #else if ((img.nComps > 256 && !readUWord(&comp)) || @@ -1308,7 +1336,7 @@ GBool JPXStream::readCodestream(Guint len) { !readUByte(&compInfo[comp].defROI.style) || !readUByte(&compInfo[comp].defROI.shift)) { error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); - return gFalse; + return jpxDecodeFatalError; } #endif break; @@ -1316,11 +1344,10 @@ GBool JPXStream::readCodestream(Guint len) { cover(26); #if 1 //~ progression order changes are unimplemented error(errUnimplemented, -1, "got a JPX POC segment"); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); + return jpxDecodeFatalError; } #else nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); @@ -1335,7 +1362,7 @@ GBool JPXStream::readCodestream(Guint len) { !(img.nComps <= 256 && readUByte(&progs[i].endComp)) || !readUByte(&progs[i].progOrder)) { error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); - return gFalse; + return jpxDecodeFatalError; } } #endif @@ -1344,52 +1371,47 @@ GBool JPXStream::readCodestream(Guint len) { cover(27); #if 1 //~ packed packet headers are unimplemented error(errUnimplemented, -1, "Got a JPX PPM segment"); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PPM marker segment"); + return jpxDecodeFatalError; } #endif break; case 0x55: // TLM - tile-part lengths // skipped cover(28); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX TLM marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX TLM marker segment"); + return jpxDecodeFatalError; } break; case 0x57: // PLM - packet length, main header // skipped cover(29); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX PLM marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PLM marker segment"); + return jpxDecodeFatalError; } break; case 0x63: // CRG - component registration // skipped cover(30); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX CRG marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX CRG marker segment"); + return jpxDecodeFatalError; } break; case 0x64: // COM - comment // skipped cover(31); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX COM marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX COM marker segment"); + return jpxDecodeFatalError; } break; case 0x90: // SOT - start of tile @@ -1400,10 +1422,8 @@ GBool JPXStream::readCodestream(Guint len) { cover(33); error(errSyntaxError, getPos(), "Unknown marker segment {0:02x} in JPX stream", segType); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - break; - } + if (segLen > 2) { + bufStr->discardChars(segLen - 2); } break; } @@ -1412,27 +1432,30 @@ GBool JPXStream::readCodestream(Guint len) { if (!haveSIZ) { error(errSyntaxError, getPos(), "Missing SIZ marker segment in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } if (!haveCOD) { error(errSyntaxError, getPos(), "Missing COD marker segment in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } if (!haveQCD) { error(errSyntaxError, getPos(), "Missing QCD marker segment in JPX stream"); - return gFalse; + return jpxDecodeFatalError; } //----- read the tile-parts + ok = gTrue; while (1) { if (!readTilePart()) { - return gFalse; + ok = gFalse; + break; } if (!readMarkerHdr(&segType, &segLen)) { error(errSyntaxError, getPos(), "Error in JPX codestream"); - return gFalse; + ok = gFalse; + break; } if (segType != 0x90) { // SOT - start of tile break; @@ -1441,7 +1464,7 @@ GBool JPXStream::readCodestream(Guint len) { if (segType != 0xd9) { // EOC - end of codestream error(errSyntaxError, getPos(), "Missing EOC marker in JPX codestream"); - return gFalse; + ok = gFalse; } //----- finish decoding the image @@ -1449,20 +1472,20 @@ GBool JPXStream::readCodestream(Guint len) { tile = &img.tiles[i]; if (!tile->init) { error(errSyntaxError, getPos(), "Uninitialized tile in JPX codestream"); - return gFalse; + return jpxDecodeFatalError; } for (comp = 0; comp < img.nComps; ++comp) { tileComp = &tile->tileComps[comp]; inverseTransform(tileComp); } if (!inverseMultiCompAndDC(tile)) { - return gFalse; + return jpxDecodeFatalError; } } //~ can free memory below tileComps here, and also tileComp.buf - return gTrue; + return ok ? jpxDecodeOk : jpxDecodeNonFatalError; } GBool JPXStream::readTilePart() { @@ -1490,11 +1513,16 @@ GBool JPXStream::readTilePart() { return gFalse; } - if ((tilePartIdx > 0 && !img.tiles[tileIdx].init) || - tileIdx >= img.nXTiles * img.nYTiles) { - error(errSyntaxError, getPos(), "Weird tile index in JPX stream"); + // check tileIdx and tilePartIdx + // (this ignores nTileParts, because some encoders get it wrong) + if (tileIdx >= img.nXTiles * img.nYTiles || + tilePartIdx != img.tiles[tileIdx].nextTilePart || + (tilePartIdx > 0 && !img.tiles[tileIdx].init) || + (tilePartIdx == 0 && img.tiles[tileIdx].init)) { + error(errSyntaxError, getPos(), "Weird tile-part header in JPX stream"); return gFalse; } + ++img.tiles[tileIdx].nextTilePart; tilePartToEOC = tilePartLen == 0; tilePartLen -= 12; // subtract size of SOT segment @@ -1527,6 +1555,13 @@ GBool JPXStream::readTilePart() { error(errSyntaxError, getPos(), "Error in JPX COD marker segment"); return gFalse; } +#if 1 //~ progression orders 2-4 are unimplemented + if (img.tiles[tileIdx].progOrder >= 2) { + error(errUnimplemented, -1, + "JPX progression order {0:d} is unimplemented", + img.tiles[tileIdx].progOrder); + } +#endif img.tiles[tileIdx].tileComps[0].codeBlockW += 2; img.tiles[tileIdx].tileComps[0].codeBlockH += 2; for (comp = 0; comp < img.nComps; ++comp) { @@ -1760,11 +1795,10 @@ GBool JPXStream::readTilePart() { cover(38); #if 1 //~ ROI is unimplemented error(errUnimplemented, -1, "Got a JPX RGN segment"); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX RGN marker segment"); + return gFalse; } #else if ((img.nComps > 256 && !readUWord(&comp)) || @@ -1781,11 +1815,10 @@ GBool JPXStream::readTilePart() { cover(39); #if 1 //~ progression order changes are unimplemented error(errUnimplemented, -1, "Got a JPX POC segment"); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX POC marker segment"); + return gFalse; } #else nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); @@ -1809,31 +1842,28 @@ GBool JPXStream::readTilePart() { cover(40); #if 1 //~ packed packet headers are unimplemented error(errUnimplemented, -1, "Got a JPX PPT segment"); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX PPT marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PPT marker segment"); + return gFalse; } #endif case 0x58: // PLT - packet length, tile-part header // skipped cover(41); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX PLT marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX PLT marker segment"); + return gFalse; } break; case 0x64: // COM - comment // skipped cover(42); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - error(errSyntaxError, getPos(), "Error in JPX COM marker segment"); - return gFalse; - } + if (segLen > 2 && + bufStr->discardChars(segLen - 2) != segLen - 2) { + error(errSyntaxError, getPos(), "Error in JPX COM marker segment"); + return gFalse; } break; case 0x93: // SOD - start of data @@ -1845,10 +1875,8 @@ GBool JPXStream::readTilePart() { error(errSyntaxError, getPos(), "Unknown marker segment {0:02x} in JPX tile-part stream", segType); - for (i = 0; i < segLen - 2; ++i) { - if (bufStr->getChar() == EOF) { - break; - } + if (segLen > 2) { + bufStr->discardChars(segLen - 2); } break; } @@ -1886,12 +1914,13 @@ GBool JPXStream::readTilePart() { tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->vSep); tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep); tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep); - tileComp->w = tileComp->x1 - tileComp->x0; tileComp->cbW = 1 << tileComp->codeBlockW; tileComp->cbH = 1 << tileComp->codeBlockH; - tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) * - (tileComp->y1 - tileComp->y0), - sizeof(int)); + tileComp->w = (tileComp->x1 - tileComp->x0 + (1 << reduction) - 1) + >> reduction; + tileComp->h = (tileComp->y1 - tileComp->y0 + (1 << reduction) - 1) + >> reduction; + tileComp->data = (int *)gmallocn(tileComp->w * tileComp->h, sizeof(int)); if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) { n = tileComp->x1 - tileComp->x0; } else { @@ -1927,6 +1956,9 @@ GBool JPXStream::readTilePart() { } resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct)); for (pre = 0; pre < 1; ++pre) { + resLevel->precincts[pre].subbands = NULL; + } + for (pre = 0; pre < 1; ++pre) { precinct = &resLevel->precincts[pre]; precinct->x0 = resLevel->x0; precinct->y0 = resLevel->y0; @@ -1936,6 +1968,11 @@ GBool JPXStream::readTilePart() { precinct->subbands = (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband)); for (sb = 0; sb < nSBs; ++sb) { + precinct->subbands[sb].inclusion = NULL; + precinct->subbands[sb].zeroBitPlane = NULL; + precinct->subbands[sb].cbs = NULL; + } + for (sb = 0; sb < nSBs; ++sb) { subband = &precinct->subbands[sb]; subband->x0 = resLevel->bx0[sb]; subband->y0 = resLevel->by0[sb]; @@ -1973,6 +2010,12 @@ GBool JPXStream::readTilePart() { subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs * subband->nYCBs, sizeof(JPXCodeBlock)); + for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) { + subband->cbs[k].dataLen = NULL; + subband->cbs[k].touched = NULL; + subband->cbs[k].arithDecoder = NULL; + subband->cbs[k].stats = NULL; + } sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW); sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH); if (r == 0) { // (NL)LL @@ -2013,21 +2056,25 @@ GBool JPXStream::readTilePart() { cb->nZeroBitPlanes = 0; cb->dataLenSize = 1; cb->dataLen = (Guint *)gmalloc(sizeof(Guint)); - cb->coeffs = sbCoeffs - + (cb->y0 - subband->y0) * tileComp->w - + (cb->x0 - subband->x0); - cb->touched = (char *)gmalloc(1 << (tileComp->codeBlockW - + tileComp->codeBlockH)); - cb->len = 0; - for (cbj = 0; cbj < cb->y1 - cb->y0; ++cbj) { - for (cbi = 0; cbi < cb->x1 - cb->x0; ++cbi) { - cb->coeffs[cbj * tileComp->w + cbi] = 0; + if (r <= tileComp->nDecompLevels - reduction) { + cb->coeffs = sbCoeffs + + (cb->y0 - subband->y0) * tileComp->w + + (cb->x0 - subband->x0); + cb->touched = (char *)gmalloc(1 << (tileComp->codeBlockW + + tileComp->codeBlockH)); + cb->len = 0; + for (cbj = 0; cbj < cb->y1 - cb->y0; ++cbj) { + for (cbi = 0; cbi < cb->x1 - cb->x0; ++cbi) { + cb->coeffs[cbj * tileComp->w + cbi] = 0; + } } + memset(cb->touched, 0, + (1 << (tileComp->codeBlockW + tileComp->codeBlockH))); + } else { + cb->coeffs = NULL; + cb->touched = NULL; + cb->len = 0; } - memset(cb->touched, 0, - (1 << (tileComp->codeBlockW + tileComp->codeBlockH))); - cb->arithDecoder = NULL; - cb->stats = NULL; ++cb; } } @@ -2381,7 +2428,21 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp, Guint horiz, vert, diag, all, cx, xorBit; int horizSign, vertSign, bit; int segSym; - Guint i, x, y0, y1; + Guint n, i, x, y0, y1; + + if (res > tileComp->nDecompLevels - reduction) { + // skip the codeblock data + if (tileComp->codeBlockStyle & 0x04) { + n = 0; + for (i = 0; i < cb->nCodingPasses; ++i) { + n += cb->dataLen[i]; + } + } else { + n = cb->dataLen[0]; + } + bufStr->discardChars(n); + return gTrue; + } if (cb->arithDecoder) { cover(63); @@ -2735,7 +2796,7 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) { } if (tileComp->transform == 0) { cover(71); - shift += fracBits; + shift += fracBits - tileComp->prec; } // do fixed point adjustment and dequantization on (NL)LL @@ -2766,7 +2827,7 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) { cover(96); if (tileComp->transform == 0) { cover(97); - val &= -1 << fracBits; + val &= -1 << (fracBits - tileComp->prec); } } else { cover(98); @@ -2782,7 +2843,7 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) { //----- IDWT for each level - for (r = 1; r <= tileComp->nDecompLevels; ++r) { + for (r = 1; r <= tileComp->nDecompLevels - reduction; ++r) { resLevel = &tileComp->resLevels[r]; // (n)LL is already in the upper-left corner of the @@ -2837,7 +2898,7 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp, } if (tileComp->transform == 0) { cover(103); - shift += fracBits; + shift += fracBits - tileComp->prec; } // fixed point adjustment and dequantization @@ -2868,7 +2929,7 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp, if (qStyle == 0) { cover(76); if (tileComp->transform == 0) { - val &= -1 << fracBits; + val &= -1 << (fracBits - tileComp->prec); } } else { cover(77); @@ -3103,8 +3164,8 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { if (tile->tileComps[0].transform == 0) { cover(87); j = 0; - for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { - for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { + for (y = 0; y < tile->tileComps[0].h; ++y) { + for (x = 0; x < tile->tileComps[0].w; ++x) { d0 = tile->tileComps[0].data[j]; d1 = tile->tileComps[1].data[j]; d2 = tile->tileComps[2].data[j]; @@ -3120,8 +3181,8 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { } else { cover(88); j = 0; - for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { - for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { + for (y = 0; y < tile->tileComps[0].h; ++y) { + for (x = 0; x < tile->tileComps[0].w; ++x) { d0 = tile->tileComps[0].data[j]; d1 = tile->tileComps[1].data[j]; d2 = tile->tileComps[2].data[j]; @@ -3144,12 +3205,12 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { minVal = -(1 << (tileComp->prec - 1)); maxVal = (1 << (tileComp->prec - 1)) - 1; dataPtr = tileComp->data; - for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { - for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { + for (y = 0; y < tileComp->h; ++y) { + for (x = 0; x < tileComp->w; ++x) { coeff = *dataPtr; if (tileComp->transform == 0) { cover(109); - coeff >>= fracBits; + coeff >>= fracBits - tileComp->prec; } if (coeff < minVal) { cover(110); @@ -3168,12 +3229,12 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { maxVal = (1 << tileComp->prec) - 1; zeroVal = 1 << (tileComp->prec - 1); dataPtr = tileComp->data; - for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { - for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { + for (y = 0; y < tileComp->h; ++y) { + for (x = 0; x < tileComp->w; ++x) { coeff = *dataPtr; if (tileComp->transform == 0) { cover(112); - coeff >>= fracBits; + coeff >>= fracBits - tileComp->prec; } coeff += zeroVal; if (coeff < 0) { @@ -3339,16 +3400,12 @@ GBool JPXStream::readBits(int nBits, Guint *x) { } void JPXStream::skipSOP() { - int i; - // SOP occurs at the start of the packet header, so we don't need to // worry about bit-stuff prior to it if (byteCount >= 6 && bufStr->lookChar(0) == 0xff && bufStr->lookChar(1) == 0x91) { - for (i = 0; i < 6; ++i) { - bufStr->getChar(); - } + bufStr->discardChars(6); byteCount -= 6; bitBufLen = 0; bitBufSkip = gFalse; @@ -3356,15 +3413,13 @@ void JPXStream::skipSOP() { } void JPXStream::skipEPH() { - int i, k; + int k; k = bitBufSkip ? 1 : 0; if (byteCount >= (Guint)(k + 2) && bufStr->lookChar(k) == 0xff && bufStr->lookChar(k + 1) == 0x92) { - for (i = 0; i < k + 2; ++i) { - bufStr->getChar(); - } + bufStr->discardChars(k + 2); byteCount -= k + 2; bitBufLen = 0; bitBufSkip = gFalse; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JPXStream.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JPXStream.h index 2c46ca0150b..d00a55e34e3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/JPXStream.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/JPXStream.h @@ -199,7 +199,7 @@ struct JPXTileComp { //----- computed Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords - Guint w; // x1 - x0 + Guint w, h; // data size = {x1 - x0, y1 - y0} >> reduction Guint cbW; // code-block width Guint cbH; // code-block height @@ -234,6 +234,9 @@ struct JPXTile { Guint precinct; // precinct Guint layer; // layer + //----- tile part info + Guint nextTilePart; // next expected tile-part + //----- children JPXTileComp *tileComps; // the tile-components (len = JPXImage.nComps) }; @@ -247,6 +250,11 @@ struct JPXImage { Guint xTileSize, yTileSize; // size of tiles Guint xTileOffset, // offset of first tile yTileOffset; + Guint xSizeR, ySizeR; // size of reference grid >> reduction + Guint xOffsetR, yOffsetR; // image offset >> reduction + Guint xTileSizeR, yTileSizeR; // size of tiles >> reduction + Guint xTileOffsetR, // offset of first tile >> reduction + yTileOffsetR; Guint nComps; // number of components //----- computed @@ -259,6 +267,14 @@ struct JPXImage { //------------------------------------------------------------------------ +enum JPXDecodeResult { + jpxDecodeOk, + jpxDecodeNonFatalError, + jpxDecodeFatalError +}; + +//------------------------------------------------------------------------ + class JPXStream: public FilterStream { public: @@ -273,14 +289,15 @@ public: virtual GBool isBinary(GBool last = gTrue); virtual void getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode); + void reduceResolution(int reductionA) { reduction = reductionA; } private: void fillReadBuf(); void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode); - GBool readBoxes(); + JPXDecodeResult readBoxes(); GBool readColorSpecBox(Guint dataLen); - GBool readCodestream(Guint len); + JPXDecodeResult readCodestream(Guint len); GBool readTilePart(); GBool readTilePartData(Guint tileIdx, Guint tilePartLen, GBool tilePartToEOC); @@ -314,6 +331,7 @@ private: Guint nComps; // number of components Guint *bpc; // bits per component, for each component Guint width, height; // image size + int reduction; // log2(reduction in resolution) GBool haveImgHdr; // set if a JP2/JPX image header has been // found JPXColorSpec cs; // color specification diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Lexer.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Lexer.cc index 058975691b1..058975691b1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Lexer.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Lexer.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Lexer.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Lexer.h index f6ad9ce9699..3f466898575 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Lexer.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Lexer.h @@ -53,13 +53,12 @@ public: Stream *getStream() { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); } - // Get current position in file. This is only used for error - // messages, so it returns an int instead of a Guint. - int getPos() - { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); } + // Get current position in file. + GFileOffset getPos() + { return curStr.isNone() ? -1 : curStr.streamGetPos(); } // Set position in file. - void setPos(Guint pos, int dir = 0) + void setPos(GFileOffset pos, int dir = 0) { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); } // Returns true if <c> is a whitespace character. diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Link.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Link.cc index 56a29636317..86a3c417e45 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Link.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Link.cc @@ -39,7 +39,7 @@ LinkAction *LinkAction::parseDest(Object *obj) { LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) { LinkAction *action; - Object obj2, obj3, obj4; + Object obj2, obj3, obj4, obj5; if (!obj->isDict()) { error(errSyntaxWarning, -1, "Bad annotation action"); @@ -86,6 +86,30 @@ LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) { obj3.free(); obj4.free(); + // JavaScript action + } else if (obj2.isName("JavaScript")) { + obj->dictLookup("JS", &obj3); + action = new LinkJavaScript(&obj3); + obj3.free(); + + // SubmitForm action + } else if (obj2.isName("SubmitForm")) { + obj->dictLookup("F", &obj3); + obj->dictLookup("Fields", &obj4); + obj->dictLookup("Flags", &obj5); + action = new LinkSubmitForm(&obj3, &obj4, &obj5); + obj3.free(); + obj4.free(); + obj5.free(); + + // Hide action + } else if (obj2.isName("Hide")) { + obj->dictLookupNF("T", &obj3); + obj->dictLookup("H", &obj4); + action = new LinkHide(&obj3, &obj4); + obj3.free(); + obj4.free(); + // unknown action } else if (obj2.isName()) { action = new LinkUnknown(obj2.getName()); @@ -117,7 +141,7 @@ GString *LinkAction::getFileSpecName(Object *fileSpecObj) { // dictionary } else if (fileSpecObj->isDict()) { -#ifdef WIN32 +#ifdef _WIN32 if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) { #else if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) { @@ -139,7 +163,7 @@ GString *LinkAction::getFileSpecName(Object *fileSpecObj) { // system-dependent path manipulation if (name) { -#ifdef WIN32 +#ifdef _WIN32 int i, j; // "//...." --> "\...." @@ -517,7 +541,7 @@ LinkLaunch::LinkLaunch(Object *actionObj) { fileName = getFileSpecName(&obj1); } else { obj1.free(); -#ifdef WIN32 +#ifdef _WIN32 if (actionObj->dictLookup("Win", &obj1)->isDict()) { obj1.dictLookup("F", &obj2); fileName = getFileSpecName(&obj2); @@ -644,6 +668,98 @@ LinkMovie::~LinkMovie() { } //------------------------------------------------------------------------ +// LinkJavaScript +//------------------------------------------------------------------------ + +LinkJavaScript::LinkJavaScript(Object *jsObj) { + char buf[4096]; + int n; + + if (jsObj->isString()) { + js = jsObj->getString()->copy(); + } else if (jsObj->isStream()) { + js = new GString(); + jsObj->streamReset(); + while ((n = jsObj->getStream()->getBlock(buf, sizeof(buf))) > 0) { + js->append(buf, n); + } + jsObj->streamClose(); + } else { + error(errSyntaxError, -1, "JavaScript action JS key is wrong type"); + js = NULL; + } +} + +LinkJavaScript::~LinkJavaScript() { + if (js) { + delete js; + } +} + +//------------------------------------------------------------------------ +// LinkSubmitForm +//------------------------------------------------------------------------ + +LinkSubmitForm::LinkSubmitForm(Object *urlObj, Object *fieldsObj, + Object *flagsObj) { + if (urlObj->isString()) { + url = urlObj->getString()->copy(); + } else { + error(errSyntaxError, -1, "SubmitForm action URL is wrong type"); + url = NULL; + } + + if (fieldsObj->isArray()) { + fieldsObj->copy(&fields); + } else { + if (!fieldsObj->isNull()) { + error(errSyntaxError, -1, "SubmitForm action Fields value is wrong type"); + } + fields.initNull(); + } + + if (flagsObj->isInt()) { + flags = flagsObj->getInt(); + } else { + if (!flagsObj->isNull()) { + error(errSyntaxError, -1, "SubmitForm action Flags value is wrong type"); + } + flags = 0; + } +} + +LinkSubmitForm::~LinkSubmitForm() { + if (url) { + delete url; + } + fields.free(); +} + +//------------------------------------------------------------------------ +// LinkHide +//------------------------------------------------------------------------ + +LinkHide::LinkHide(Object *fieldsObj, Object *hideFlagObj) { + if (fieldsObj->isRef() || fieldsObj->isString() || fieldsObj->isArray()) { + fieldsObj->copy(&fields); + } else { + error(errSyntaxError, -1, "Hide action T value is wrong type"); + fields.initNull(); + } + + if (hideFlagObj->isBool()) { + hideFlag = hideFlagObj->getBool(); + } else { + error(errSyntaxError, -1, "Hide action H value is wrong type"); + hideFlag = gFalse; + } +} + +LinkHide::~LinkHide() { + fields.free(); +} + +//------------------------------------------------------------------------ // LinkUnknown //------------------------------------------------------------------------ @@ -745,7 +861,7 @@ Link::~Link() { Links::Links(Object *annots, GString *baseURI) { Link *link; - Object obj1, obj2; + Object obj1, obj2, obj3; int size; int i; @@ -756,7 +872,10 @@ Links::Links(Object *annots, GString *baseURI) { if (annots->isArray()) { for (i = 0; i < annots->arrayGetLength(); ++i) { if (annots->arrayGet(i, &obj1)->isDict()) { - if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) { + obj1.dictLookup("Subtype", &obj2); + obj1.dictLookup("FT", &obj3); + if (obj2.isName("Link") || + (obj2.isName("Widget") && (obj3.isName("Btn") || obj3.isNull()))) { link = new Link(obj1.getDict(), baseURI); if (link->isOk()) { if (numLinks >= size) { @@ -768,6 +887,7 @@ Links::Links(Object *annots, GString *baseURI) { delete link; } } + obj3.free(); obj2.free(); } obj1.free(); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Link.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Link.h index 55fbfa1cc2e..480496ad176 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Link.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Link.h @@ -32,6 +32,9 @@ enum LinkActionKind { actionURI, // URI actionNamed, // named action actionMovie, // movie action + actionJavaScript, // run JavaScript + actionSubmitForm, // submit form + actionHide, // hide annotation actionUnknown // anything else }; @@ -244,8 +247,10 @@ public: virtual ~LinkNamed(); + // Was the LinkNamed created successfully? virtual GBool isOk() { return name != NULL; } + // Accessors. virtual LinkActionKind getKind() { return actionNamed; } GString *getName() { return name; } @@ -265,8 +270,10 @@ public: virtual ~LinkMovie(); + // Was the LinkMovie created successfully? virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; } + // Accessors. virtual LinkActionKind getKind() { return actionMovie; } GBool hasAnnotRef() { return annotRef.num >= 0; } Ref *getAnnotRef() { return &annotRef; } @@ -279,6 +286,81 @@ private: }; //------------------------------------------------------------------------ +// LinkJavaScript +//------------------------------------------------------------------------ + +class LinkJavaScript: public LinkAction { +public: + + LinkJavaScript(Object *jsObj); + + virtual ~LinkJavaScript(); + + // Was the LinkJavaScript created successfully? + virtual GBool isOk() { return js != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionJavaScript; } + GString *getJS() { return js; } + +private: + + GString *js; +}; + +//------------------------------------------------------------------------ +// LinkSubmitForm +//------------------------------------------------------------------------ + +class LinkSubmitForm: public LinkAction { +public: + + LinkSubmitForm(Object *urlObj, Object *fieldsObj, Object *flagsObj); + + virtual ~LinkSubmitForm(); + + // Was the LinkSubmitForm created successfully? + virtual GBool isOk() { return url != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionSubmitForm; } + GString *getURL() { return url; } + Object *getFields() { return &fields; } + int getFlags() { return flags; } + +private: + + GString *url; + Object fields; + int flags; +}; + +//------------------------------------------------------------------------ +// LinkHide +//------------------------------------------------------------------------ + +class LinkHide: public LinkAction { +public: + + LinkHide(Object *fieldsObj, Object *hideFlagObj); + + virtual ~LinkHide(); + + // Was the LinkHide created successfully? + virtual GBool isOk() { return !fields.isNull(); } + + // Accessors. + virtual LinkActionKind getKind() { return actionHide; } + Object *getFields() { return &fields; } + GBool getHideFlag() { return hideFlag; } + +private: + + Object fields; + GBool hideFlag; +}; + +//------------------------------------------------------------------------ // LinkUnknown //------------------------------------------------------------------------ diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.dep b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.dep index e69de29bb2d..e69de29bb2d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Makefile.dep +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.in b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.in new file mode 100644 index 00000000000..de3e6766e60 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Makefile.in @@ -0,0 +1,687 @@ +#======================================================================== +# +# Xpdf Makefile +# +# Copyright 1996-2003 Glyph & Cog, LLC +# +#======================================================================== + +SHELL = /bin/sh + +prefix = @prefix@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +GOOSRCDIR = $(srcdir)/../goo +GOOLIBDIR = ../goo +FOFISRCDIR = $(srcdir)/../fofi +FOFILIBDIR = ../fofi +SPLASHSRCDIR = $(srcdir)/../splash +SPLASHLIBDIR = ../splash + +CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir)/.. -I$(GOOSRCDIR) -I$(FOFISRCDIR) -I$(SPLASHSRCDIR) -I$(srcdir) @freetype2_CFLAGS@ @Sgm_CFLAGS@ @Xm_CFLAGS@ @Xt_CFLAGS@ @Xp_CFLAGS@ @Xext_CFLAGS@ @Xpm_CFLAGS@ @libpng_CFLAGS@ @libpaper_CFLAGS@ @X_CFLAGS@ @EXTRA_CFLAGS@ + +LDFLAGS = @LDFLAGS@ + +FTLIBS = @freetype2_LIBS@ -lz + +XLIBS = @Sgm_LIBS@ @Xm_LIBS@ @Xt_LIBS@ @Xp_LIBS@ @Xext_LIBS@ @Xpm_LIBS@ @X_PRE_LIBS@ @X_LIBS@ -lX11 @X_EXTRA_LIBS@ + +PNGLIBS = @libpng_LIBS@ + +SPLASHLIBS = -L$(SPLASHLIBDIR) -lsplash + +OTHERLIBS = @LIBS@ @libpaper_LIBS@ @EXTRA_LIBS@ \ + -L$(FOFILIBDIR) -lfofi \ + -L$(GOOLIBDIR) -lGoo + +CXX = @CXX@ + +LIBPREFIX = @LIBPREFIX@ +EXE = @EXE@ + +#------------------------------------------------------------------------ + +.SUFFIXES: .cc + +.cc.o: + $(CXX) $(CXXFLAGS) -c $< + +#------------------------------------------------------------------------ + +CXX_SRC = \ + $(srcdir)/AcroForm.cc \ + $(srcdir)/Annot.cc \ + $(srcdir)/Array.cc \ + $(srcdir)/BuiltinFont.cc \ + $(srcdir)/BuiltinFontTables.cc \ + $(srcdir)/CMap.cc \ + $(srcdir)/Catalog.cc \ + $(srcdir)/CharCodeToUnicode.cc \ + $(srcdir)/CoreOutputDev.cc \ + $(srcdir)/Decrypt.cc \ + $(srcdir)/Dict.cc \ + $(srcdir)/Error.cc \ + $(srcdir)/FontEncodingTables.cc \ + $(srcdir)/Form.cc \ + $(srcdir)/Function.cc \ + $(srcdir)/Gfx.cc \ + $(srcdir)/GfxFont.cc \ + $(srcdir)/GfxState.cc \ + $(srcdir)/GlobalParams.cc \ + $(srcdir)/HTMLGen.cc \ + $(srcdir)/ImageOutputDev.cc \ + $(srcdir)/JArithmeticDecoder.cc \ + $(srcdir)/JBIG2Stream.cc \ + $(srcdir)/JPXStream.cc \ + $(srcdir)/Lexer.cc \ + $(srcdir)/Link.cc \ + $(srcdir)/NameToCharCode.cc \ + $(srcdir)/Object.cc \ + $(srcdir)/OptionalContent.cc \ + $(srcdir)/Outline.cc \ + $(srcdir)/OutputDev.cc \ + $(srcdir)/PDFCore.cc \ + $(srcdir)/PDFDoc.cc \ + $(srcdir)/PDFDocEncoding.cc \ + $(srcdir)/PSOutputDev.cc \ + $(srcdir)/PSTokenizer.cc \ + $(srcdir)/Page.cc \ + $(srcdir)/Parser.cc \ + $(srcdir)/PreScanOutputDev.cc \ + $(srcdir)/SecurityHandler.cc \ + $(srcdir)/SplashOutputDev.cc \ + $(srcdir)/Stream.cc \ + $(srcdir)/TextOutputDev.cc \ + $(srcdir)/TextString.cc \ + $(srcdir)/UnicodeMap.cc \ + $(srcdir)/UnicodeTypeTable.cc \ + $(srcdir)/XFAForm.cc \ + $(srcdir)/XPDFApp.cc \ + $(srcdir)/XPDFCore.cc \ + $(srcdir)/XPDFTree.cc \ + $(srcdir)/XPDFViewer.cc \ + $(srcdir)/XpdfPluginAPI.cc \ + $(srcdir)/XRef.cc \ + $(srcdir)/Zoox.cc \ + $(srcdir)/pdftops.cc \ + $(srcdir)/pdftotext.cc \ + $(srcdir)/pdftohtml.cc \ + $(srcdir)/pdfinfo.cc \ + $(srcdir)/pdffonts.cc \ + $(srcdir)/pdfdetach.cc \ + $(srcdir)/pdftoppm.cc \ + $(srcdir)/pdftopng.cc \ + $(srcdir)/pdfimages.cc \ + $(srcdir)/xpdf.cc + +#------------------------------------------------------------------------ + +all: xpdf$(EXE) pdftops$(EXE) pdftotext$(EXE) pdftohtml$(EXE) \ + pdfinfo$(EXE) pdffonts$(EXE) pdfdetach$(EXE) pdftoppm$(EXE) \ + pdftopng$(EXE) pdfimages$(EXE) + +all-no-x: pdftops$(EXE) pdftotext$(EXE) pdftohtml$(EXE) pdfinfo$(EXE) \ + pdffonts$(EXE) pdfdetach$(EXE) pdfimages$(EXE) + +#------------------------------------------------------------------------ + +XPDF_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + CoreOutputDev.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFCore.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PreScanOutputDev.o \ + PSOutputDev.o \ + PSTokenizer.o \ + SecurityHandler.o \ + SplashOutputDev.o \ + Stream.o \ + TextOutputDev.o \ + TextString.o \ + UnicodeMap.o \ + UnicodeTypeTable.o \ + XFAForm.o \ + XPDFApp.o \ + XPDFCore.o \ + XPDFTree.o \ + XPDFViewer.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + xpdf.o +XPDF_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(FTLIBS) \ + $(XLIBS) $(OTHERLIBS) -lm + +xpdf$(EXE): $(XPDF_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o xpdf$(EXE) $(XPDF_OBJS) $(XPDF_LIBS) + +#------------------------------------------------------------------------ + +PDFTOPS_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + OptionalContent.o \ + Outline.o \ + Object.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PreScanOutputDev.o \ + PSOutputDev.o \ + PSTokenizer.o \ + SecurityHandler.o \ + SplashOutputDev.o \ + Stream.o \ + TextString.o \ + UnicodeMap.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdftops.o +PDFTOPS_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(FTLIBS) \ + $(OTHERLIBS) -lm + +pdftops$(EXE): $(PDFTOPS_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftops$(EXE) $(PDFTOPS_OBJS) \ + $(PDFTOPS_LIBS) + +#------------------------------------------------------------------------ + +PDFTOTEXT_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + Stream.o \ + TextOutputDev.o \ + TextString.o \ + UnicodeMap.o \ + UnicodeTypeTable.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdftotext.o +PDFTOTEXT_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm + +pdftotext$(EXE): $(PDFTOTEXT_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftotext$(EXE) $(PDFTOTEXT_OBJS) \ + $(PDFTOTEXT_LIBS) + +#------------------------------------------------------------------------ + +PDFTOHTML_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + HTMLGen.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + SplashOutputDev.o \ + Stream.o \ + TextOutputDev.o \ + TextString.o \ + UnicodeMap.o \ + UnicodeTypeTable.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdftohtml.o +PDFTOHTML_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(FTLIBS) \ + $(OTHERLIBS) $(PNGLIBS) -lm + +pdftohtml$(EXE): $(PDFTOHTML_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftohtml$(EXE) $(PDFTOHTML_OBJS) \ + $(PDFTOHTML_LIBS) + +#------------------------------------------------------------------------ + +PDFINFO_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + Stream.o \ + TextString.o \ + UnicodeMap.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdfinfo.o +PDFINFO_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm + +pdfinfo$(EXE): $(PDFINFO_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfinfo$(EXE) $(PDFINFO_OBJS) \ + $(PDFINFO_LIBS) + +#------------------------------------------------------------------------ + +PDFFONTS_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + Stream.o \ + TextString.o \ + UnicodeMap.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdffonts.o +PDFFONTS_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm + +pdffonts$(EXE): $(PDFFONTS_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdffonts$(EXE) $(PDFFONTS_OBJS) \ + $(PDFFONTS_LIBS) + +#------------------------------------------------------------------------ + +PDFDETACH_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + Stream.o \ + TextString.o \ + UnicodeMap.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdfdetach.o +PDFDETACH_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm + +pdfdetach$(EXE): $(PDFDETACH_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfdetach$(EXE) $(PDFDETACH_OBJS) \ + $(PDFDETACH_LIBS) + +#------------------------------------------------------------------------ + +PDFTOPPM_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + SplashOutputDev.o \ + Stream.o \ + TextOutputDev.o \ + TextString.o \ + UnicodeMap.o \ + UnicodeTypeTable.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdftoppm.o +PDFTOPPM_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(FTLIBS) \ + $(OTHERLIBS) -lm + +pdftoppm$(EXE): $(PDFTOPPM_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftoppm$(EXE) $(PDFTOPPM_OBJS) \ + $(PDFTOPPM_LIBS) + +#------------------------------------------------------------------------ + +PDFTOPNG_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + SplashOutputDev.o \ + Stream.o \ + TextOutputDev.o \ + TextString.o \ + UnicodeMap.o \ + UnicodeTypeTable.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdftopng.o +PDFTOPNG_LIBS = -L$(GOOLIBDIR) -lGoo $(SPLASHLIBS) $(FTLIBS) \ + $(OTHERLIBS) $(PNGLIBS) -lm + +pdftopng$(EXE): $(PDFTOPNG_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdftopng$(EXE) $(PDFTOPNG_OBJS) \ + $(PDFTOPNG_LIBS) + +#------------------------------------------------------------------------ + +PDFIMAGES_OBJS = \ + AcroForm.o \ + Annot.o \ + Array.o \ + BuiltinFont.o \ + BuiltinFontTables.o \ + Catalog.o \ + CharCodeToUnicode.o \ + CMap.o \ + Decrypt.o \ + Dict.o \ + Error.o \ + FontEncodingTables.o \ + Form.o \ + Function.o \ + Gfx.o \ + GfxFont.o \ + GfxState.o \ + GlobalParams.o \ + ImageOutputDev.o \ + JArithmeticDecoder.o \ + JBIG2Stream.o \ + JPXStream.o \ + Lexer.o \ + Link.o \ + NameToCharCode.o \ + Object.o \ + OptionalContent.o \ + Outline.o \ + OutputDev.o \ + Page.o \ + Parser.o \ + PDFDoc.o \ + PDFDocEncoding.o \ + PSTokenizer.o \ + SecurityHandler.o \ + Stream.o \ + TextString.o \ + UnicodeMap.o \ + XFAForm.o \ + XpdfPluginAPI.o \ + XRef.o \ + Zoox.o \ + pdfimages.o +PDFIMAGES_LIBS = -L$(GOOLIBDIR) -lGoo $(OTHERLIBS) -lm + +pdfimages$(EXE): $(PDFIMAGES_OBJS) $(GOOLIBDIR)/$(LIBPREFIX)Goo.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o pdfimages$(EXE) $(PDFIMAGES_OBJS) \ + $(PDFIMAGES_LIBS) + +#------------------------------------------------------------------------ + +clean: + rm -f $(XPDF_OBJS) xpdf$(EXE) + rm -f $(PDFTOPS_OBJS) pdftops$(EXE) + rm -f $(PDFTOTEXT_OBJS) pdftotext$(EXE) + rm -f $(PDFTOHTML_OBJS) pdftohtml$(EXE) + rm -f $(PDFINFO_OBJS) pdfinfo$(EXE) + rm -f $(PDFFONTS_OBJS) pdffonts$(EXE) + rm -f $(PDFDETACH_OBJS) pdfdetach$(EXE) + rm -f $(PDFTOPPM_OBJS) pdftoppm$(EXE) + rm -f $(PDFTOPNG_OBJS) pdftopng$(EXE) + rm -f $(PDFIMAGES_OBJS) pdfimages$(EXE) + +#------------------------------------------------------------------------ + +depend: + $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep + +-include Makefile.dep diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToCharCode.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToCharCode.cc index c05fdf58787..c05fdf58787 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToCharCode.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToCharCode.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToCharCode.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToCharCode.h index 6548133cdcd..6548133cdcd 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToCharCode.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToCharCode.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToUnicodeTable.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToUnicodeTable.h index c516dea27e6..c516dea27e6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/NameToUnicodeTable.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/NameToUnicodeTable.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Object.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Object.cc index 3536bcfeed9..3536bcfeed9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Object.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Object.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Object.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Object.h index e1abed94b35..64c75f737c7 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Object.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Object.h @@ -19,6 +19,7 @@ #include <string.h> #include "gtypes.h" #include "gmem.h" +#include "gfile.h" #include "GString.h" class XRef; @@ -179,9 +180,10 @@ public: void streamClose(); int streamGetChar(); int streamLookChar(); + int streamGetBlock(char *blk, int size); char *streamGetLine(char *buf, int size); - Guint streamGetPos(); - void streamSetPos(Guint pos, int dir = 0); + GFileOffset streamGetPos(); + void streamSetPos(GFileOffset pos, int dir = 0); Dict *streamGetDict(); // Output. @@ -288,13 +290,16 @@ inline int Object::streamGetChar() inline int Object::streamLookChar() { return stream->lookChar(); } +inline int Object::streamGetBlock(char *blk, int size) + { return stream->getBlock(blk, size); } + inline char *Object::streamGetLine(char *buf, int size) { return stream->getLine(buf, size); } -inline Guint Object::streamGetPos() +inline GFileOffset Object::streamGetPos() { return stream->getPos(); } -inline void Object::streamSetPos(Guint pos, int dir) +inline void Object::streamSetPos(GFileOffset pos, int dir) { stream->setPos(pos, dir); } inline Dict *Object::streamGetDict() diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OptionalContent.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OptionalContent.cc index 589719cfe6d..bebb674ce23 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OptionalContent.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OptionalContent.cc @@ -2,7 +2,7 @@ // // OptionalContent.cc // -// Copyright 2008 Glyph & Cog, LLC +// Copyright 2008-2013 Glyph & Cog, LLC // //======================================================================== @@ -17,7 +17,7 @@ #include "Error.h" #include "Object.h" #include "PDFDoc.h" -#include "PDFDocEncoding.h" +#include "TextString.h" #include "OptionalContent.h" //------------------------------------------------------------------------ @@ -150,70 +150,79 @@ GBool OptionalContent::evalOCObject(Object *obj, GBool *visible) { } } obj->fetch(xref, &obj2); - if (obj2.isDict("OCMD")) { - if (obj2.dictLookup("VE", &obj3)->isArray()) { - *visible = evalOCVisibilityExpr(&obj3, 0); - obj3.free(); - } else { - obj3.free(); - policy = ocPolicyAnyOn; - if (obj2.dictLookup("P", &obj3)->isName()) { - if (obj3.isName("AllOn")) { - policy = ocPolicyAllOn; - } else if (obj3.isName("AnyOn")) { - policy = ocPolicyAnyOn; - } else if (obj3.isName("AnyOff")) { - policy = ocPolicyAnyOff; - } else if (obj3.isName("AllOff")) { - policy = ocPolicyAllOff; - } + if (!obj2.isDict("OCMD")) { + obj2.free(); + return gFalse; + } + if (obj2.dictLookup("VE", &obj3)->isArray()) { + *visible = evalOCVisibilityExpr(&obj3, 0); + obj3.free(); + } else { + obj3.free(); + policy = ocPolicyAnyOn; + if (obj2.dictLookup("P", &obj3)->isName()) { + if (obj3.isName("AllOn")) { + policy = ocPolicyAllOn; + } else if (obj3.isName("AnyOn")) { + policy = ocPolicyAnyOn; + } else if (obj3.isName("AnyOff")) { + policy = ocPolicyAnyOff; + } else if (obj3.isName("AllOff")) { + policy = ocPolicyAllOff; } - obj3.free(); - obj2.dictLookupNF("OCGs", &obj3); - ocg = NULL; - if (obj3.isRef()) { - ref = obj3.getRef(); - ocg = findOCG(&ref); + } + obj3.free(); + obj2.dictLookupNF("OCGs", &obj3); + ocg = NULL; + if (obj3.isRef()) { + ref = obj3.getRef(); + ocg = findOCG(&ref); + } + if (ocg) { + *visible = (policy == ocPolicyAllOn || policy == ocPolicyAnyOn) ? + ocg->getState() : !ocg->getState(); + } else { + *visible = policy == ocPolicyAllOn || policy == ocPolicyAllOff; + if (!obj3.fetch(xref, &obj4)->isArray()) { + obj4.free(); + obj3.free(); + obj2.free(); + return gFalse; } - if (ocg) { - *visible = (policy == ocPolicyAllOn || policy == ocPolicyAnyOn) ? - ocg->getState() : !ocg->getState(); - } else { - *visible = gTrue; - if (obj3.fetch(xref, &obj4)->isArray()) { - for (i = 0; i < obj4.arrayGetLength(); ++i) { - obj4.arrayGetNF(i, &obj5); - if (obj5.isRef()) { - ref = obj5.getRef(); - if ((ocg = findOCG(&ref))) { - switch (policy) { - case ocPolicyAllOn: - *visible = *visible && ocg->getState(); - break; - case ocPolicyAnyOn: - *visible = *visible || ocg->getState(); - break; - case ocPolicyAnyOff: - *visible = *visible || !ocg->getState(); - break; - case ocPolicyAllOff: - *visible = *visible && !ocg->getState(); - break; - } - } - } + for (i = 0; i < obj4.arrayGetLength(); ++i) { + obj4.arrayGetNF(i, &obj5); + if (obj5.isRef()) { + ref = obj5.getRef(); + if (!(ocg = findOCG(&ref))) { obj5.free(); + obj4.free(); + obj3.free(); + obj2.free(); + return gFalse; + } + switch (policy) { + case ocPolicyAllOn: + *visible = *visible && ocg->getState(); + break; + case ocPolicyAnyOn: + *visible = *visible || ocg->getState(); + break; + case ocPolicyAnyOff: + *visible = *visible || !ocg->getState(); + break; + case ocPolicyAllOff: + *visible = *visible && !ocg->getState(); + break; } } - obj4.free(); + obj5.free(); } - obj3.free(); + obj4.free(); } - obj2.free(); - return gTrue; + obj3.free(); } obj2.free(); - return gFalse; + return gTrue; } GBool OptionalContent::evalOCVisibilityExpr(Object *expr, int recursion) { @@ -279,12 +288,9 @@ GBool OptionalContent::evalOCVisibilityExpr(Object *expr, int recursion) { //------------------------------------------------------------------------ OptionalContentGroup *OptionalContentGroup::parse(Ref *refA, Object *obj) { - Unicode *nameA; - int nameLenA; + TextString *nameA; Object obj1, obj2, obj3; - GString *s; OCUsageState viewStateA, printStateA; - int i; if (!obj->isDict()) { return NULL; @@ -294,22 +300,7 @@ OptionalContentGroup *OptionalContentGroup::parse(Ref *refA, Object *obj) { obj1.free(); return NULL; } - s = obj1.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - nameLenA = (s->getLength() - 2) / 2; - nameA = (Unicode *)gmallocn(nameLenA, sizeof(Unicode)); - for (i = 0; i < nameLenA; ++i) { - nameA[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | - (s->getChar(3 + 2*i) & 0xff); - } - } else { - nameLenA = s->getLength(); - nameA = (Unicode *)gmallocn(nameLenA, sizeof(Unicode)); - for (i = 0; i < nameLenA; ++i) { - nameA[i] = pdfDocEncoding[s->getChar(i) & 0xff]; - } - } + nameA = new TextString(obj1.getString()); obj1.free(); viewStateA = printStateA = ocUsageUnset; @@ -339,30 +330,35 @@ OptionalContentGroup *OptionalContentGroup::parse(Ref *refA, Object *obj) { } obj1.free(); - return new OptionalContentGroup(refA, nameA, nameLenA, - viewStateA, printStateA); + return new OptionalContentGroup(refA, nameA, viewStateA, printStateA); } -OptionalContentGroup::OptionalContentGroup(Ref *refA, Unicode *nameA, - int nameLenA, +OptionalContentGroup::OptionalContentGroup(Ref *refA, TextString *nameA, OCUsageState viewStateA, OCUsageState printStateA) { ref = *refA; name = nameA; - nameLen = nameLenA; viewState = viewStateA; printState = printStateA; state = gTrue; } OptionalContentGroup::~OptionalContentGroup() { - gfree(name); + delete name; } GBool OptionalContentGroup::matches(Ref *refA) { return refA->num == ref.num && refA->gen == ref.gen; } +Unicode *OptionalContentGroup::getName() { + return name->getUnicode(); +} + +int OptionalContentGroup::getNameLength() { + return name->getLength(); +} + //------------------------------------------------------------------------ OCDisplayNode *OCDisplayNode::parse(Object *obj, OptionalContent *oc, @@ -404,8 +400,10 @@ OCDisplayNode *OCDisplayNode::parse(Object *obj, OptionalContent *oc, obj2.arrayGetNF(i, &obj3); if ((child = OCDisplayNode::parse(&obj3, oc, xref, recursion + 1))) { if (!child->ocg && !child->name && node->getNumChildren() > 0) { - node->getChild(node->getNumChildren() - 1)-> - addChildren(child->takeChildren()); + if (child->getNumChildren() > 0) { + node->getChild(node->getNumChildren() - 1)-> + addChildren(child->takeChildren()); + } delete child; } else { node->addChild(child); @@ -418,42 +416,19 @@ OCDisplayNode *OCDisplayNode::parse(Object *obj, OptionalContent *oc, } OCDisplayNode::OCDisplayNode() { - name = NULL; - nameLen = 0; + name = new TextString(); ocg = NULL; children = NULL; } OCDisplayNode::OCDisplayNode(GString *nameA) { - int i; - - if ((nameA->getChar(0) & 0xff) == 0xfe && - (nameA->getChar(1) & 0xff) == 0xff) { - nameLen = (nameA->getLength() - 2) / 2; - name = (Unicode *)gmallocn(nameLen, sizeof(Unicode)); - for (i = 0; i < nameLen; ++i) { - name[i] = ((nameA->getChar(2 + 2*i) & 0xff) << 8) | - (nameA->getChar(3 + 2*i) & 0xff); - } - } else { - nameLen = nameA->getLength(); - name = (Unicode *)gmallocn(nameLen, sizeof(Unicode)); - for (i = 0; i < nameLen; ++i) { - name[i] = pdfDocEncoding[nameA->getChar(i) & 0xff]; - } - } + name = new TextString(nameA); ocg = NULL; children = NULL; } OCDisplayNode::OCDisplayNode(OptionalContentGroup *ocgA) { - nameLen = ocgA->getNameLength(); - if (nameLen) { - name = (Unicode *)gmallocn(nameLen, sizeof(Unicode)); - memcpy(name, ocgA->getName(), nameLen * sizeof(Unicode)); - } else { - name = NULL; - } + name = new TextString(ocgA->name); ocg = ocgA; children = NULL; } @@ -482,12 +457,20 @@ GList *OCDisplayNode::takeChildren() { } OCDisplayNode::~OCDisplayNode() { - gfree(name); + delete name; if (children) { deleteGList(children, OCDisplayNode); } } +Unicode *OCDisplayNode::getName() { + return name->getUnicode(); +} + +int OCDisplayNode::getNameLength() { + return name->getLength(); +} + int OCDisplayNode::getNumChildren() { if (!children) { return 0; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OptionalContent.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OptionalContent.h index 82d3e0ef521..e2ea2446bbc 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OptionalContent.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OptionalContent.h @@ -2,7 +2,7 @@ // // OptionalContent.h // -// Copyright 2008 Glyph & Cog, LLC +// Copyright 2008-2013 Glyph & Cog, LLC // //======================================================================== @@ -22,6 +22,7 @@ class GString; class GList; class PDFDoc; +class TextString; class XRef; class OptionalContentGroup; class OCDisplayNode; @@ -78,8 +79,8 @@ public: GBool matches(Ref *refA); - Unicode *getName() { return name; } - int getNameLength() { return nameLen; } + Unicode *getName(); + int getNameLength(); OCUsageState getViewState() { return viewState; } OCUsageState getPrintState() { return printState; } GBool getState() { return state; } @@ -87,15 +88,16 @@ public: private: - OptionalContentGroup(Ref *refA, Unicode *nameA, int nameLenA, + OptionalContentGroup(Ref *refA, TextString *nameA, OCUsageState viewStateA, OCUsageState printStateA); Ref ref; - Unicode *name; - int nameLen; + TextString *name; OCUsageState viewState, // suggested state when viewing printState; // suggested state when printing GBool state; // current state (on/off) + + friend class OCDisplayNode; }; //------------------------------------------------------------------------ @@ -108,8 +110,8 @@ public: OCDisplayNode(); ~OCDisplayNode(); - Unicode *getName() { return name; } - int getNameLength() { return nameLen; } + Unicode *getName(); + int getNameLength(); OptionalContentGroup *getOCG() { return ocg; } int getNumChildren(); OCDisplayNode *getChild(int idx); @@ -122,8 +124,7 @@ private: void addChildren(GList *childrenA); GList *takeChildren(); - Unicode *name; // display name (may be NULL) - int nameLen; + TextString *name; // display name OptionalContentGroup *ocg; // NULL for display labels GList *children; // NULL if there are no children // [OCDisplayNode] diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Outline.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Outline.cc index 30ca85d85b7..e87f61e0db9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Outline.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Outline.cc @@ -2,7 +2,7 @@ // // Outline.cc // -// Copyright 2002-2003 Glyph & Cog, LLC +// Copyright 2002-2013 Glyph & Cog, LLC // //======================================================================== @@ -17,7 +17,7 @@ #include "GList.h" #include "Error.h" #include "Link.h" -#include "PDFDocEncoding.h" +#include "TextString.h" #include "Outline.h" //------------------------------------------------------------------------ @@ -32,7 +32,7 @@ Outline::Outline(Object *outlineObj, XRef *xref) { outlineObj->dictLookupNF("First", &first); outlineObj->dictLookupNF("Last", &last); if (first.isRef() && last.isRef()) { - items = OutlineItem::readItemList(&first, &last, xref); + items = OutlineItem::readItemList(&first, &last, NULL, xref); } first.free(); last.free(); @@ -46,35 +46,18 @@ Outline::~Outline() { //------------------------------------------------------------------------ -OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) { +OutlineItem::OutlineItem(Object *itemRefA, Dict *dict, + OutlineItem *parentA, XRef *xrefA) { Object obj1; - GString *s; - int i; xref = xrefA; title = NULL; action = NULL; kids = NULL; + parent = parentA; if (dict->lookup("Title", &obj1)->isString()) { - s = obj1.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - titleLen = (s->getLength() - 2) / 2; - title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); - for (i = 0; i < titleLen; ++i) { - title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | - (s->getChar(3 + 2*i) & 0xff); - } - } else { - titleLen = s->getLength(); - title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); - for (i = 0; i < titleLen; ++i) { - title[i] = pdfDocEncoding[s->getChar(i) & 0xff]; - } - } - } else { - titleLen = 0; + title = new TextString(obj1.getString()); } obj1.free(); @@ -88,6 +71,7 @@ OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) { } obj1.free(); + itemRefA->copy(&itemRef); dict->lookupNF("First", &firstRef); dict->lookupNF("Last", &lastRef); dict->lookupNF("Next", &nextRef); @@ -104,22 +88,24 @@ OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) { OutlineItem::~OutlineItem() { close(); if (title) { - gfree(title); + delete title; } if (action) { delete action; } + itemRef.free(); firstRef.free(); lastRef.free(); nextRef.free(); } GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, - XRef *xrefA) { + OutlineItem *parentA, XRef *xrefA) { GList *items; - OutlineItem *item; + OutlineItem *item, *sibling; Object obj; - Object *p, *refObj; + Object *p; + OutlineItem *ancestor; int i; items = new GList(); @@ -132,8 +118,36 @@ GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, obj.free(); break; } - item = new OutlineItem(obj.getDict(), xrefA); + item = new OutlineItem(p, obj.getDict(), parentA, xrefA); obj.free(); + + // check for loops with parents + for (ancestor = parentA; ancestor; ancestor = ancestor->parent) { + if (p->getRefNum() == ancestor->itemRef.getRefNum() && + p->getRefGen() == ancestor->itemRef.getRefGen()) { + error(errSyntaxError, -1, "Loop detected in outline"); + break; + } + } + if (ancestor) { + delete item; + break; + } + + // check for loops with siblings + for (i = 0; i < items->getLength(); ++i) { + sibling = (OutlineItem *)items->get(i); + if (p->getRefNum() == sibling->itemRef.getRefNum() && + p->getRefGen() == sibling->itemRef.getRefGen()) { + error(errSyntaxError, -1, "Loop detected in outline"); + break; + } + } + if (i < items->getLength()) { + delete item; + break; + } + items->append(item); if (p->getRefNum() == lastItemRef->getRef().num && p->getRefGen() == lastItemRef->getRef().gen) { @@ -143,23 +157,13 @@ GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, if (!p->isRef()) { break; } - for (i = 0; i < items->getLength(); ++i) { - refObj = (i == 0) ? firstItemRef - : &((OutlineItem *)items->get(i - 1))->nextRef; - if (refObj->getRefNum() == p->getRefNum() && - refObj->getRefGen() == p->getRefGen()) { - error(errSyntaxError, -1, "Loop detected in outline item list"); - p = NULL; - break; - } - } } while (p); return items; } void OutlineItem::open() { if (!kids) { - kids = readItemList(&firstRef, &lastRef, xref); + kids = readItemList(&firstRef, &lastRef, this, xref); } } @@ -169,3 +173,11 @@ void OutlineItem::close() { kids = NULL; } } + +Unicode *OutlineItem::getTitle() { + return title ? title->getUnicode() : (Unicode *)NULL; +} + +int OutlineItem::getTitleLength() { + return title ? title->getLength() : 0; +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Outline.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Outline.h index f38f8d16121..a9c2089e6c3 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Outline.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Outline.h @@ -2,7 +2,7 @@ // // Outline.h // -// Copyright 2002-2003 Glyph & Cog, LLC +// Copyright 2002-2013 Glyph & Cog, LLC // //======================================================================== @@ -22,6 +22,7 @@ class GString; class GList; class XRef; class LinkAction; +class TextString; //------------------------------------------------------------------------ @@ -44,17 +45,18 @@ private: class OutlineItem { public: - OutlineItem(Dict *dict, XRef *xrefA); + OutlineItem(Object *itemRefA, Dict *dict, OutlineItem *parentA, XRef *xrefA); ~OutlineItem(); static GList *readItemList(Object *firstItemRef, Object *lastItemRef, - XRef *xrefA); + OutlineItem *parentA, XRef *xrefA); void open(); void close(); - Unicode *getTitle() { return title; } - int getTitleLength() { return titleLen; } + Unicode *getTitle(); + int getTitleLength(); + TextString *getTitleTextString() { return title; } LinkAction *getAction() { return action; } GBool isOpen() { return startsOpen; } GBool hasKids() { return firstRef.isRef(); } @@ -63,14 +65,15 @@ public: private: XRef *xref; - Unicode *title; - int titleLen; + TextString *title; // may be NULL LinkAction *action; + Object itemRef; Object firstRef; Object lastRef; Object nextRef; GBool startsOpen; GList *kids; // NULL unless this item is open [OutlineItem] + OutlineItem *parent; }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OutputDev.cc index d2ef286859a..2d17547210e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OutputDev.cc @@ -43,6 +43,11 @@ void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) { *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5]; } +void OutputDev::cvtUserToDev(double ux, double uy, double *dx, double *dy) { + *dx = defCTM[0] * ux + defCTM[2] * uy + defCTM[4]; + *dy = defCTM[1] * ux + defCTM[3] * uy + defCTM[5]; +} + void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) { *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5); *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5); @@ -78,14 +83,10 @@ GBool OutputDev::beginType3Char(GfxState *state, double x, double y, void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { - int i, j; - + GBool inlineImg, GBool interpolate) { if (inlineImg) { str->reset(); - j = height * ((width + 7) / 8); - for (i = 0; i < j; ++i) - str->getChar(); + str->discardChars(height * ((width + 7) / 8)); str->close(); } } @@ -93,21 +94,17 @@ void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, void OutputDev::setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { - drawImageMask(state, ref, str, width, height, invert, inlineImg); + GBool inlineImg, GBool interpolate) { + drawImageMask(state, ref, str, width, height, invert, inlineImg, interpolate); } void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { - int i, j; - + int *maskColors, GBool inlineImg, GBool interpolate) { if (inlineImg) { str->reset(); - j = height * ((width * colorMap->getNumPixelComps() * - colorMap->getBits() + 7) / 8); - for (i = 0; i < j; ++i) - str->getChar(); + str->discardChars(height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8)); str->close(); } } @@ -117,8 +114,9 @@ void OutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert) { - drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); + GBool maskInvert, GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, NULL, gFalse, + interpolate); } void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, @@ -126,8 +124,10 @@ void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap) { - drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); + GfxImageColorMap *maskColorMap, + GBool interpolate) { + drawImage(state, ref, str, width, height, colorMap, NULL, gFalse, + interpolate); } #if OPI_SUPPORT diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OutputDev.h index 138aa34882b..759e356df18 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/OutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/OutputDev.h @@ -112,6 +112,7 @@ public: // Convert between device and user coordinates. virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy); + virtual void cvtUserToDev(double ux, double uy, double *dx, double *dy); virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy); double *getDefCTM() { return defCTM; } @@ -161,7 +162,7 @@ public: virtual void stroke(GfxState *state) {} virtual void fill(GfxState *state) {} virtual void eoFill(GfxState *state) {} - virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -201,25 +202,26 @@ public: //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); + int *maskColors, GBool inlineImg, GBool interpolate); virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); + GBool maskInvert, GBool interpolate); virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap); + GfxImageColorMap *maskColorMap, + GBool interpolate); #if OPI_SUPPORT //----- OPI functions diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFCore.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFCore.cc index 6435815fc1d..34b64835c67 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFCore.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFCore.cc @@ -2,7 +2,7 @@ // // PDFCore.cc // -// Copyright 2004 Glyph & Cog, LLC +// Copyright 2004-2013 Glyph & Cog, LLC // //======================================================================== @@ -100,7 +100,8 @@ PDFCore::PDFCore(SplashColorMode colorModeA, int bitmapRowPadA, selectULY = selectLRY = 0; dragging = gFalse; lastDragLeft = lastDragTop = gTrue; - selectXorColor[0] = selectXorColor[1] = selectXorColor[2] = 0; + selectXorColor[0] = selectXorColor[1] = selectXorColor[2] = + reverseVideoA ? 0xff : 0x00; splashColorXor(selectXorColor, paperColorA); historyCur = pdfHistorySize - 1; @@ -128,7 +129,11 @@ PDFCore::~PDFCore() { } for (i = 0; i < pdfHistorySize; ++i) { if (history[i].fileName) { +#ifdef _WIN32 + delete[] history[i].fileName; +#else delete history[i].fileName; +#endif } } gfree(pageY); @@ -147,7 +152,7 @@ int PDFCore::loadFile(GString *fileName, GString *ownerPassword, return err; } -#ifdef WIN32 +#ifdef _WIN32 int PDFCore::loadFile(wchar_t *fileName, int fileNameLen, GString *ownerPassword, GString *userPassword) { int err; @@ -423,6 +428,7 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA, // check for changes to the PDF file if ((force || (!continuousMode && topPage != topPageA)) && + doc->getFileName() && checkForNewFile()) { if (loadFile(doc->getFileName()) == errNone) { if (topPageA > doc->getNumPages()) { @@ -758,13 +764,30 @@ void PDFCore::update(int topPageA, int scrollXA, int scrollYA, } hist = &history[historyCur]; if (hist->fileName) { +#ifdef _WIN32 + delete[] hist->fileName; +#else delete hist->fileName; +#endif + } +#ifdef _WIN32 + if (doc->getFileNameU()) { + hist->fileName = (wchar_t *)gmallocn(MAX_PATH + 1, sizeof(wchar_t)); + if (GetFullPathNameW(doc->getFileNameU(), MAX_PATH + 1, + hist->fileName, NULL) == 0) { + delete[] hist->fileName; + hist->fileName = NULL; + } + } else { + hist->fileName = NULL; } +#else if (doc->getFileName()) { hist->fileName = doc->getFileName()->copy(); } else { hist->fileName = NULL; } +#endif hist->page = topPage; if (historyBLen < pdfHistorySize) { ++historyBLen; @@ -807,6 +830,7 @@ void PDFCore::addPage(int pg, int rot) { void PDFCore::needTile(PDFCorePage *page, int x, int y) { PDFCoreTile *tile; + TextOutputControl textOutCtrl; TextOutputDev *textOut; int xDest, yDest, sliceW, sliceH; int i; @@ -893,7 +917,8 @@ void PDFCore::needTile(PDFCorePage *page, int x, int y) { page->links = doc->getLinks(page->page); } if (!page->text) { - if ((textOut = new TextOutputDev(NULL, gTrue, 0, gFalse, gFalse))) { + textOutCtrl.mode = textOutPhysLayout; + if ((textOut = new TextOutputDev(NULL, &textOutCtrl, gFalse))) { doc->displayPage(textOut, page->page, dpi, dpi, rotate, gFalse, gTrue, gFalse); page->text = textOut->takeText(); @@ -977,11 +1002,27 @@ GBool PDFCore::goForward() { } --historyFLen; ++historyBLen; - if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (!history[historyCur].fileName) { + return gFalse; + } +#ifdef _WIN32 + if (!doc || + !doc->getFileNameU() || + wcscmp(history[historyCur].fileName, doc->getFileNameU()) != 0) { + if (loadFile(history[historyCur].fileName, + wcslen(history[historyCur].fileName)) != errNone) { + return gFalse; + } + } +#else + if (!doc || + !doc->getFileName() || + history[historyCur].fileName->cmp(doc->getFileName()) != 0) { if (loadFile(history[historyCur].fileName) != errNone) { return gFalse; } } +#endif pg = history[historyCur].page; update(pg, scrollX, continuousMode ? -1 : scrollY, zoom, rotate, gFalse, gFalse, gTrue); @@ -999,11 +1040,27 @@ GBool PDFCore::goBackward() { } --historyBLen; ++historyFLen; - if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (!history[historyCur].fileName) { + return gFalse; + } +#ifdef _WIN32 + if (!doc || + !doc->getFileNameU() || + wcscmp(history[historyCur].fileName, doc->getFileNameU()) != 0) { + if (loadFile(history[historyCur].fileName, + wcslen(history[historyCur].fileName)) != errNone) { + return gFalse; + } + } +#else + if (!doc || + !doc->getFileName() || + history[historyCur].fileName->cmp(doc->getFileName()) != 0) { if (loadFile(history[historyCur].fileName) != errNone) { return gFalse; } } +#endif pg = history[historyCur].page; update(pg, scrollX, continuousMode ? -1 : scrollY, zoom, rotate, gFalse, gFalse, gTrue); @@ -1615,6 +1672,7 @@ GBool PDFCore::getSelection(int *pg, double *ulx, double *uly, GString *PDFCore::extractText(int pg, double xMin, double yMin, double xMax, double yMax) { PDFCorePage *page; + TextOutputControl textOutCtrl; TextOutputDev *textOut; int x0, y0, x1, y1, t; GString *s; @@ -1633,7 +1691,8 @@ GString *PDFCore::extractText(int pg, double xMin, double yMin, } s = page->text->getText(x0, y0, x1, y1); } else { - textOut = new TextOutputDev(NULL, gTrue, 0, gFalse, gFalse); + textOutCtrl.mode = textOutPhysLayout; + textOut = new TextOutputDev(NULL, &textOutCtrl, gFalse); if (textOut->isOk()) { doc->displayPage(textOut, pg, dpi, dpi, rotate, gFalse, gTrue, gFalse); textOut->cvtUserToDev(xMin, yMin, &x0, &y0); @@ -1675,10 +1734,10 @@ GBool PDFCore::find(char *s, GBool caseSensitive, GBool next, GBool backward, GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive, GBool next, GBool backward, GBool wholeWord, GBool onePageOnly) { + TextOutputControl textOutCtrl; TextOutputDev *textOut; double xMin, yMin, xMax, yMax; PDFCorePage *page; - PDFCoreTile *tile; int pg; GBool startAtTop, startAtLast, stopAtLast; @@ -1721,7 +1780,8 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive, if (!onePageOnly) { // search following/previous pages - textOut = new TextOutputDev(NULL, gTrue, 0, gFalse, gFalse); + textOutCtrl.mode = textOutPhysLayout; + textOut = new TextOutputDev(NULL, &textOutCtrl, gFalse); if (!textOut->isOk()) { delete textOut; goto notFound; @@ -1791,7 +1851,6 @@ GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive, // found: change the selection found: - tile = (PDFCoreTile *)page->tiles->get(0); setSelection(pg, (int)floor(xMin), (int)floor(yMin), (int)ceil(xMax), (int)ceil(yMax)); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFCore.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFCore.h index 264756f828f..1be1010024b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFCore.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFCore.h @@ -100,7 +100,11 @@ public: //------------------------------------------------------------------------ struct PDFHistory { +#ifdef _WIN32 + wchar_t *fileName; +#else GString *fileName; +#endif int page; }; @@ -125,7 +129,7 @@ public: virtual int loadFile(GString *fileName, GString *ownerPassword = NULL, GString *userPassword = NULL); -#ifdef WIN32 +#ifdef _WIN32 // Load a new file. Returns pdfOk or error code. virtual int loadFile(wchar_t *fileName, int fileNameLen, GString *ownerPassword = NULL, diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDoc.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDoc.cc index b20ef2c1530..51262897f72 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDoc.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDoc.cc @@ -16,7 +16,7 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> -#ifdef WIN32 +#ifdef _WIN32 # include <windows.h> #endif #include "GString.h" @@ -52,7 +52,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, GString *userPassword, PDFCore *coreA) { Object obj; GString *fileName1, *fileName2; -#ifdef WIN32 +#ifdef _WIN32 int n, i; #endif @@ -71,7 +71,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, optContent = NULL; fileName = fileNameA; -#ifdef WIN32 +#ifdef _WIN32 n = fileName->getLength(); fileNameU = (wchar_t *)gmallocn(n + 1, sizeof(wchar_t)); for (i = 0; i < n; ++i) { @@ -114,7 +114,7 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, ok = setup(ownerPassword, userPassword); } -#ifdef WIN32 +#ifdef _WIN32 PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, GString *userPassword, PDFCore *coreA) { OSVERSIONINFO version; @@ -169,7 +169,7 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, GString *userPassword, PDFCore *coreA) { -#ifdef WIN32 +#ifdef _WIN32 int n, i; #endif @@ -178,7 +178,7 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, core = coreA; if (strA->getFileName()) { fileName = strA->getFileName()->copy(); -#ifdef WIN32 +#ifdef _WIN32 n = fileName->getLength(); fileNameU = (wchar_t *)gmallocn(n + 1, sizeof(wchar_t)); for (i = 0; i < n; ++i) { @@ -188,7 +188,7 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, #endif } else { fileName = NULL; -#ifdef WIN32 +#ifdef _WIN32 fileNameU = NULL; #endif } @@ -231,6 +231,7 @@ GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { // read the optional content info optContent = new OptionalContent(this); + // done return gTrue; } @@ -294,7 +295,7 @@ PDFDoc::~PDFDoc() { if (fileName) { delete fileName; } -#ifdef WIN32 +#ifdef _WIN32 if (fileNameU) { gfree(fileNameU); } @@ -309,10 +310,8 @@ void PDFDoc::checkHeader() { int i; pdfVersion = 0; - for (i = 0; i < headerSearchSize; ++i) { - hdrBuf[i] = str->getChar(); - } - hdrBuf[headerSearchSize] = '\0'; + memset(hdrBuf, 0, headerSearchSize + 1); + str->getBlock(hdrBuf, headerSearchSize); for (i = 0; i < headerSearchSize - 5; ++i) { if (!strncmp(&hdrBuf[i], "%PDF-", 5)) { break; @@ -455,15 +454,16 @@ GBool PDFDoc::isLinearized() { GBool PDFDoc::saveAs(GString *name) { FILE *f; - int c; + char buf[4096]; + int n; if (!(f = fopen(name->getCString(), "wb"))) { error(errIO, -1, "Couldn't open file '{0:t}'", name); return gFalse; } str->reset(); - while ((c = str->getChar()) != EOF) { - fputc(c, f); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); } str->close(); fclose(f); @@ -482,7 +482,7 @@ GBool PDFDoc::saveEmbeddedFile(int idx, char *path) { return ret; } -#ifdef WIN32 +#ifdef _WIN32 GBool PDFDoc::saveEmbeddedFile(int idx, wchar_t *path, int pathLen) { FILE *f; OSVERSIONINFO version; @@ -518,14 +518,15 @@ GBool PDFDoc::saveEmbeddedFile(int idx, wchar_t *path, int pathLen) { GBool PDFDoc::saveEmbeddedFile2(int idx, FILE *f) { Object strObj; - int c; + char buf[4096]; + int n; if (!catalog->getEmbeddedFileStreamObj(idx, &strObj)) { return gFalse; } strObj.streamReset(); - while ((c = strObj.streamGetChar()) != EOF) { - fputc(c, f); + while ((n = strObj.streamGetBlock(buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, f); } strObj.streamClose(); strObj.free(); @@ -535,24 +536,28 @@ GBool PDFDoc::saveEmbeddedFile2(int idx, FILE *f) { char *PDFDoc::getEmbeddedFileMem(int idx, int *size) { Object strObj; char *buf; - int bufSize, len, c; + int bufSize, sizeInc, n; if (!catalog->getEmbeddedFileStreamObj(idx, &strObj)) { return NULL; } strObj.streamReset(); - bufSize = 1024; - buf = (char *)gmalloc(bufSize); - len = 0; - while ((c = strObj.streamGetChar()) != EOF) { - if (len == bufSize) { - bufSize *= 2; - buf = (char *)grealloc(buf, bufSize); + bufSize = 0; + buf = NULL; + do { + sizeInc = bufSize ? bufSize : 1024; + if (bufSize > INT_MAX - sizeInc) { + error(errIO, -1, "embedded file is too large"); + *size = 0; + return NULL; } - buf[len++] = (char)c; - } + buf = (char *)grealloc(buf, bufSize + sizeInc); + n = strObj.streamGetBlock(buf + bufSize, sizeInc); + bufSize += n; + } while (n == sizeInc); strObj.streamClose(); strObj.free(); - *size = len; + *size = bufSize; return buf; } + diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDoc.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDoc.h index 94fcfb73659..509c1d5ac84 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDoc.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDoc.h @@ -39,7 +39,7 @@ public: PDFDoc(GString *fileNameA, GString *ownerPassword = NULL, GString *userPassword = NULL, PDFCore *coreA = NULL); -#ifdef WIN32 +#ifdef _WIN32 PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL, GString *userPassword = NULL, PDFCore *coreA = NULL); #endif @@ -55,7 +55,7 @@ public: // Get file name. GString *getFileName() { return fileName; } -#ifdef WIN32 +#ifdef _WIN32 wchar_t *getFileNameU() { return fileNameU; } #endif @@ -172,11 +172,12 @@ public: int getEmbeddedFileNameLength(int idx) { return catalog->getEmbeddedFileNameLength(idx); } GBool saveEmbeddedFile(int idx, char *path); -#ifdef WIN32 +#ifdef _WIN32 GBool saveEmbeddedFile(int idx, wchar_t *path, int pathLen); #endif char *getEmbeddedFileMem(int idx, int *size); + private: GBool setup(GString *ownerPassword, GString *userPassword); @@ -187,7 +188,7 @@ private: GBool saveEmbeddedFile2(int idx, FILE *f); GString *fileName; -#ifdef WIN32 +#ifdef _WIN32 wchar_t *fileNameU; #endif FILE *file; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDocEncoding.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDocEncoding.cc index d173cefd717..d173cefd717 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDocEncoding.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDocEncoding.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDocEncoding.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDocEncoding.h index 3259d3e1064..3259d3e1064 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PDFDocEncoding.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PDFDocEncoding.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSOutputDev.cc index 55e576b8aa9..9521f6ce0e5 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSOutputDev.cc @@ -2,7 +2,7 @@ // // PSOutputDev.cc // -// Copyright 1996-2003 Glyph & Cog, LLC +// Copyright 1996-2013 Glyph & Cog, LLC // //======================================================================== @@ -39,6 +39,8 @@ #include "XRef.h" #include "PreScanOutputDev.h" #include "CharCodeToUnicode.h" +#include "Form.h" +#include "TextString.h" #if HAVE_SPLASH # include "Splash.h" # include "SplashBitmap.h" @@ -57,11 +59,6 @@ #endif //------------------------------------------------------------------------ - -// Max size of a slice when rasterizing pages, in pixels. -#define rasterizationSliceSize 20000000 - -//------------------------------------------------------------------------ // PostScript prolog and setup //------------------------------------------------------------------------ @@ -85,24 +82,29 @@ static const char *prolog[] = { " } for", "~123sn", "/pdfSetup {", + " /pdfDuplex exch def", " /setpagedevice where {", " pop 2 dict begin", " /Policies 1 dict dup begin /PageSize 6 def end def", - " { /Duplex true def } if", + " pdfDuplex { /Duplex true def } if", " currentdict end setpagedevice", - " } {", - " pop", - " } ifelse", + " } if", + " /pdfPageW 0 def", + " /pdfPageH 0 def", "} def", "/pdfSetupPaper {", - " 2 array astore", - " /setpagedevice where {", - " pop 2 dict begin", - " /PageSize exch def", - " /ImagingBBox null def", - " currentdict end setpagedevice", + " 2 copy pdfPageH ne exch pdfPageW ne or {", + " /pdfPageH exch def", + " /pdfPageW exch def", + " /setpagedevice where {", + " pop 3 dict begin", + " /PageSize [pdfPageW pdfPageH] def", + " pdfDuplex { /Duplex true def } if", + " /ImagingBBox null def", + " currentdict end setpagedevice", + " } if", " } {", - " pop", + " pop pop", " } ifelse", "} def", "~1sn", @@ -571,17 +573,14 @@ static const char *prolog[] = { "} def", "~23sn", "/pdfImM { fCol imagemask skipEOD } def", - "/pr { 2 index 2 index 3 2 roll putinterval 4 add } def", - "/pdfImClip {", - " gsave", - " 0 2 4 index length 1 sub {", - " dup 4 index exch 2 copy", - " get 5 index div put", - " 1 add 3 index exch 2 copy", - " get 3 index div put", - " } for", - " pop pop rectclip", + "/pr {", + " 4 2 roll exch 5 index div exch 4 index div moveto", + " exch 3 index div dup 0 rlineto", + " exch 2 index div 0 exch rlineto", + " neg 0 rlineto", + " closepath", "} def", + "/pdfImClip { gsave clip } def", "/pdfImClipEnd { grestore } def", "~23sn", "% shading operators", @@ -736,6 +735,19 @@ static const char *prolog[] = { NULL }; +static const char *minLineWidthProlog[] = { + "/pdfDist { dup dtransform dup mul exch dup mul add 0.5 mul sqrt } def", + "/pdfIDist { dup idtransform dup mul exch dup mul add 0.5 mul sqrt } def", + "/pdfMinLineDist pdfMinLineWidth pdfDist def", + "/setlinewidth {", + " dup pdfDist pdfMinLineDist lt {", + " pop pdfMinLineDist pdfIDist", + " } if", + " setlinewidth", + "} bind def", + NULL +}; + static const char *cmapProlog[] = { "/CIDInit /ProcSet findresource begin", "10 dict begin", @@ -809,25 +821,68 @@ static PSSubstFont psBase14SubstFonts[14] = { {"ZapfDingbats", 0} }; -// Mapping from Type 1/1C font file to PS font name. -struct PST1FontName { - Ref fontFileID; - GString *psName; // PostScript font name used for this - // embedded font file -}; +class PSFontInfo { +public: + + PSFontInfo(Ref fontIDA) + { fontID = fontIDA; ff = NULL; } -// Info for 8-bit fonts -struct PSFont8Info { Ref fontID; - int *codeToGID; // code-to-GID mapping for TrueType fonts + PSFontFileInfo *ff; // pointer to font file info; NULL indicates + // font mapping failed }; -// Encoding info for substitute 16-bit font -struct PSFont16Enc { - Ref fontID; - GString *enc; // NULL means font wasn't correctly substituted +enum PSFontFileLocation { + psFontFileResident, + psFontFileEmbedded, + psFontFileExternal }; +class PSFontFileInfo { +public: + + PSFontFileInfo(GString *psNameA, GfxFontType typeA, + PSFontFileLocation locA); + ~PSFontFileInfo(); + + GString *psName; // name under which font is defined + GfxFontType type; // font type + PSFontFileLocation loc; // font location + Ref embFontID; // object ID for the embedded font file + // (for all embedded fonts) + GString *extFileName; // external font file path + // (for all external fonts) + GString *encoding; // encoding name (for resident CID fonts) + int *codeToGID; // mapping from code/CID to GID + // (for TrueType, OpenType-TrueType, and + // CID OpenType-CFF fonts) + int codeToGIDLen; // length of codeToGID array +}; + +PSFontFileInfo::PSFontFileInfo(GString *psNameA, GfxFontType typeA, + PSFontFileLocation locA) { + psName = psNameA; + type = typeA; + loc = locA; + embFontID.num = embFontID.gen = -1; + extFileName = NULL; + encoding = NULL; + codeToGID = NULL; +} + +PSFontFileInfo::~PSFontFileInfo() { + delete psName; + if (extFileName) { + delete extFileName; + } + if (encoding) { + delete encoding; + } + if (codeToGID) { + gfree(codeToGID); + } +} + //------------------------------------------------------------------------ // process colors //------------------------------------------------------------------------ @@ -998,11 +1053,8 @@ PSOutputDev::PSOutputDev(char *fileName, PDFDoc *docA, customCodeCbk = customCodeCbkA; customCodeCbkData = customCodeCbkDataA; - fontIDs = NULL; - fontNames = new GHash(gTrue); - t1FontNames = NULL; - font8Info = NULL; - font16Enc = NULL; + fontInfo = new GList(); + fontFileInfo = new GHash(); imgIDs = NULL; formIDs = NULL; xobjStack = NULL; @@ -1019,7 +1071,7 @@ PSOutputDev::PSOutputDev(char *fileName, PDFDoc *docA, } else if (fileName[0] == '|') { fileTypeA = psPipe; #ifdef HAVE_POPEN -#ifndef WIN32 +#ifndef _WIN32 signal(SIGPIPE, (SignalFunc)SIG_IGN); #endif if (!(f = popen(fileName + 1, "w"))) { @@ -1060,11 +1112,8 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, customCodeCbk = customCodeCbkA; customCodeCbkData = customCodeCbkDataA; - fontIDs = NULL; - fontNames = new GHash(gTrue); - t1FontNames = NULL; - font8Info = NULL; - font16Enc = NULL; + fontInfo = new GList(); + fontFileInfo = new GHash(); imgIDs = NULL; formIDs = NULL; xobjStack = NULL; @@ -1088,6 +1137,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, Page *page; PDFRectangle *box; PSOutPaperSize *size; + PSFontFileInfo *ff; GList *names; int pg, w, h, i; @@ -1118,8 +1168,13 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, pg <= lastPage && pg <= catalog->getNumPages(); ++pg) { page = catalog->getPage(pg); - w = (int)ceil(page->getMediaWidth()); - h = (int)ceil(page->getMediaHeight()); + if (globalParams->getPSUseCropBoxAsPage()) { + w = (int)ceil(page->getCropWidth()); + h = (int)ceil(page->getCropHeight()); + } else { + w = (int)ceil(page->getMediaWidth()); + h = (int)ceil(page->getMediaHeight()); + } for (i = 0; i < paperSizes->getLength(); ++i) { size = (PSOutPaperSize *)paperSizes->get(i); if (size->w == w && size->h == h) { @@ -1160,25 +1215,21 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, clipLLX0 = clipLLY0 = 0; clipURX0 = clipURY0 = -1; - // initialize fontIDs and fontNames lists - fontIDSize = 64; - fontIDLen = 0; - fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref)); + // initialize font lists, etc. for (i = 0; i < 14; ++i) { - fontNames->add(new GString(psBase14SubstFonts[i].psName), 1); + ff = new PSFontFileInfo(new GString(psBase14SubstFonts[i].psName), + fontType1, psFontFileResident); + fontFileInfo->add(ff->psName, ff); } names = globalParams->getPSResidentFonts(); for (i = 0; i < names->getLength(); ++i) { - fontNames->add((GString *)names->get(i), 1); + if (!fontFileInfo->lookup((GString *)names->get(i))) { + ff = new PSFontFileInfo((GString *)names->get(i), fontType1, + psFontFileResident); + fontFileInfo->add(ff->psName, ff); + } } delete names; - t1FontNameSize = 64; - t1FontNameLen = 0; - t1FontNames = (PST1FontName *)gmallocn(t1FontNameSize, sizeof(PST1FontName)); - font8InfoLen = 0; - font8InfoSize = 0; - font16EncLen = 0; - font16EncSize = 0; imgIDLen = 0; imgIDSize = 0; formIDLen = 0; @@ -1224,7 +1275,6 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, PSOutputDev::~PSOutputDev() { PSOutCustomColor *cc; - int i; if (ok) { if (!manualCtrl) { @@ -1243,7 +1293,7 @@ PSOutputDev::~PSOutputDev() { #ifdef HAVE_POPEN else if (fileType == psPipe) { pclose((FILE *)outputStream); -#ifndef WIN32 +#ifndef _WIN32 signal(SIGPIPE, (SignalFunc)SIG_DFL); #endif } @@ -1255,30 +1305,8 @@ PSOutputDev::~PSOutputDev() { if (embFontList) { delete embFontList; } - if (fontIDs) { - gfree(fontIDs); - } - delete fontNames; - if (t1FontNames) { - for (i = 0; i < t1FontNameLen; ++i) { - delete t1FontNames[i].psName; - } - gfree(t1FontNames); - } - if (font8Info) { - for (i = 0; i < font8InfoLen; ++i) { - gfree(font8Info[i].codeToGID); - } - gfree(font8Info); - } - if (font16Enc) { - for (i = 0; i < font16EncLen; ++i) { - if (font16Enc[i].enc) { - delete font16Enc[i].enc; - } - } - gfree(font16Enc); - } + deleteGList(fontInfo, PSFontInfo); + deleteGHash(fontFileInfo, PSFontFileInfo); gfree(imgIDs); gfree(formIDs); if (xobjStack) { @@ -1291,6 +1319,16 @@ PSOutputDev::~PSOutputDev() { } } +GBool PSOutputDev::checkIO() { + if (fileType == psFile || fileType == psPipe || fileType == psStdout) { + if (ferror((FILE *)outputStream)) { + error(errIO, -1, "Error writing to PostScript file"); + return gFalse; + } + } + return gTrue; +} + void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *mediaBox, PDFRectangle *cropBox, int pageRotate) { @@ -1395,6 +1433,7 @@ void PSOutputDev::writeXpdfProcset() { GBool lev1, lev2, lev3, sep, nonSep; const char **p; const char *q; + double w; writePSFmt("%%BeginResource: procset xpdf {0:s} 0\n", xpdfVersion); writePSFmt("%%Copyright: {0:s}\n", xpdfCopyright); @@ -1420,6 +1459,12 @@ void PSOutputDev::writeXpdfProcset() { writePSFmt("{0:s}\n", *p); } } + if ((w = globalParams->getPSMinLineWidth()) > 0) { + writePSFmt("/pdfMinLineWidth {0:.4g} def\n", w); + for (p = minLineWidthProlog; *p; ++p) { + writePSFmt("{0:s}\n", *p); + } + } writePS("%%EndResource\n"); if (level >= psLevel3) { @@ -1434,10 +1479,10 @@ void PSOutputDev::writeDocSetup(Catalog *catalog, Page *page; Dict *resDict; Annots *annots; - Object *acroForm; + Form *form; Object obj1, obj2, obj3; GString *s; - int pg, i; + int pg, i, j; if (mode == psModeForm) { // swap the form and xpdf dicts @@ -1464,23 +1509,22 @@ void PSOutputDev::writeDocSetup(Catalog *catalog, } delete annots; } - if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) { - if (acroForm->dictLookup("DR", &obj1)->isDict()) { - setupResources(obj1.getDict()); - } - obj1.free(); - if (acroForm->dictLookup("Fields", &obj1)->isArray()) { - for (i = 0; i < obj1.arrayGetLength(); ++i) { - if (obj1.arrayGet(i, &obj2)->isDict()) { - if (obj2.dictLookup("DR", &obj3)->isDict()) { - setupResources(obj3.getDict()); + if ((form = catalog->getForm())) { + for (i = 0; i < form->getNumFields(); ++i) { + form->getField(i)->getResources(&obj1); + if (obj1.isArray()) { + for (j = 0; j < obj1.arrayGetLength(); ++j) { + obj1.arrayGet(j, &obj2); + if (obj2.isDict()) { + setupResources(obj2.getDict()); } - obj3.free(); + obj2.free(); } - obj2.free(); + } else if (obj1.isDict()) { + setupResources(obj1.getDict()); } + obj1.free(); } - obj1.free(); } if (mode != psModeForm) { if (mode != psModeEPS && !manualCtrl) { @@ -1503,6 +1547,9 @@ void PSOutputDev::writeDocSetup(Catalog *catalog, delete s; } } + if (mode != psModeForm) { + writePS("end\n"); + } } void PSOutputDev::writePageTrailer() { @@ -1517,7 +1564,6 @@ void PSOutputDev::writeTrailer() { if (mode == psModeForm) { writePS("/Foo exch /Form defineresource pop\n"); } else { - writePS("end\n"); writePS("%%DocumentSuppliedResources:\n"); writePS(embFontList->getCString()); if (level == psLevel1Sep || level == psLevel2Sep || @@ -1554,14 +1600,14 @@ void PSOutputDev::writeTrailer() { } void PSOutputDev::setupResources(Dict *resDict) { - Object xObjDict, xObjRef, xObj, patDict, patRef, pat, resObj; + Object xObjDict, xObjRef, xObj, patDict, patRef, pat; + Object gsDict, gsRef, gs, smask, smaskGroup, resObj; Ref ref0, ref1; GBool skip; int i, j; setupFonts(resDict); setupImages(resDict); - setupForms(resDict); //----- recursively scan XObjects resDict->lookup("XObject", &xObjDict); @@ -1648,6 +1694,55 @@ void PSOutputDev::setupResources(Dict *resDict) { inType3Char = gFalse; } patDict.free(); + + //----- recursively scan SMask transparency groups in ExtGState dicts + resDict->lookup("ExtGState", &gsDict); + if (gsDict.isDict()) { + for (i = 0; i < gsDict.dictGetLength(); ++i) { + + // avoid infinite recursion on ExtGStates + skip = gFalse; + if ((gsDict.dictGetValNF(i, &gsRef)->isRef())) { + ref0 = gsRef.getRef(); + for (j = 0; j < xobjStack->getLength(); ++j) { + ref1 = *(Ref *)xobjStack->get(j); + if (ref1.num == ref0.num && ref1.gen == ref0.gen) { + skip = gTrue; + break; + } + } + if (!skip) { + xobjStack->append(&ref0); + } + } + if (!skip) { + + // process the ExtGState's SMask's transparency group's resource dict + if (gsDict.dictGetVal(i, &gs)->isDict()) { + if (gs.dictLookup("SMask", &smask)->isDict()) { + if (smask.dictLookup("G", &smaskGroup)->isStream()) { + smaskGroup.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + setupResources(resObj.getDict()); + } + resObj.free(); + } + smaskGroup.free(); + } + smask.free(); + } + gs.free(); + } + + if (gsRef.isRef() && !skip) { + xobjStack->del(xobjStack->getLength() - 1); + } + gsRef.free(); + } + } + gsDict.free(); + + setupForms(resDict); } void PSOutputDev::setupFonts(Dict *resDict) { @@ -1681,8 +1776,8 @@ void PSOutputDev::setupFonts(Dict *resDict) { } void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { + PSFontInfo *fi; GfxFontLoc *fontLoc; - GString *psName; GBool subst; char buf[16]; UnicodeMap *uMap; @@ -1693,123 +1788,101 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { int i, j; // check if font is already set up - for (i = 0; i < fontIDLen; ++i) { - if (fontIDs[i].num == font->getID()->num && - fontIDs[i].gen == font->getID()->gen) { + for (i = 0; i < fontInfo->getLength(); ++i) { + fi = (PSFontInfo *)fontInfo->get(i); + if (fi->fontID.num == font->getID()->num && + fi->fontID.gen == font->getID()->gen) { return; } } - // add entry to fontIDs list - if (fontIDLen >= fontIDSize) { - fontIDSize += 64; - fontIDs = (Ref *)greallocn(fontIDs, fontIDSize, sizeof(Ref)); - } - fontIDs[fontIDLen++] = *font->getID(); + // add fontInfo entry + fi = new PSFontInfo(*font->getID()); + fontInfo->append(fi); - psName = NULL; xs = ys = 1; subst = gFalse; if (font->getType() == fontType3) { - psName = GString::format("T3_{0:d}_{1:d}", - font->getID()->num, font->getID()->gen); - setupType3Font(font, psName, parentResDict); + fi->ff = setupType3Font(font, parentResDict); } else { - fontLoc = font->locateFont(xref, gTrue); - switch (fontLoc->locType) { - case gfxFontLocEmbedded: - switch (fontLoc->fontType) { - case fontType1: - // this assumes that the PS font name matches the PDF font name - psName = font->getEmbeddedFontName()->copy(); - setupEmbeddedType1Font(&fontLoc->embFontID, psName); - break; - case fontType1C: - psName = makePSFontName(font, &fontLoc->embFontID); - setupEmbeddedType1CFont(font, &fontLoc->embFontID, psName); - break; - case fontType1COT: - psName = makePSFontName(font, &fontLoc->embFontID); - setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID, psName); - break; - case fontTrueType: - case fontTrueTypeOT: - psName = makePSFontName(font, font->getID()); - setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID, psName); - break; - case fontCIDType0C: - psName = makePSFontName(font, &fontLoc->embFontID); - setupEmbeddedCIDType0Font(font, &fontLoc->embFontID, psName); - break; - case fontCIDType2: - case fontCIDType2OT: - psName = makePSFontName(font, font->getID()); - //~ should check to see if font actually uses vertical mode - setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, psName, gTrue); - break; - case fontCIDType0COT: - psName = makePSFontName(font, &fontLoc->embFontID); - setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID, psName); - break; - default: - break; - } - break; - case gfxFontLocExternal: - //~ add cases for external 16-bit fonts - switch (fontLoc->fontType) { - case fontType1: - if (font->getName()) { - // this assumes that the PS font name matches the PDF font name - psName = font->getName()->copy(); - } else { - //~ this won't work -- the PS font name won't match - psName = makePSFontName(font, font->getID()); + if ((fontLoc = font->locateFont(xref, gTrue))) { + switch (fontLoc->locType) { + case gfxFontLocEmbedded: + switch (fontLoc->fontType) { + case fontType1: + fi->ff = setupEmbeddedType1Font(font, &fontLoc->embFontID); + break; + case fontType1C: + fi->ff = setupEmbeddedType1CFont(font, &fontLoc->embFontID); + break; + case fontType1COT: + fi->ff = setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID); + break; + case fontTrueType: + case fontTrueTypeOT: + fi->ff = setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID); + break; + case fontCIDType0C: + fi->ff = setupEmbeddedCIDType0Font(font, &fontLoc->embFontID); + break; + case fontCIDType2: + case fontCIDType2OT: + //~ should check to see if font actually uses vertical mode + fi->ff = setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, + gTrue); + break; + case fontCIDType0COT: + fi->ff = setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID); + break; + default: + break; } - setupExternalType1Font(fontLoc->path, psName); - break; - case fontTrueType: - case fontTrueTypeOT: - psName = makePSFontName(font, font->getID()); - setupExternalTrueTypeFont(font, fontLoc->path, psName); break; - case fontCIDType2: - case fontCIDType2OT: - psName = makePSFontName(font, font->getID()); - //~ should check to see if font actually uses vertical mode - setupExternalCIDTrueTypeFont(font, fontLoc->path, psName, gTrue); + case gfxFontLocExternal: + //~ add cases for other external 16-bit fonts + switch (fontLoc->fontType) { + case fontType1: + fi->ff = setupExternalType1Font(font, fontLoc->path); + break; + case fontTrueType: + case fontTrueTypeOT: + fi->ff = setupExternalTrueTypeFont(font, fontLoc->path, + fontLoc->fontNum); + break; + case fontCIDType2: + case fontCIDType2OT: + //~ should check to see if font actually uses vertical mode + fi->ff = setupExternalCIDTrueTypeFont(font, fontLoc->path, + fontLoc->fontNum, gTrue); + break; + default: + break; + } break; - default: + case gfxFontLocResident: + if (!(fi->ff = (PSFontFileInfo *)fontFileInfo->lookup(fontLoc->path))) { + // handle psFontPassthrough + fi->ff = new PSFontFileInfo(fontLoc->path->copy(), fontLoc->fontType, + psFontFileResident); + fontFileInfo->add(fi->ff->psName, fi->ff); + } break; } - break; - case gfxFontLocResident: - psName = fontLoc->path->copy(); - break; } - if (!psName) { + if (!fi->ff) { if (font->isCIDFont()) { error(errSyntaxError, -1, - "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)", + "Couldn't find a font for '{0:s}' ('{1:s}' character collection)", font->getName() ? font->getName()->getCString() : "(unnamed)", ((GfxCIDFont *)font)->getCollection() ? ((GfxCIDFont *)font)->getCollection()->getCString() : "(unknown)"); - if (font16EncLen >= font16EncSize) { - font16EncSize += 16; - font16Enc = (PSFont16Enc *)greallocn(font16Enc, - font16EncSize, - sizeof(PSFont16Enc)); - } - font16Enc[font16EncLen].fontID = *font->getID(); - font16Enc[font16EncLen].enc = NULL; - ++font16EncLen; } else { error(errSyntaxError, -1, - "Couldn't find a font to substitute for '{0:s}'", + "Couldn't find a font for '{0:s}'", font->getName() ? font->getName()->getCString() : "(unnamed)"); } @@ -1843,23 +1916,14 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { if (fontLoc->locType == gfxFontLocResident && fontLoc->fontType >= fontCIDType0) { subst = gTrue; - if (font16EncLen >= font16EncSize) { - font16EncSize += 16; - font16Enc = (PSFont16Enc *)greallocn(font16Enc, - font16EncSize, - sizeof(PSFont16Enc)); - } - font16Enc[font16EncLen].fontID = *font->getID(); if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding))) { - font16Enc[font16EncLen].enc = fontLoc->encoding->copy(); + fi->ff->encoding = fontLoc->encoding->copy(); uMap->decRefCnt(); } else { error(errSyntaxError, -1, "Couldn't find Unicode map for 16-bit font encoding '{0:t}'", fontLoc->encoding); - font16Enc[font16EncLen].enc = NULL; } - ++font16EncLen; } delete fontLoc; @@ -1869,16 +1933,16 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { if (font->isCIDFont()) { if (level == psLevel3 || level == psLevel3Sep) { writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16L3\n", - font->getID()->num, font->getID()->gen, psName, + font->getID()->num, font->getID()->gen, fi->ff->psName, font->getWMode()); } else { writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16\n", - font->getID()->num, font->getID()->gen, psName, + font->getID()->num, font->getID()->gen, fi->ff->psName, font->getWMode()); } } else { writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.6g} {4:.6g}\n", - font->getID()->num, font->getID()->gen, psName, xs, ys); + font->getID()->num, font->getID()->gen, fi->ff->psName, xs, ys); for (i = 0; i < 256; i += 8) { writePS((char *)((i == 0) ? "[ " : " ")); for (j = 0; j < 8; ++j) { @@ -1903,25 +1967,29 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { } writePS("pdfMakeFont\n"); } - - delete psName; } -void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) { +PSFontFileInfo *PSOutputDev::setupEmbeddedType1Font(GfxFont *font, Ref *id) { static char hexChar[17] = "0123456789abcdef"; - Object refObj, strObj, obj1, obj2, obj3; + GString *psName; + PSFontFileInfo *ff; + Object refObj, strObj, obj1, obj2; Dict *dict; - int length1, length2, length3; + int length1, length2; int c; - int start[4]; + int start[6]; GBool binMode; - int i; + int n, i; // check if font is already embedded - if (fontNames->lookupInt(psName)) { - return; + if ((ff = (PSFontFileInfo *) + fontFileInfo->lookup(font->getEmbeddedFontName()))) { + return ff; } - fontNames->add(psName->copy(), 1); + + // generate name + // (this assumes that the PS font name matches the PDF font name) + psName = font->getEmbeddedFontName()->copy(); // get the font stream and info refObj.initRef(id->num, id->gen); @@ -1938,21 +2006,17 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) { } dict->lookup("Length1", &obj1); dict->lookup("Length2", &obj2); - dict->lookup("Length3", &obj3); - if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) { + if (!obj1.isInt() || !obj2.isInt()) { error(errSyntaxError, -1, "Missing length fields in embedded font stream dictionary"); obj1.free(); obj2.free(); - obj3.free(); goto err1; } length1 = obj1.getInt(); length2 = obj2.getInt(); - length3 = obj3.getInt(); obj1.free(); obj2.free(); - obj3.free(); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -1960,91 +2024,164 @@ void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) { embFontList->append(psName->getCString()); embFontList->append("\n"); - // copy ASCII portion of font + // check for PFB format strObj.streamReset(); - for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) { - writePSChar(c); - } + start[0] = strObj.streamGetChar(); + start[1] = strObj.streamGetChar(); + if (start[0] == 0x80 && start[1] == 0x01) { + error(errSyntaxWarning, -1, "Embedded Type 1 font is in PFB format"); + while (1) { + for (i = 2; i < 6; ++i) { + start[i] = strObj.streamGetChar(); + } + if (start[2] == EOF || start[3] == EOF || + start[4] == EOF || start[5] == EOF) { + break; + } + n = start[2] + (start[3] << 8) + (start[4] << 16) + (start[5] << 24); + if (start[1] == 0x01) { + for (i = 0; i < n; ++i) { + if ((c = strObj.streamGetChar()) == EOF) { + break; + } + writePSChar(c); + } + } else { + for (i = 0; i < n; ++i) { + if ((c = strObj.streamGetChar()) == EOF) { + break; + } + writePSChar(hexChar[(c >> 4) & 0x0f]); + writePSChar(hexChar[c & 0x0f]); + if (i % 32 == 31) { + writePSChar('\n'); + } + } + } + start[0] = strObj.streamGetChar(); + start[1] = strObj.streamGetChar(); + if (start[0] == EOF || start[1] == EOF || + (start[0] == 0x80 && start[1] == 0x03)) { + break; + } else if (!(start[0] == 0x80 && + (start[1] == 0x01 || start[1] == 0x02))) { + error(errSyntaxError, -1, + "Invalid PFB header in embedded font stream"); + break; + } + } + writePSChar('\n'); - // figure out if encrypted portion is binary or ASCII - binMode = gFalse; - for (i = 0; i < 4; ++i) { - start[i] = strObj.streamGetChar(); - if (start[i] == EOF) { - error(errSyntaxError, -1, - "Unexpected end of file in embedded font stream"); - goto err1; + // plain text (PFA) format + } else { + + // copy ASCII portion of font + writePSChar(start[0]); + writePSChar(start[1]); + for (i = 2; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) { + writePSChar(c); } - if (!((start[i] >= '0' && start[i] <= '9') || - (start[i] >= 'A' && start[i] <= 'F') || - (start[i] >= 'a' && start[i] <= 'f'))) - binMode = gTrue; - } - // convert binary data to ASCII - if (binMode) { + // figure out if encrypted portion is binary or ASCII + binMode = gFalse; for (i = 0; i < 4; ++i) { - writePSChar(hexChar[(start[i] >> 4) & 0x0f]); - writePSChar(hexChar[start[i] & 0x0f]); + start[i] = strObj.streamGetChar(); + if (start[i] == EOF) { + error(errSyntaxError, -1, + "Unexpected end of file in embedded font stream"); + goto err1; + } + if (!((start[i] >= '0' && start[i] <= '9') || + (start[i] >= 'A' && start[i] <= 'F') || + (start[i] >= 'a' && start[i] <= 'f'))) + binMode = gTrue; } + + // convert binary data to ASCII + if (binMode) { + for (i = 0; i < 4; ++i) { + writePSChar(hexChar[(start[i] >> 4) & 0x0f]); + writePSChar(hexChar[start[i] & 0x0f]); + } #if 0 // this causes trouble for various PostScript printers - // if Length2 is incorrect (too small), font data gets chopped, so - // we take a few extra characters from the trailer just in case - length2 += length3 >= 8 ? 8 : length3; + // if Length2 is incorrect (too small), font data gets chopped, so + // we take a few extra characters from the trailer just in case + length2 += length3 >= 8 ? 8 : length3; #endif - while (i < length2) { - if ((c = strObj.streamGetChar()) == EOF) { - break; + while (i < length2) { + if ((c = strObj.streamGetChar()) == EOF) { + break; + } + writePSChar(hexChar[(c >> 4) & 0x0f]); + writePSChar(hexChar[c & 0x0f]); + if (++i % 32 == 0) { + writePSChar('\n'); + } } - writePSChar(hexChar[(c >> 4) & 0x0f]); - writePSChar(hexChar[c & 0x0f]); - if (++i % 32 == 0) { + if (i % 32 > 0) { writePSChar('\n'); } - } - if (i % 32 > 0) { - writePSChar('\n'); - } - // already in ASCII format -- just copy it - } else { - for (i = 0; i < 4; ++i) { - writePSChar(start[i]); - } - for (i = 4; i < length2; ++i) { - if ((c = strObj.streamGetChar()) == EOF) { - break; + // already in ASCII format -- just copy it + } else { + for (i = 0; i < 4; ++i) { + writePSChar(start[i]); + } + for (i = 4; i < length2; ++i) { + if ((c = strObj.streamGetChar()) == EOF) { + break; + } + writePSChar(c); } - writePSChar(c); } - } - // write padding and "cleartomark" - for (i = 0; i < 8; ++i) { - writePS("00000000000000000000000000000000" - "00000000000000000000000000000000\n"); + // write padding and "cleartomark" + for (i = 0; i < 8; ++i) { + writePS("00000000000000000000000000000000" + "00000000000000000000000000000000\n"); + } + writePS("cleartomark\n"); } - writePS("cleartomark\n"); // ending comment writePS("%%EndResource\n"); + strObj.streamClose(); + strObj.free(); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; + err1: strObj.streamClose(); strObj.free(); + delete psName; + return NULL; } -//~ This doesn't handle .pfb files or binary eexec data (which only -//~ happens in pfb files?). -void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) { +PSFontFileInfo *PSOutputDev::setupExternalType1Font(GfxFont *font, + GString *fileName) { + static char hexChar[17] = "0123456789abcdef"; + GString *psName; + PSFontFileInfo *ff; FILE *fontFile; - int c; + int buf[6]; + int c, n, i; - // check if font is already embedded - if (fontNames->lookupInt(psName)) { - return; + if (font->getName()) { + // check if font is already embedded + if ((ff = (PSFontFileInfo *)fontFileInfo->lookup(font->getName()))) { + return ff; + } + // this assumes that the PS font name matches the PDF font name + psName = font->getName()->copy(); + } else { + // generate name + //~ this won't work -- the PS font name won't match + psName = makePSFontName(font, font->getID()); } - fontNames->add(psName->copy(), 1); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2052,44 +2189,98 @@ void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) { embFontList->append(psName->getCString()); embFontList->append("\n"); - // copy the font file + // open the font file if (!(fontFile = fopen(fileName->getCString(), "rb"))) { error(errIO, -1, "Couldn't open external font file"); - return; + return NULL; } - while ((c = fgetc(fontFile)) != EOF) { - writePSChar(c); + + // check for PFB format + buf[0] = fgetc(fontFile); + buf[1] = fgetc(fontFile); + if (buf[0] == 0x80 && buf[1] == 0x01) { + while (1) { + for (i = 2; i < 6; ++i) { + buf[i] = fgetc(fontFile); + } + if (buf[2] == EOF || buf[3] == EOF || buf[4] == EOF || buf[5] == EOF) { + break; + } + n = buf[2] + (buf[3] << 8) + (buf[4] << 16) + (buf[5] << 24); + if (buf[1] == 0x01) { + for (i = 0; i < n; ++i) { + if ((c = fgetc(fontFile)) == EOF) { + break; + } + writePSChar(c); + } + } else { + for (i = 0; i < n; ++i) { + if ((c = fgetc(fontFile)) == EOF) { + break; + } + writePSChar(hexChar[(c >> 4) & 0x0f]); + writePSChar(hexChar[c & 0x0f]); + if (i % 32 == 31) { + writePSChar('\n'); + } + } + } + buf[0] = fgetc(fontFile); + buf[1] = fgetc(fontFile); + if (buf[0] == EOF || buf[1] == EOF || + (buf[0] == 0x80 && buf[1] == 0x03)) { + break; + } else if (!(buf[0] == 0x80 && + (buf[1] == 0x01 || buf[1] == 0x02))) { + error(errSyntaxError, -1, + "Invalid PFB header in external font file"); + break; + } + } + writePSChar('\n'); + + // plain text (PFA) format + } else { + writePSChar(buf[0]); + writePSChar(buf[1]); + while ((c = fgetc(fontFile)) != EOF) { + writePSChar(c); + } } + fclose(fontFile); // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id, - GString *psName) { +PSFontFileInfo *PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id) { + GString *psName; + PSFontFileInfo *ff; char *fontBuf; int fontLen; FoFiType1C *ffT1C; - int i; + GHashIter *iter; // check if font is already embedded - for (i = 0; i < t1FontNameLen; ++i) { - if (t1FontNames[i].fontFileID.num == id->num && - t1FontNames[i].fontFileID.gen == id->gen) { - psName->clear(); - psName->insert(0, t1FontNames[i].psName); - return; + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; } } - if (t1FontNameLen == t1FontNameSize) { - t1FontNameSize *= 2; - t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, - sizeof(PST1FontName)); - } - t1FontNames[t1FontNameLen].fontFileID = *id; - t1FontNames[t1FontNameLen].psName = psName->copy(); - ++t1FontNameLen; + + // generate name + psName = makePSFontName(font, id); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2109,32 +2300,35 @@ void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id, // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, - GString *psName) { +PSFontFileInfo *PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, + Ref *id) { + GString *psName; + PSFontFileInfo *ff; char *fontBuf; int fontLen; FoFiTrueType *ffTT; - int i; + GHashIter *iter; // check if font is already embedded - for (i = 0; i < t1FontNameLen; ++i) { - if (t1FontNames[i].fontFileID.num == id->num && - t1FontNames[i].fontFileID.gen == id->gen) { - psName->clear(); - psName->insert(0, t1FontNames[i].psName); - return; + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; } } - if (t1FontNameLen == t1FontNameSize) { - t1FontNameSize *= 2; - t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, - sizeof(PST1FontName)); - } - t1FontNames[t1FontNameLen].fontFileID = *id; - t1FontNames[t1FontNameLen].psName = psName->copy(); - ++t1FontNameLen; + + // generate name + psName = makePSFontName(font, id); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2144,7 +2338,7 @@ void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, // convert it to a Type 1 font if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) { - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen, 0))) { if (ffTT->isOpenTypeCFF()) { ffTT->convertToType1(psName->getCString(), NULL, gTrue, outputFunc, outputStream); @@ -2156,14 +2350,50 @@ void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, - GString *psName) { +PSFontFileInfo *PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id) { + GString *psName; + PSFontFileInfo *ff; char *fontBuf; int fontLen; FoFiTrueType *ffTT; int *codeToGID; + GHashIter *iter; + + // get the code-to-GID mapping + if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) { + return NULL; + } + if (!(ffTT = FoFiTrueType::make(fontBuf, fontLen, 0))) { + gfree(fontBuf); + return NULL; + } + codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen && + ff->codeToGIDLen == 256 && + !memcmp(ff->codeToGID, codeToGID, 256 * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + gfree(fontBuf); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2172,38 +2402,57 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, embFontList->append("\n"); // convert it to a Type 42 font - if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) { - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { - codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); - ffTT->convertToType42(psName->getCString(), - ((Gfx8BitFont *)font)->getHasEncoding() - ? ((Gfx8BitFont *)font)->getEncoding() - : (char **)NULL, - codeToGID, outputFunc, outputStream); - if (codeToGID) { - if (font8InfoLen >= font8InfoSize) { - font8InfoSize += 16; - font8Info = (PSFont8Info *)greallocn(font8Info, - font8InfoSize, - sizeof(PSFont8Info)); - } - font8Info[font8InfoLen].fontID = *font->getID(); - font8Info[font8InfoLen].codeToGID = codeToGID; - ++font8InfoLen; - } - delete ffTT; - } - gfree(fontBuf); - } + ffTT->convertToType42(psName->getCString(), + ((Gfx8BitFont *)font)->getHasEncoding() + ? ((Gfx8BitFont *)font)->getEncoding() + : (char **)NULL, + codeToGID, outputFunc, outputStream); + delete ffTT; + gfree(fontBuf); // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + ff->codeToGID = codeToGID; + ff->codeToGIDLen = 256; + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *fileName, - GString *psName) { +PSFontFileInfo *PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, + GString *fileName, + int fontNum) { + GString *psName; + PSFontFileInfo *ff; FoFiTrueType *ffTT; int *codeToGID; + GHashIter *iter; + + // get the code-to-GID mapping + if (!(ffTT = FoFiTrueType::load(fileName->getCString(), fontNum))) { + return NULL; + } + codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileExternal && + ff->type == font->getType() && + !ff->extFileName->cmp(fileName) && + ff->codeToGIDLen == 256 && + !memcmp(ff->codeToGID, codeToGID, 256 * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + return ff; + } + } + + // generate name + psName = makePSFontName(font, font->getID()); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2212,55 +2461,45 @@ void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *fileName, embFontList->append("\n"); // convert it to a Type 42 font - if ((ffTT = FoFiTrueType::load(fileName->getCString()))) { - codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); - ffTT->convertToType42(psName->getCString(), - ((Gfx8BitFont *)font)->getHasEncoding() - ? ((Gfx8BitFont *)font)->getEncoding() - : (char **)NULL, - codeToGID, outputFunc, outputStream); - if (codeToGID) { - if (font8InfoLen >= font8InfoSize) { - font8InfoSize += 16; - font8Info = (PSFont8Info *)greallocn(font8Info, - font8InfoSize, - sizeof(PSFont8Info)); - } - font8Info[font8InfoLen].fontID = *font->getID(); - font8Info[font8InfoLen].codeToGID = codeToGID; - ++font8InfoLen; - } - delete ffTT; - } + ffTT->convertToType42(psName->getCString(), + ((Gfx8BitFont *)font)->getHasEncoding() + ? ((Gfx8BitFont *)font)->getEncoding() + : (char **)NULL, + codeToGID, outputFunc, outputStream); + delete ffTT; // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + ff->codeToGID = codeToGID; + ff->codeToGIDLen = 256; + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, - GString *psName) { +PSFontFileInfo *PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id) { + GString *psName; + PSFontFileInfo *ff; char *fontBuf; int fontLen; FoFiType1C *ffT1C; - int i; + GHashIter *iter; // check if font is already embedded - for (i = 0; i < t1FontNameLen; ++i) { - if (t1FontNames[i].fontFileID.num == id->num && - t1FontNames[i].fontFileID.gen == id->gen) { - psName->clear(); - psName->insert(0, t1FontNames[i].psName); - return; + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; } } - if (t1FontNameLen == t1FontNameSize) { - t1FontNameSize *= 2; - t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, - sizeof(PST1FontName)); - } - t1FontNames[t1FontNameLen].fontFileID = *id; - t1FontNames[t1FontNameLen].psName = psName->copy(); - ++t1FontNameLen; + + // generate name + psName = makePSFontName(font, id); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2287,14 +2526,46 @@ void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, - GString *psName, - GBool needVerticalMetrics) { +PSFontFileInfo *PSOutputDev::setupEmbeddedCIDTrueTypeFont( + GfxFont *font, Ref *id, + GBool needVerticalMetrics) { + GString *psName; + PSFontFileInfo *ff; char *fontBuf; int fontLen; FoFiTrueType *ffTT; + int *codeToGID; + int codeToGIDLen; + GHashIter *iter; + + // get the code-to-GID mapping + codeToGID = ((GfxCIDFont *)font)->getCIDToGID(); + codeToGIDLen = ((GfxCIDFont *)font)->getCIDToGIDLen(); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen && + ff->codeToGIDLen == codeToGIDLen && + ((!ff->codeToGID && !codeToGID) || + (ff->codeToGID && codeToGID && + !memcmp(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int))))) { + fontFileInfo->killIter(&iter); + return ff; + } + } + + // generate name + psName = makePSFontName(font, id); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2304,19 +2575,17 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, // convert it to a Type 0 font if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) { - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen, 0))) { if (globalParams->getPSLevel() >= psLevel3) { // Level 3: use a CID font ffTT->convertToCIDType2(psName->getCString(), - ((GfxCIDFont *)font)->getCIDToGID(), - ((GfxCIDFont *)font)->getCIDToGIDLen(), + codeToGID, codeToGIDLen, needVerticalMetrics, outputFunc, outputStream); } else { // otherwise: use a non-CID composite font ffTT->convertToType0(psName->getCString(), - ((GfxCIDFont *)font)->getCIDToGID(), - ((GfxCIDFont *)font)->getCIDToGIDLen(), + codeToGID, codeToGIDLen, needVerticalMetrics, outputFunc, outputStream); } @@ -2327,18 +2596,104 @@ void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + if (codeToGIDLen) { + ff->codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); + memcpy(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int)); + ff->codeToGIDLen = codeToGIDLen; + } + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, - GString *fileName, - GString *psName, - GBool needVerticalMetrics) { +PSFontFileInfo *PSOutputDev::setupExternalCIDTrueTypeFont( + GfxFont *font, + GString *fileName, + int fontNum, + GBool needVerticalMetrics) { + GString *psName; + PSFontFileInfo *ff; FoFiTrueType *ffTT; int *codeToGID; int codeToGIDLen; CharCodeToUnicode *ctu; Unicode uBuf[8]; int cmap, code; + GHashIter *iter; + + // create a code-to-GID mapping, via Unicode + if (!(ffTT = FoFiTrueType::load(fileName->getCString(), fontNum))) { + return NULL; + } + if (!(ctu = ((GfxCIDFont *)font)->getToUnicode())) { + error(errSyntaxError, -1, + "Couldn't find a mapping to Unicode for font '{0:s}'", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + delete ffTT; + return NULL; + } + // look for a Unicode cmap + for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) { + if ((ffTT->getCmapPlatform(cmap) == 3 && + ffTT->getCmapEncoding(cmap) == 1) || + ffTT->getCmapPlatform(cmap) == 0) { + break; + } + } + if (cmap >= ffTT->getNumCmaps()) { + error(errSyntaxError, -1, + "Couldn't find a Unicode cmap in font '{0:s}'", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + ctu->decRefCnt(); + delete ffTT; + return NULL; + } + // map CID -> Unicode -> GID + if (ctu->isIdentity()) { + codeToGIDLen = 65536; + } else { + codeToGIDLen = ctu->getLength(); + } + codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); + for (code = 0; code < codeToGIDLen; ++code) { + if (ctu->mapToUnicode(code, uBuf, 8) > 0) { + codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]); + } else { + codeToGID[code] = 0; + } + } + ctu->decRefCnt(); + + // check if font is already embedded + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileExternal && + ff->type == font->getType() && + !ff->extFileName->cmp(fileName) && + ff->codeToGIDLen == codeToGIDLen && + ff->codeToGID && + !memcmp(ff->codeToGID, codeToGID, codeToGIDLen * sizeof(int))) { + fontFileInfo->killIter(&iter); + gfree(codeToGID); + delete ffTT; + return ff; + } + } + + // check for embedding permission + if (ffTT->getEmbeddingRights() < 1) { + error(errSyntaxError, -1, + "TrueType font '{0:s}' does not allow embedding", + font->getName() ? font->getName()->getCString() : "(unnamed)"); + gfree(codeToGID); + delete ffTT; + return NULL; + } + + // generate name + psName = makePSFontName(font, font->getID()); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2348,90 +2703,55 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, // convert it to a Type 0 font //~ this should use fontNum to load the correct font - if ((ffTT = FoFiTrueType::load(fileName->getCString()))) { - - // check for embedding permission - if (ffTT->getEmbeddingRights() >= 1) { - - // create a CID-to-GID mapping, via Unicode - if ((ctu = ((GfxCIDFont *)font)->getToUnicode())) { - // look for a Unicode cmap - for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) { - if ((ffTT->getCmapPlatform(cmap) == 3 && - ffTT->getCmapEncoding(cmap) == 1) || - ffTT->getCmapPlatform(cmap) == 0) { - break; - } - } - if (cmap < ffTT->getNumCmaps()) { - // map CID -> Unicode -> GID - codeToGIDLen = ctu->getLength(); - codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); - for (code = 0; code < codeToGIDLen; ++code) { - if (ctu->mapToUnicode(code, uBuf, 8) > 0) { - codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]); - } else { - codeToGID[code] = 0; - } - } - if (globalParams->getPSLevel() >= psLevel3) { - // Level 3: use a CID font - ffTT->convertToCIDType2(psName->getCString(), - codeToGID, codeToGIDLen, - needVerticalMetrics, - outputFunc, outputStream); - } else { - // otherwise: use a non-CID composite font - ffTT->convertToType0(psName->getCString(), - codeToGID, codeToGIDLen, - needVerticalMetrics, - outputFunc, outputStream); - } - gfree(codeToGID); - } - ctu->decRefCnt(); - } else { - error(errSyntaxError, -1, - "Couldn't find a mapping to Unicode for font '{0:s}'", - font->getName() ? font->getName()->getCString() : "(unnamed)"); - } - } else { - error(errSyntaxError, -1, - "TrueType font '%s' does not allow embedding", - font->getName() ? font->getName()->getCString() : "(unnamed)"); - - } - delete ffTT; + if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffTT->convertToCIDType2(psName->getCString(), + codeToGID, codeToGIDLen, + needVerticalMetrics, + outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffTT->convertToType0(psName->getCString(), + codeToGID, codeToGIDLen, + needVerticalMetrics, + outputFunc, outputStream); } + delete ffTT; // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + ff->codeToGID = codeToGID; + ff->codeToGIDLen = codeToGIDLen; + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, - GString *psName) { +PSFontFileInfo *PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, + Ref *id) { + GString *psName; + PSFontFileInfo *ff; char *fontBuf; int fontLen; FoFiTrueType *ffTT; - int i; + GHashIter *iter; + int n; // check if font is already embedded - for (i = 0; i < t1FontNameLen; ++i) { - if (t1FontNames[i].fontFileID.num == id->num && - t1FontNames[i].fontFileID.gen == id->gen) { - psName->clear(); - psName->insert(0, t1FontNames[i].psName); - return; + fontFileInfo->startIter(&iter); + while (fontFileInfo->getNext(&iter, &psName, (void **)&ff)) { + if (ff->loc == psFontFileEmbedded && + ff->embFontID.num == id->num && + ff->embFontID.gen == id->gen) { + fontFileInfo->killIter(&iter); + return ff; } } - if (t1FontNameLen == t1FontNameSize) { - t1FontNameSize *= 2; - t1FontNames = (PST1FontName *)greallocn(t1FontNames, t1FontNameSize, - sizeof(PST1FontName)); - } - t1FontNames[t1FontNameLen].fontFileID = *id; - t1FontNames[t1FontNameLen].psName = psName->copy(); - ++t1FontNameLen; + + // generate name + psName = makePSFontName(font, id); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2441,7 +2761,7 @@ void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, // convert it to a Type 0 font if ((fontBuf = font->readEmbFontFile(xref, &fontLen))) { - if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen, 0))) { if (ffTT->isOpenTypeCFF()) { if (globalParams->getPSLevel() >= psLevel3) { // Level 3: use a CID font @@ -2464,10 +2784,22 @@ void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + ff->embFontID = *id; + if ((n = ((GfxCIDFont *)font)->getCIDToGIDLen())) { + ff->codeToGID = (int *)gmallocn(n, sizeof(int)); + memcpy(ff->codeToGID, ((GfxCIDFont *)font)->getCIDToGID(), n * sizeof(int)); + ff->codeToGIDLen = n; + } + fontFileInfo->add(ff->psName, ff); + return ff; } -void PSOutputDev::setupType3Font(GfxFont *font, GString *psName, - Dict *parentResDict) { +PSFontFileInfo *PSOutputDev::setupType3Font(GfxFont *font, + Dict *parentResDict) { + PSFontFileInfo *ff; + GString *psName; Dict *resDict; Dict *charProcs; Object charProc; @@ -2477,6 +2809,10 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName, GString *buf; int i; + // generate name + psName = GString::format("T3_{0:d}_{1:d}", + font->getID()->num, font->getID()->gen); + // set up resources used by font if ((resDict = ((Gfx8BitFont *)font)->getResources())) { inType3Char = gTrue; @@ -2528,7 +2864,7 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName, writePS("/"); writePSName(charProcs->getKey(i)); writePS(" {\n"); - gfx->display(charProcs->getVal(i, &charProc)); + gfx->display(charProcs->getValNF(i, &charProc)); charProc.free(); if (t3String) { if (t3Cacheable) { @@ -2558,6 +2894,10 @@ void PSOutputDev::setupType3Font(GfxFont *font, GString *psName, // ending comment writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileEmbedded); + fontFileInfo->add(ff->psName, ff); + return ff; } // Make a unique PS font name, based on the names given in the PDF @@ -2567,16 +2907,14 @@ GString *PSOutputDev::makePSFontName(GfxFont *font, Ref *id) { if ((s = font->getEmbeddedFontName())) { psName = filterPSName(s); - if (!fontNames->lookupInt(psName)) { - fontNames->add(psName->copy(), 1); + if (!fontFileInfo->lookup(psName)) { return psName; } delete psName; } if ((s = font->getName())) { psName = filterPSName(s); - if (!fontNames->lookupInt(psName)) { - fontNames->add(psName->copy(), 1); + if (!fontFileInfo->lookup(psName)) { return psName; } delete psName; @@ -2591,7 +2929,6 @@ GString *PSOutputDev::makePSFontName(GfxFont *font, Ref *id) { psName->append('_')->append(s); delete s; } - fontNames->add(psName->copy(), 1); return psName; } @@ -2651,7 +2988,7 @@ void PSOutputDev::setupImages(Dict *resDict) { } void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) { - GBool useRLE, useCompressed, useASCIIHex; + GBool useLZW, useRLE, useCompressed, useASCIIHex; GString *s; int c; int size, line, col, i; @@ -2660,21 +2997,27 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) { //~ this does not correctly handle the DeviceN color space //~ -- need to use DeviceNRecoder if (level < psLevel2) { - useRLE = gFalse; + useLZW = useRLE = gFalse; useCompressed = gFalse; useASCIIHex = gTrue; } else { if (globalParams->getPSUncompressPreloadedImages()) { - useRLE = gFalse; + useLZW = useRLE = gFalse; useCompressed = gFalse; } else { s = str->getPSFilter(level < psLevel3 ? 2 : 3, ""); if (s) { - useRLE = gFalse; + useLZW = useRLE = gFalse; useCompressed = gTrue; delete s; } else { - useRLE = gTrue; + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } useCompressed = gFalse; } } @@ -2683,7 +3026,9 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) { if (useCompressed) { str = str->getUndecodedStream(); } - if (useRLE) { + if (useLZW) { + str = new LZWEncoder(str); + } else if (useRLE) { str = new RunLengthEncoder(str); } if (useASCIIHex) { @@ -2722,9 +3067,9 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) { } } while (c != (useASCIIHex ? '>' : '~') && c != EOF); // add one entry for the final line of data; add another entry - // because the RunLengthDecode filter may read past the end + // because the LZWDecode/RunLengthDecode filter may read past the end ++size; - if (useRLE) { + if (useLZW || useRLE) { ++size; } writePSFmt("{0:d} array dup /{1:s}Data_{2:d}_{3:d} exch def\n", @@ -2771,7 +3116,7 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask) { } } while (c != (useASCIIHex ? '>' : '~') && c != EOF); writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); - if (useRLE) { + if (useLZW || useRLE) { ++line; writePSFmt("{0:d} <> put\n", line); } else { @@ -2799,7 +3144,7 @@ void PSOutputDev::setupForms(Dict *resDict) { xObj.streamGetDict()->lookup("Subtype", &subtypeObj); if (subtypeObj.isName("Form")) { if (xObjRef.isRef()) { - setupForm(xObjRef.getRef(), &xObj); + setupForm(&xObjRef, &xObj); } else { error(errSyntaxError, -1, "Form in resource dict is not an indirect reference"); @@ -2814,7 +3159,7 @@ void PSOutputDev::setupForms(Dict *resDict) { xObjDict.free(); } -void PSOutputDev::setupForm(Ref id, Object *strObj) { +void PSOutputDev::setupForm(Object *strRef, Object *strObj) { Dict *dict, *resDict; Object matrixObj, bboxObj, resObj, obj1; double m[6], bbox[4]; @@ -2824,7 +3169,8 @@ void PSOutputDev::setupForm(Ref id, Object *strObj) { // check if form is already defined for (i = 0; i < formIDLen; ++i) { - if (formIDs[i].num == id.num && formIDs[i].gen == id.gen) { + if (formIDs[i].num == strRef->getRefNum() && + formIDs[i].gen == strRef->getRefGen()) { return; } } @@ -2838,7 +3184,7 @@ void PSOutputDev::setupForm(Ref id, Object *strObj) { } formIDs = (Ref *)greallocn(formIDs, formIDSize, sizeof(Ref)); } - formIDs[formIDLen++] = id; + formIDs[formIDLen++] = strRef->getRef(); dict = strObj->streamGetDict(); @@ -2875,7 +3221,7 @@ void PSOutputDev::setupForm(Ref id, Object *strObj) { dict->lookup("Resources", &resObj); resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; - writePSFmt("/f_{0:d}_{1:d} {{\n", id.num, id.gen); + writePSFmt("/f_{0:d}_{1:d} {{\n", strRef->getRefNum(), strRef->getRefGen()); writePS("q\n"); writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", m[0], m[1], m[2], m[3], m[4], m[5]); @@ -2885,7 +3231,7 @@ void PSOutputDev::setupForm(Ref id, Object *strObj) { box.x2 = bbox[2]; box.y2 = bbox[3]; gfx = new Gfx(doc, this, resDict, &box, &box); - gfx->display(strObj); + gfx->display(strRef); delete gfx; writePS("Q\n"); @@ -2905,6 +3251,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, GBool rasterize; #if HAVE_SPLASH GBool mono; + GBool useLZW; double dpi; SplashOutputDev *splashOut; SplashColor paperColor; @@ -2915,10 +3262,11 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, Object obj; Guchar *p; Guchar col[4]; + char buf[4096]; double hDPI2, vDPI2; double m0, m1, m2, m3, m4, m5; int nStripes, stripeH, stripeY; - int c, w, h, x, y, comp, i; + int w, h, x, y, comp, i, n; #endif if (globalParams->getPSAlwaysRasterize()) { @@ -2939,6 +3287,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, // get the rasterization parameters dpi = globalParams->getPSRasterResolution(); mono = globalParams->getPSRasterMono(); + useLZW = globalParams->getPSLZW(); // start the PS page page->makeBox(dpi, dpi, rotateA, useMediaBox, gFalse, @@ -2987,8 +3336,8 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, sliceW = (int)((box.x2 - box.x1) * hDPI2 / 72.0); sliceH = (int)((box.y2 - box.y1) * vDPI2 / 72.0); } - nStripes = (int)ceil((double)(sliceW * sliceH) / - (double)rasterizationSliceSize); + nStripes = (int)ceil(((double)sliceW * (double)sliceH) / + (double)globalParams->getPSRasterSliceSize()); stripeH = (sliceH + nStripes - 1) / nStripes; // render the stripes @@ -3094,21 +3443,29 @@ GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, } else { writePS(" /ASCII85Decode filter\n"); } - writePS(" /RunLengthDecode filter\n"); + if (useLZW) { + writePS(" /LZWDecode filter\n"); + } else { + writePS(" /RunLengthDecode filter\n"); + } writePS(">>\n"); writePS("image\n"); obj.initNull(); p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize(); str0 = new MemStream((char *)p, 0, w * h * (mono ? 1 : 3), &obj); - str = new RunLengthEncoder(str0); + if (useLZW) { + str = new LZWEncoder(str0); + } else { + str = new RunLengthEncoder(str0); + } if (globalParams->getPSASCIIHex()) { str = new ASCIIHexEncoder(str); } else { str = new ASCII85Encoder(str); } str->reset(); - while ((c = str->getChar()) != EOF) { - writePSChar(c); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); } str->close(); delete str; @@ -3148,8 +3505,13 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) { if (paperMatch) { page = doc->getCatalog()->getPage(pageNum); imgLLX = imgLLY = 0; - imgURX = (int)ceil(page->getMediaWidth()); - imgURY = (int)ceil(page->getMediaHeight()); + if (globalParams->getPSUseCropBoxAsPage()) { + imgURX = (int)ceil(page->getCropWidth()); + imgURY = (int)ceil(page->getCropHeight()); + } else { + imgURX = (int)ceil(page->getMediaWidth()); + imgURY = (int)ceil(page->getMediaHeight()); + } if (state->getRotate() == 90 || state->getRotate() == 270) { t = imgURX; imgURX = imgURY; @@ -3160,6 +3522,9 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) { } writePS("%%BeginPageSetup\n"); } + if (mode != psModeForm) { + writePS("xpdf begin\n"); + } // underlays if (underlayCbk) { @@ -3356,6 +3721,7 @@ void PSOutputDev::endPage() { } writePS("%%PageTrailer\n"); writePageTrailer(); + writePS("end\n"); } } @@ -3371,8 +3737,13 @@ void PSOutputDev::restoreState(GfxState *state) { void PSOutputDev::updateCTM(GfxState *state, double m11, double m12, double m21, double m22, double m31, double m32) { - writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", - m11, m12, m21, m22, m31, m32); + if (fabs(m11 * m22 - m12 * m21) < 0.00001) { + // avoid a singular (or close-to-singular) matrix + writePSFmt("[0.00001 0 0 0.00001 {0:.6g} {1:.6g}] Tm\n", m31, m32); + } else { + writePSFmt("[{0:.6g} {1:.6g} {2:.6g} {3:.6g} {4:.6g} {5:.6g}] cm\n", + m11, m12, m21, m22, m31, m32); + } } void PSOutputDev::updateLineDash(GfxState *state) { @@ -3737,7 +4108,7 @@ void PSOutputDev::eoFill(GfxState *state) { writePS("f*\n"); } -void PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, +void PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -3770,6 +4141,7 @@ void PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, box.x2 = bbox[2]; box.y2 = bbox[3]; gfx2 = new Gfx(doc, this, resDict, &box, NULL); + gfx2->takeContentStreamStack(gfx); writePS("/x {\n"); if (paintType == 2) { writePSFmt("{0:.6g} 0 {1:.6g} {2:.6g} {3:.6g} {4:.6g} setcachedevice\n", @@ -3785,7 +4157,7 @@ void PSOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, } inType3Char = gTrue; ++numTilingPatterns; - gfx2->display(str); + gfx2->display(strRef); --numTilingPatterns; inType3Char = gFalse; writePS("} def\n"); @@ -3944,7 +4316,7 @@ GBool PSOutputDev::radialShadedFill(GfxState *state, double xMin, yMin, xMax, yMax; double x0, y0, r0, x1, y1, r1, t0, t1; double xa, ya, ra; - double sz, sMin, sMax, h, ta; + double sMin, sMax, h, ta; double sLeft, sRight, sTop, sBottom, sZero, sDiag; GBool haveSLeft, haveSRight, haveSTop, haveSBottom, haveSZero; GBool haveSMin, haveSMax; @@ -3970,18 +4342,14 @@ GBool PSOutputDev::radialShadedFill(GfxState *state, if (h == 0) { enclosed = gTrue; theta = 0; // make gcc happy - sz = 0; // make gcc happy } else if (r1 - r0 == 0) { enclosed = gFalse; theta = 0; - sz = 0; // make gcc happy } else if (fabs(r1 - r0) >= h) { enclosed = gTrue; theta = 0; // make gcc happy - sz = 0; // make gcc happy } else { enclosed = gFalse; - sz = -r0 / (r1 - r0); theta = asin((r1 - r0) / h); } if (enclosed) { @@ -4267,8 +4635,9 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { int wMode; int *codeToGID; GString *s2; - double dx, dy, originX, originY; + double dx, dy, originX, originY, originX0, originY0, tOriginX0, tOriginY0; char *p; + PSFontInfo *fi; UnicodeMap *uMap; CharCode code; Unicode u[8]; @@ -4292,30 +4661,32 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { } wMode = font->getWMode(); + fi = NULL; + for (i = 0; i < fontInfo->getLength(); ++i) { + fi = (PSFontInfo *)fontInfo->get(i); + if (fi->fontID.num == font->getID()->num && + fi->fontID.gen == font->getID()->gen) { + break; + } + fi = NULL; + } + // check for a subtitute 16-bit font uMap = NULL; codeToGID = NULL; if (font->isCIDFont()) { - for (i = 0; i < font16EncLen; ++i) { - if (font->getID()->num == font16Enc[i].fontID.num && - font->getID()->gen == font16Enc[i].fontID.gen) { - if (!font16Enc[i].enc) { - // font substitution failed, so don't output any text - return; - } - uMap = globalParams->getUnicodeMap(font16Enc[i].enc); - break; - } + if (!(fi && fi->ff)) { + // font substitution failed, so don't output any text + return; + } + if (fi->ff->encoding) { + uMap = globalParams->getUnicodeMap(fi->ff->encoding); } - // check for a code-to-GID map + // check for an 8-bit code-to-GID map } else { - for (i = 0; i < font8InfoLen; ++i) { - if (font->getID()->num == font8Info[i].fontID.num && - font->getID()->gen == font8Info[i].fontID.gen) { - codeToGID = font8Info[i].codeToGID; - break; - } + if (fi && fi->ff) { + codeToGID = fi->ff->codeToGID; } } @@ -4326,10 +4697,18 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { s2 = new GString(); dxdySize = font->isCIDFont() ? 8 : s->getLength(); dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double)); + originX0 = originY0 = 0; // make gcc happy while (len > 0) { n = font->getNextChar(p, len, &code, u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, &dx, &dy, &originX, &originY); + //~ this doesn't handle the case where the origin offset changes + //~ within a string of characters -- which could be fixed by + //~ modifying dx,dy as needed for each character + if (p == s->getCString()) { + originX0 = originX; + originY0 = originY; + } dx *= state->getFontSize(); dy *= state->getFontSize(); if (wMode) { @@ -4389,8 +4768,14 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { if (uMap) { uMap->decRefCnt(); } + originX0 *= state->getFontSize(); + originY0 *= state->getFontSize(); + state->textTransformDelta(originX0, originY0, &tOriginX0, &tOriginY0); if (nChars > 0) { + if (wMode) { + writePSFmt("{0:.6g} {1:.6g} rmoveto\n", -tOriginX0, -tOriginY0); + } writePSString(s2); writePS("\n["); for (i = 0; i < 2 * nChars; ++i) { @@ -4400,6 +4785,9 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { writePSFmt("{0:.6g}", dxdy[i]); } writePS("] Tj\n"); + if (wMode) { + writePSFmt("{0:.6g} {1:.6g} rmoveto\n", tOriginX0, tOriginY0); + } } gfree(dxdy); delete s2; @@ -4418,7 +4806,7 @@ void PSOutputDev::endTextObject(GfxState *state) { void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { + GBool inlineImg, GBool interpolate) { int len; len = height * ((width + 7) / 8); @@ -4442,7 +4830,8 @@ void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { + int *maskColors, GBool inlineImg, + GBool interpolate) { int len; len = height * ((width * colorMap->getNumPixelComps() * @@ -4474,7 +4863,7 @@ void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert) { + GBool maskInvert, GBool interpolate) { int len; len = height * ((width * colorMap->getNumPixelComps() * @@ -4684,10 +5073,11 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, GBool emitRect, addRect, extendRect; GString *s; int n, numComps; - GBool useRLE, useASCII, useASCIIHex, useCompressed; + GBool useLZW, useRLE, useASCII, useASCIIHex, useCompressed; GfxSeparationColorSpace *sepCS; GfxColor color; GfxCMYK cmyk; + char buf[4096]; int c; int col, i, j, x0, x1, y, maskXor; @@ -4821,14 +5211,14 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1; ++rectsOutLen; } - writePSFmt("{0:d} array 0\n", rectsOutLen * 4); + writePSFmt("{0:d} {1:d}\n", maskWidth, maskHeight); for (i = 0; i < rectsOutLen; ++i) { - writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n", + writePSFmt("{0:d} {1:d} {2:d} {3:d} pr\n", rectsOut[i].x0, rectsOut[i].y0, rectsOut[i].x1 - rectsOut[i].x0, rectsOut[i].y1 - rectsOut[i].y0); } - writePSFmt("pop {0:d} {1:d} pdfImClip\n", width, height); + writePS("pop pop pdfImClip\n"); gfree(rectsOut); gfree(rects0); gfree(rects1); @@ -4923,14 +5313,14 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1; ++rectsOutLen; } - writePSFmt("{0:d} array 0\n", rectsOutLen * 4); + writePSFmt("{0:d} {1:d}\n", maskWidth, maskHeight); for (i = 0; i < rectsOutLen; ++i) { - writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n", + writePSFmt("{0:d} {1:d} {2:d} {3:d} pr\n", rectsOut[i].x0, rectsOut[i].y0, rectsOut[i].x1 - rectsOut[i].x0, rectsOut[i].y1 - rectsOut[i].y0); } - writePSFmt("pop {0:d} {1:d} pdfImClip\n", maskWidth, maskHeight); + writePS("pop pop pdfImClip\n"); gfree(rectsOut); gfree(rects0); gfree(rects1); @@ -4951,7 +5341,11 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, if (inlineImg) { // create an array str2 = new FixedLengthEncoder(str, len); - str2 = new RunLengthEncoder(str2); + if (globalParams->getPSLZW()) { + str2 = new LZWEncoder(str2); + } else { + str2 = new RunLengthEncoder(str2); + } if (useASCIIHex) { str2 = new ASCIIHexEncoder(str2); } else { @@ -4994,8 +5388,8 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, } } while (c != (useASCIIHex ? '>' : '~') && c != EOF); writePS((char *)(useASCIIHex ? ">\n" : "~>\n")); - // add an extra entry because the RunLengthDecode filter may - // read past the end + // add an extra entry because the LZWDecode/RunLengthDecode + // filter may read past the end writePS("<>]\n"); writePS("0\n"); str2->close(); @@ -5065,7 +5459,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, if ((mode == psModeForm || inType3Char || preload) && globalParams->getPSUncompressPreloadedImages()) { s = NULL; - useRLE = gFalse; + useLZW = useRLE = gFalse; useCompressed = gFalse; useASCII = gFalse; } else { @@ -5073,11 +5467,17 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, " "); if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || inlineImg || !s) { - useRLE = gTrue; + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } useASCII = !(mode == psModeForm || inType3Char || preload); useCompressed = gFalse; } else { - useRLE = gFalse; + useLZW = useRLE = gFalse; useASCII = str->isBinary() && !(mode == psModeForm || inType3Char || preload); useCompressed = gTrue; @@ -5087,7 +5487,9 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, writePSFmt(" /ASCII{0:s}Decode filter\n", useASCIIHex ? "Hex" : "85"); } - if (useRLE) { + if (useLZW) { + writePS(" /LZWDecode filter\n"); + } else if (useRLE) { writePS(" /RunLengthDecode filter\n"); } if (useCompressed) { @@ -5119,8 +5521,10 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, str = new DeviceNRecoder(str, width, height, colorMap); } - // add RunLengthEncode and ASCIIHex/85 encode filters - if (useRLE) { + // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters + if (useLZW) { + str = new LZWEncoder(str); + } else if (useRLE) { str = new RunLengthEncoder(str); } if (useASCII) { @@ -5141,12 +5545,14 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, n = 0; } else { // need to read the stream to count characters -- the length - // is data-dependent (because of ASCII and RLE filters) + // is data-dependent (because of ASCII and LZW/RunLength + // filters) str->reset(); n = 0; - while ((c = str->getChar()) != EOF) { - ++n; - } + do { + i = str->discardChars(4096); + n += i; + } while (i == 4096); str->close(); } // +6/7 for "pdfIm\n" / "pdfImM\n" @@ -5170,8 +5576,8 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, // copy the stream data str->reset(); - while ((c = str->getChar()) != EOF) { - writePSChar(c); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); } str->close(); @@ -5185,7 +5591,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, #endif // delete encoders - if (useRLE || useASCII || inlineImg) { + if (useLZW || useRLE || useASCII || inlineImg) { delete str; } } @@ -5204,18 +5610,20 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, Stream *str2; GString *s; int n, numComps; - GBool useRLE, useASCII, useASCIIHex, useCompressed; - GBool maskUseRLE, maskUseASCII, maskUseCompressed; + GBool useLZW, useRLE, useASCII, useASCIIHex, useCompressed; + GBool maskUseLZW, maskUseRLE, maskUseASCII, maskUseCompressed; GString *maskFilters; GfxSeparationColorSpace *sepCS; GfxColor color; GfxCMYK cmyk; + char buf[4096]; int c; int col, i; useASCIIHex = globalParams->getPSASCIIHex(); - useRLE = useASCII = useCompressed = gFalse; // make gcc happy - maskUseRLE = maskUseASCII = maskUseCompressed = gFalse; // make gcc happy + useLZW = useRLE = useASCII = useCompressed = gFalse; // make gcc happy + maskUseLZW = maskUseRLE = maskUseASCII = gFalse; // make gcc happy + maskUseCompressed = gFalse; // make gcc happy maskFilters = NULL; // make gcc happy // explicit masking @@ -5225,17 +5633,23 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, if ((mode == psModeForm || inType3Char || preload) && globalParams->getPSUncompressPreloadedImages()) { s = NULL; - maskUseRLE = gFalse; + maskUseLZW = maskUseRLE = gFalse; maskUseCompressed = gFalse; maskUseASCII = gFalse; } else { s = maskStr->getPSFilter(3, " "); if (!s) { - maskUseRLE = gTrue; + if (globalParams->getPSLZW()) { + maskUseLZW = gTrue; + maskUseRLE = gFalse; + } else { + maskUseRLE = gTrue; + maskUseLZW = gFalse; + } maskUseASCII = !(mode == psModeForm || inType3Char || preload); maskUseCompressed = gFalse; } else { - maskUseRLE = gFalse; + maskUseLZW = maskUseRLE = gFalse; maskUseASCII = maskStr->isBinary() && !(mode == psModeForm || inType3Char || preload); maskUseCompressed = gTrue; @@ -5246,7 +5660,9 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, maskFilters->appendf(" /ASCII{0:s}Decode filter\n", useASCIIHex ? "Hex" : "85"); } - if (maskUseRLE) { + if (maskUseLZW) { + maskFilters->append(" /LZWDecode filter\n"); + } else if (maskUseRLE) { maskFilters->append(" /RunLengthDecode filter\n"); } if (maskUseCompressed) { @@ -5263,11 +5679,13 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, writePS(maskFilters->getCString()); writePS("pdfMask\n"); - // add RunLengthEncode and ASCIIHex/85 encode filters + // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters if (maskUseCompressed) { maskStr = maskStr->getUndecodedStream(); } - if (maskUseRLE) { + if (maskUseLZW) { + maskStr = new LZWEncoder(maskStr); + } else if (maskUseRLE) { maskStr = new RunLengthEncoder(maskStr); } if (maskUseASCII) { @@ -5280,15 +5698,15 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, // copy the stream data maskStr->reset(); - while ((c = maskStr->getChar()) != EOF) { - writePSChar(c); + while ((n = maskStr->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); } maskStr->close(); writePSChar('\n'); writePS("%-EOD-\n"); // delete encoders - if (maskUseRLE || maskUseASCII) { + if (maskUseLZW || maskUseRLE || maskUseASCII) { delete maskStr; } } @@ -5305,7 +5723,11 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, if (inlineImg) { // create an array str2 = new FixedLengthEncoder(str, len); - str2 = new RunLengthEncoder(str2); + if (globalParams->getPSLZW()) { + str2 = new LZWEncoder(str2); + } else { + str2 = new RunLengthEncoder(str2); + } if (useASCIIHex) { str2 = new ASCIIHexEncoder(str2); } else { @@ -5348,8 +5770,8 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, } } while (c != (useASCIIHex ? '>' : '~') && c != EOF); writePS((char *)(useASCIIHex ? ">\n" : "~>\n")); - // add an extra entry because the RunLengthDecode filter may - // read past the end + // add an extra entry because the LZWDecode/RunLengthDecode + // filter may read past the end writePS("<>]\n"); writePS("0\n"); str2->close(); @@ -5436,7 +5858,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, if ((mode == psModeForm || inType3Char || preload) && globalParams->getPSUncompressPreloadedImages()) { s = NULL; - useRLE = gFalse; + useLZW = useRLE = gFalse; useCompressed = gFalse; useASCII = gFalse; } else { @@ -5444,11 +5866,17 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, " "); if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || inlineImg || !s) { - useRLE = gTrue; + if (globalParams->getPSLZW()) { + useLZW = gTrue; + useRLE = gFalse; + } else { + useRLE = gTrue; + useLZW = gFalse; + } useASCII = !(mode == psModeForm || inType3Char || preload); useCompressed = gFalse; } else { - useRLE = gFalse; + useLZW = useRLE = gFalse; useASCII = str->isBinary() && !(mode == psModeForm || inType3Char || preload); useCompressed = gTrue; @@ -5458,7 +5886,9 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, writePSFmt(" /ASCII{0:s}Decode filter\n", useASCIIHex ? "Hex" : "85"); } - if (useRLE) { + if (useLZW) { + writePS(" /LZWDecode filter\n"); + } else if (useRLE) { writePS(" /RunLengthDecode filter\n"); } if (useCompressed) { @@ -5538,8 +5968,10 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, str = new DeviceNRecoder(str, width, height, colorMap); } - // add RunLengthEncode and ASCIIHex/85 encode filters - if (useRLE) { + // add LZWEncode/RunLengthEncode and ASCIIHex/85 encode filters + if (useLZW) { + str = new LZWEncoder(str); + } else if (useRLE) { str = new RunLengthEncoder(str); } if (useASCII) { @@ -5552,8 +5984,8 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, // copy the stream data str->reset(); - while ((c = str->getChar()) != EOF) { - writePSChar(c); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); } str->close(); @@ -5562,7 +5994,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, writePS("%-EOD-\n"); // delete encoders - if (useRLE || useASCII || inlineImg) { + if (useLZW || useRLE || useASCII || inlineImg) { delete str; } } @@ -6267,6 +6699,10 @@ void PSOutputDev::type3D0(GfxState *state, double wx, double wy) { void PSOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) { + if (t3String) { + error(errSyntaxError, -1, "Multiple 'd1' operators in Type 3 CharProc"); + return; + } t3WX = wx; t3WY = wy; t3LLX = llx; @@ -6286,7 +6722,8 @@ void PSOutputDev::drawForm(Ref id) { void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) { Stream *str; - int c; + char buf[4096]; + int n; if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) { str = level1Stream; @@ -6294,8 +6731,8 @@ void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) { str = psStream; } str->reset(); - while ((c = str->getChar()) != EOF) { - writePSChar(c); + while ((n = str->getBlock(buf, sizeof(buf))) > 0) { + writePSBlock(buf, n); } str->close(); } @@ -6462,6 +6899,14 @@ void PSOutputDev::writePSChar(char c) { } } +void PSOutputDev::writePSBlock(char *s, int len) { + if (t3String) { + t3String->append(s, len); + } else { + (*outputFunc)(outputStream, s, len); + } +} + void PSOutputDev::writePS(const char *s) { if (t3String) { t3String->append(s); @@ -6564,7 +7009,9 @@ GString *PSOutputDev::filterPSName(GString *name) { // Write a DSC-compliant <textline>. void PSOutputDev::writePSTextLine(GString *s) { - int i, j, step; + TextString *ts; + Unicode *u; + int i, j; int c; // - DSC comments must be printable ASCII; control chars and @@ -6574,17 +7021,10 @@ void PSOutputDev::writePSTextLine(GString *s) { // for the keyword, which was emitted by the caller) // - lines that start with a left paren are treated as <text> // instead of <textline>, so we escape a leading paren - if (s->getLength() >= 2 && - (s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - i = 3; - step = 2; - } else { - i = 0; - step = 1; - } - for (j = 0; i < s->getLength() && j < 200; i += step) { - c = s->getChar(i) & 0xff; + ts = new TextString(s); + u = ts->getUnicode(); + for (i = 0, j = 0; i < ts->getLength() && j < 200; ++i) { + c = u[i] & 0xff; if (c == '\\') { writePS("\\\\"); j += 2; @@ -6597,4 +7037,5 @@ void PSOutputDev::writePSTextLine(GString *s) { } } writePS("\n"); + delete ts; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSOutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSOutputDev.h index e528f8c83d1..7118830aceb 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSOutputDev.h @@ -30,11 +30,9 @@ class GfxFont; class GfxColorSpace; class GfxSeparationColorSpace; class PDFRectangle; -struct PST1FontName; -struct PSFont8Info; -struct PSFont16Enc; class PSOutCustomColor; class PSOutputDev; +class PSFontFileInfo; //------------------------------------------------------------------------ // PSOutputDev @@ -92,6 +90,9 @@ public: // Check if file was successfully created. virtual GBool isOk() { return ok; } + // Returns false if there have been any errors on the output stream. + GBool checkIO(); + //---- get info about output device // Does this device use upside-down coordinates? @@ -196,7 +197,7 @@ public: virtual void stroke(GfxState *state); virtual void fill(GfxState *state); virtual void eoFill(GfxState *state); - virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -218,15 +219,15 @@ public: //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); + int *maskColors, GBool inlineImg, GBool interpolate); virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); + GBool maskInvert, GBool interpolate); #if OPI_SUPPORT //----- OPI functions @@ -262,6 +263,7 @@ public: { overlayCbk = cbk; overlayCbkData = data; } void writePSChar(char c); + void writePSBlock(char *s, int len); void writePS(const char *s); void writePSFmt(const char *fmt, ...); void writePSString(GString *s); @@ -277,27 +279,27 @@ private: void setupResources(Dict *resDict); void setupFonts(Dict *resDict); void setupFont(GfxFont *font, Dict *parentResDict); - void setupEmbeddedType1Font(Ref *id, GString *psName); - void setupExternalType1Font(GString *fileName, GString *psName); - void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GString *psName); - void setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, GString *psName); - void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GString *psName); - void setupExternalTrueTypeFont(GfxFont *font, GString *fileName, - GString *psName); - void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GString *psName); - void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GString *psName, - GBool needVerticalMetrics); - void setupExternalCIDTrueTypeFont(GfxFont *font, - GString *fileName, - GString *psName, - GBool needVerticalMetrics); - void setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, GString *psName); - void setupType3Font(GfxFont *font, GString *psName, Dict *parentResDict); + PSFontFileInfo *setupEmbeddedType1Font(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalType1Font(GfxFont *font, GString *fileName); + PSFontFileInfo *setupEmbeddedType1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalTrueTypeFont(GfxFont *font, GString *fileName, + int fontNum); + PSFontFileInfo *setupEmbeddedCIDType0Font(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, + GBool needVerticalMetrics); + PSFontFileInfo *setupExternalCIDTrueTypeFont(GfxFont *font, + GString *fileName, + int fontNum, + GBool needVerticalMetrics); + PSFontFileInfo *setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupType3Font(GfxFont *font, Dict *parentResDict); GString *makePSFontName(GfxFont *font, Ref *id); void setupImages(Dict *resDict); void setupImage(Ref id, Stream *str, GBool mask); void setupForms(Dict *resDict); - void setupForm(Ref id, Object *strObj); + void setupForm(Object *strRef, Object *strObj); void addProcessColor(double c, double m, double y, double k); void addCustomColor(GfxSeparationColorSpace *sepCS); void doPath(GfxPath *path); @@ -358,19 +360,8 @@ private: PDFDoc *doc; XRef *xref; // the xref table for this PDF file - Ref *fontIDs; // list of object IDs of all used fonts - int fontIDLen; // number of entries in fontIDs array - int fontIDSize; // size of fontIDs array - GHash *fontNames; // all used font names - PST1FontName *t1FontNames; // font names for Type 1/1C fonts - int t1FontNameLen; // number of entries in t1FontNames array - int t1FontNameSize; // size of t1FontNames array - PSFont8Info *font8Info; // info for 8-bit fonts - int font8InfoLen; // number of entries in font8Info array - int font8InfoSize; // size of font8Info array - PSFont16Enc *font16Enc; // encodings for substitute 16-bit fonts - int font16EncLen; // number of entries in font16Enc array - int font16EncSize; // size of font16Enc array + GList *fontInfo; // info for each font [PSFontInfo] + GHash *fontFileInfo; // info for each font file [PSFontFileInfo] Ref *imgIDs; // list of image IDs for in-memory images int imgIDLen; // number of entries in imgIDs array int imgIDSize; // size of imgIDs array diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSTokenizer.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSTokenizer.cc index 0ad37618563..0ad37618563 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSTokenizer.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSTokenizer.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSTokenizer.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSTokenizer.h index 4d5ee97f4dd..4d5ee97f4dd 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PSTokenizer.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PSTokenizer.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Page.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Page.cc index f5eb0da6b04..2eadb24d9f9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Page.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Page.cc @@ -25,6 +25,7 @@ #include "Gfx.h" #include "GfxState.h" #include "Annot.h" +#include "Form.h" #endif #include "Error.h" #include "Catalog.h" @@ -123,6 +124,15 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { dict->lookup("Metadata", &metadata); dict->lookup("PieceInfo", &pieceInfo); dict->lookup("SeparationInfo", &separationInfo); + if (dict->lookup("UserUnit", &obj1)->isNum()) { + userUnit = obj1.getNum(); + if (userUnit < 1) { + userUnit = 1; + } + } else { + userUnit = 1; + } + obj1.free(); // resource dictionary dict->lookup("Resources", &obj1); @@ -312,7 +322,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, Gfx *gfx; Object obj; Annots *annotList; - Dict *acroForm; + Form *form; int i; if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop, @@ -347,8 +357,10 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, contents.fetch(xref, &obj); if (!obj.isNull()) { gfx->saveState(); - gfx->display(&obj); - gfx->restoreState(); + gfx->display(&contents); + while (gfx->getState()->hasSaves()) { + gfx->restoreState(); + } } else { // empty pages need to call dump to do any setup required by the // OutputDev @@ -356,20 +368,11 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, } obj.free(); - // draw annotations + // draw (non-form) annotations if (globalParams->getDrawAnnotations()) { annotList = new Annots(doc, getAnnots(&obj)); obj.free(); - acroForm = doc->getCatalog()->getAcroForm()->isDict() ? - doc->getCatalog()->getAcroForm()->getDict() : NULL; - if (acroForm) { - if (acroForm->lookup("NeedAppearances", &obj)) { - if (obj.isBool() && obj.getBool()) { - annotList->generateAppearances(); - } - } - obj.free(); - } + annotList->generateAnnotAppearances(); if (annotList->getNumAnnots() > 0) { if (globalParams->getPrintCommands()) { printf("***** Annotations\n"); @@ -382,6 +385,12 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, delete annotList; } + // draw form fields + if ((form = doc->getCatalog()->getForm())) { + form->draw(num, gfx, printing); + out->dump(); + } + delete gfx; #endif } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Page.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Page.h index 102eca8a7b6..0e7729efc47 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Page.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Page.h @@ -77,6 +77,7 @@ public: Dict *getSeparationInfo() { return separationInfo.isDict() ? separationInfo.getDict() : (Dict *)NULL; } + double getUserUnit() { return userUnit; } Dict *getResourceDict() { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } @@ -100,6 +101,7 @@ private: Object metadata; Object pieceInfo; Object separationInfo; + double userUnit; Object resources; }; @@ -146,6 +148,7 @@ public: Stream *getMetadata() { return attrs->getMetadata(); } Dict *getPieceInfo() { return attrs->getPieceInfo(); } Dict *getSeparationInfo() { return attrs->getSeparationInfo(); } + double getUserUnit() { return attrs->getUserUnit(); } // Get resource dictionary. Dict *getResourceDict() { return attrs->getResourceDict(); } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Parser.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Parser.cc index c43da260d00..dd37470b139 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Parser.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Parser.cc @@ -153,7 +153,7 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey, Object obj; BaseStream *baseStr; Stream *str; - Guint pos, endPos, length; + GFileOffset pos, endPos, length; // get stream start position lexer->skipToNextLine(); @@ -162,20 +162,21 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey, } pos = str->getPos(); - // get length - dict->dictLookup("Length", &obj, recursion); - if (obj.isInt()) { - length = (Guint)obj.getInt(); - obj.free(); - } else { - error(errSyntaxError, getPos(), "Bad 'Length' attribute in stream"); - obj.free(); - return NULL; - } - // check for length in damaged file if (xref && xref->getStreamEnd(pos, &endPos)) { length = endPos - pos; + + // get length from the stream object + } else { + dict->dictLookup("Length", &obj, recursion); + if (obj.isInt()) { + length = (GFileOffset)(Guint)obj.getInt(); + obj.free(); + } else { + error(errSyntaxError, getPos(), "Bad 'Length' attribute in stream"); + obj.free(); + return NULL; + } } // in badly damaged PDF files, we can run off the end of the input @@ -210,7 +211,7 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey, } // get filters - str = str->addFilters(dict); + str = str->addFilters(dict, recursion); return str; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Parser.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Parser.h index b25d749821b..d5403d0c8fc 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Parser.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Parser.h @@ -42,7 +42,7 @@ public: Stream *getStream() { return lexer->getStream(); } // Get current position in file. - int getPos() { return lexer->getPos(); } + GFileOffset getPos() { return lexer->getPos(); } private: diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PreScanOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PreScanOutputDev.cc index bf48df05444..ced188ea376 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PreScanOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PreScanOutputDev.cc @@ -61,13 +61,13 @@ void PreScanOutputDev::eoFill(GfxState *state) { } void PreScanOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, - Object *str, + Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) { if (paintType == 1) { - gfx->drawForm(str, resDict, mat, bbox); + gfx->drawForm(strRef, resDict, mat, bbox); } else { check(state->getFillColorSpace(), state->getFillColor(), state->getFillOpacity(), state->getBlendMode()); @@ -174,9 +174,7 @@ void PreScanOutputDev::endType3Char(GfxState *state) { void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { - int i, j; - + GBool inlineImg, GBool interpolate) { check(state->getFillColorSpace(), state->getFillColor(), state->getFillOpacity(), state->getBlendMode()); if (state->getFillColorSpace()->getMode() == csPattern) { @@ -186,9 +184,7 @@ void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, if (inlineImg) { str->reset(); - j = height * ((width + 7) / 8); - for (i = 0; i < j; ++i) - str->getChar(); + str->discardChars(height * ((width + 7) / 8)); str->close(); } } @@ -196,9 +192,9 @@ void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, void PreScanOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { + int *maskColors, GBool inlineImg, + GBool interpolate) { GfxColorSpace *colorSpace; - int i, j; colorSpace = colorMap->getColorSpace(); if (colorSpace->getMode() == csIndexed) { @@ -221,10 +217,8 @@ void PreScanOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, if (inlineImg) { str->reset(); - j = height * ((width * colorMap->getNumPixelComps() * - colorMap->getBits() + 7) / 8); - for (i = 0; i < j; ++i) - str->getChar(); + str->discardChars(height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8)); str->close(); } } @@ -235,7 +229,7 @@ void PreScanOutputDev::drawMaskedImage(GfxState *state, Object *ref, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert) { + GBool maskInvert, GBool interpolate) { GfxColorSpace *colorSpace; colorSpace = colorMap->getColorSpace(); @@ -264,7 +258,8 @@ void PreScanOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap) { + GfxImageColorMap *maskColorMap, + GBool interpolate) { GfxColorSpace *colorSpace; colorSpace = colorMap->getColorSpace(); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PreScanOutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PreScanOutputDev.h index 3889cfce7c6..6ca8b463432 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/PreScanOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/PreScanOutputDev.h @@ -67,7 +67,7 @@ public: virtual void stroke(GfxState *state); virtual void fill(GfxState *state); virtual void eoFill(GfxState *state); - virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -92,21 +92,22 @@ public: //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); + int *maskColors, GBool inlineImg, GBool interpolate); virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); + GBool maskInvert, GBool interpolate); virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap); + GfxImageColorMap *maskColorMap, + GBool interpolate); //----- transparency groups and soft masks virtual void beginTransparencyGroup(GfxState *state, double *bbox, diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SecurityHandler.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SecurityHandler.cc index 52607c24042..88f2b65b8f1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SecurityHandler.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SecurityHandler.cc @@ -158,7 +158,7 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, if ((encRevision <= 4 && ownerKeyObj.getString()->getLength() == 32 && userKeyObj.getString()->getLength() == 32) || - (encRevision == 5 && + ((encRevision == 5 || encRevision == 6) && // the spec says 48 bytes, but Acrobat pads them out longer ownerKeyObj.getString()->getLength() >= 48 && userKeyObj.getString()->getLength() >= 48 && @@ -180,7 +180,7 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, //~ doesn't handle the case where StmF, StrF, and EFF are not all the //~ same) if ((encVersion == 4 || encVersion == 5) && - (encRevision == 4 || encRevision == 5)) { + (encRevision == 4 || encRevision == 5 || encRevision == 6)) { encryptDictA->dictLookup("CF", &cryptFiltersObj); encryptDictA->dictLookup("StmF", &streamFilterObj); encryptDictA->dictLookup("StrF", &stringFilterObj); @@ -216,7 +216,9 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, cfLengthObj.free(); } else if (cfmObj.isName("AESV3")) { encVersion = 5; - encRevision = 5; + if (encRevision != 5 && encRevision != 6) { + encRevision = 6; + } encAlgorithm = cryptAES256; if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) { @@ -254,15 +256,15 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, } else { fileID = new GString(); } - if (fileKeyLength > 16 || fileKeyLength < 0) { + if (fileKeyLength > 16 || fileKeyLength <= 0) { fileKeyLength = 16; } ok = gTrue; - } else if (encVersion == 5 && encRevision == 5) { + } else if (encVersion == 5 && (encRevision == 5 || encRevision == 6)) { fileID = new GString(); // unused for V=R=5 ownerEnc = ownerEncObj.getString()->copy(); userEnc = userEncObj.getString()->copy(); - if (fileKeyLength > 32 || fileKeyLength < 0) { + if (fileKeyLength > 32 || fileKeyLength <= 0) { fileKeyLength = 32; } ok = gTrue; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SecurityHandler.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SecurityHandler.h index 784a52e8017..784a52e8017 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SecurityHandler.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SecurityHandler.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SplashOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SplashOutputDev.cc index 50e4801d052..d9befecd253 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SplashOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SplashOutputDev.cc @@ -2,7 +2,7 @@ // // SplashOutputDev.cc // -// Copyright 2003 Glyph & Cog, LLC +// Copyright 2003-2013 Glyph & Cog, LLC // //======================================================================== @@ -27,6 +27,7 @@ #include "BuiltinFont.h" #include "BuiltinFontTables.h" #include "FoFiTrueType.h" +#include "JPXStream.h" #include "SplashBitmap.h" #include "SplashGlyphBitmap.h" #include "SplashPattern.h" @@ -118,7 +119,9 @@ static void splashOutBlendColorDodge(SplashColorPtr src, SplashColorPtr dest, int i, x; for (i = 0; i < splashColorModeNComps[cm]; ++i) { - if (src[i] == 255) { + if (dest[i] == 0) { + blend[i] = 0; + } else if (src[i] == 255) { blend[i] = 255; } else { x = (dest[i] * 255) / (255 - src[i]); @@ -132,7 +135,9 @@ static void splashOutBlendColorBurn(SplashColorPtr src, SplashColorPtr dest, int i, x; for (i = 0; i < splashColorModeNComps[cm]; ++i) { - if (src[i] == 0) { + if (dest[i] == 255) { + blend[i] = 255; + } else if (src[i] == 0) { blend[i] = 0; } else { x = ((255 - dest[i]) * 255) / src[i]; @@ -284,7 +289,10 @@ static void setSat(Guchar rIn, Guchar gIn, Guchar bIn, int sat, static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest, SplashColorPtr blend, SplashColorMode cm) { - Guchar r0, g0, b0, r1, g1, b1; + Guchar r0, g0, b0; +#if SPLASH_CMYK + Guchar r1, g1, b1; +#endif switch (cm) { case splashModeMono1: @@ -317,7 +325,10 @@ static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest, static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest, SplashColorPtr blend, SplashColorMode cm) { - Guchar r0, g0, b0, r1, g1, b1; + Guchar r0, g0, b0; +#if SPLASH_CMYK + Guchar r1, g1, b1; +#endif switch (cm) { case splashModeMono1: @@ -435,7 +446,11 @@ SplashBlendFunc splashOutBlendFuncs[] = { class SplashOutFontFileID: public SplashFontFileID { public: - SplashOutFontFileID(Ref *rA) { r = *rA; substIdx = -1; } + SplashOutFontFileID(Ref *rA) { + r = *rA; + substIdx = -1; + oblique = 0; + } ~SplashOutFontFileID() {} @@ -444,12 +459,15 @@ public: ((SplashOutFontFileID *)id)->r.gen == r.gen; } + void setOblique(double obliqueA) { oblique = obliqueA; } + double getOblique() { return oblique; } void setSubstIdx(int substIdxA) { substIdx = substIdxA; } int getSubstIdx() { return substIdx; } private: Ref r; + double oblique; int substIdx; }; @@ -536,6 +554,10 @@ T3FontCache::~T3FontCache() { struct T3GlyphStack { Gushort code; // character code + GBool haveDx; // set after seeing a d0/d1 operator + GBool doNotCache; // set if we see a gsave/grestore before + // the d0/d1 + //----- cache info T3FontCache *cache; // font cache for the current font T3FontCacheTag *cacheTag; // pointer to cache tag for the glyph @@ -580,6 +602,7 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA, bitmapRowPad = bitmapRowPadA; bitmapTopDown = bitmapTopDownA; bitmapUpsideDown = gFalse; + noComposite = gFalse; allowAntialias = allowAntialiasA; vectorAntialias = allowAntialias && globalParams->getVectorAntialias() && @@ -596,6 +619,7 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA, colorMode != splashModeMono1, bitmapTopDown); splash = new Splash(bitmap, vectorAntialias, &screenParams); splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust(globalParams->getStrokeAdjust()); splash->clear(paperColor, 0); fontEngine = NULL; @@ -688,9 +712,6 @@ void SplashOutputDev::startDoc(XRef *xrefA) { delete fontEngine; } fontEngine = new SplashFontEngine( -#if HAVE_T1LIB_H - globalParams->getEnableT1lib(), -#endif #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H globalParams->getEnableFreeType(), globalParams->getDisableFreeTypeHinting() @@ -777,18 +798,28 @@ void SplashOutputDev::startPage(int pageNum, GfxState *state) { } void SplashOutputDev::endPage() { - if (colorMode != splashModeMono1) { + if (colorMode != splashModeMono1 && !noComposite) { splash->compositeBackground(paperColor); } } void SplashOutputDev::saveState(GfxState *state) { splash->saveState(); + if (t3GlyphStack && !t3GlyphStack->haveDx) { + t3GlyphStack->doNotCache = gTrue; + error(errSyntaxWarning, -1, + "Save (q) operator before d0/d1 in Type 3 glyph"); + } } void SplashOutputDev::restoreState(GfxState *state) { splash->restoreState(); needFontUpdate = gTrue; + if (t3GlyphStack && !t3GlyphStack->haveDx) { + t3GlyphStack->doNotCache = gTrue; + error(errSyntaxWarning, -1, + "Restore (Q) operator before d0/d1 in Type 3 glyph"); + } } void SplashOutputDev::updateAll(GfxState *state) { @@ -976,10 +1007,19 @@ void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace, if (overprintFlag && globalParams->getOverprintPreview()) { mask = colorSpace->getOverprintMask(); + // The OPM (overprintMode) setting is only relevant when the color + // space is DeviceCMYK or is "implicitly converted to DeviceCMYK". + // Per the PDF spec, this happens with ICCBased color spaces only + // if the profile matches the output device -- Acrobat's output + // preview mode does NOT honor OPM=1 for ICCBased CMYK color + // spaces. To change the behavior here, use: + // if (singleColor && overprintMode && + // (colorSpace->getMode() == csDeviceCMYK || + // (colorSpace->getMode() == csICCBased && + // colorSpace->getNComps() == 4 && + // <...the profile matches...>))) if (singleColor && overprintMode && - (colorSpace->getMode() == csDeviceCMYK || - (colorSpace->getMode() == csICCBased && - colorSpace->getNComps() == 4))) { + colorSpace->getMode() == csDeviceCMYK) { colorSpace->getCMYK(singleColor, &cmyk); if (cmyk.c == 0) { mask &= ~1; @@ -1072,22 +1112,33 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { FoFiTrueType *ff; Ref embRef; Object refObj, strObj; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf; + FILE *extFontFile; +#else GString *tmpFileName, *fileName; FILE *tmpFile; +#endif + char blk[4096]; int *codeToGID; CharCodeToUnicode *ctu; double *textMat; - double m11, m12, m21, m22, fontSize; - double w, fontScaleMin, fontScaleAvg, fontScale; + double m11, m12, m21, m22, fontSize, oblique; + double fsx, fsy, w, fontScaleMin, fontScaleAvg, fontScale; Gushort ww; SplashCoord mat[4]; char *name; Unicode uBuf[8]; - int c, substIdx, n, code, cmap, i; + int substIdx, n, code, cmap, i; needFontUpdate = gFalse; font = NULL; +#if LOAD_FONTS_FROM_MEM + fontBuf = NULL; +#else tmpFileName = NULL; + fileName = NULL; +#endif substIdx = -1; if (!(gfxFont = state->getFont())) { @@ -1098,10 +1149,13 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { goto err1; } - // sanity-check the font size - skip anything larger than 10 inches + // sanity-check the font size - skip anything larger than 20 inches // (this avoids problems allocating memory for the font cache) - if (state->getTransformedFontSize() - > 10 * (state->getHDPI() + state->getVDPI())) { + state->textTransformDelta(state->getFontSize(), state->getFontSize(), + &fsx, &fsy); + state->transformDelta(fsx, fsy, &fsx, &fsy); + if (fabs(fsx) > 20 * state->getHDPI() || + fabs(fsy) > 20 * state->getVDPI()) { goto err1; } @@ -1112,7 +1166,6 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { } else { - fileName = NULL; fontNum = 0; if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) { @@ -1125,6 +1178,24 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { // embedded font if (fontLoc->locType == gfxFontLocEmbedded) { gfxFont->getEmbeddedFontID(&embRef); +#if LOAD_FONTS_FROM_MEM + fontBuf = new GString(); + refObj.initRef(embRef.num, embRef.gen); + refObj.fetch(xref, &strObj); + refObj.free(); + if (!strObj.isStream()) { + error(errSyntaxError, -1, "Embedded font object is wrong type"); + strObj.free(); + delete fontLoc; + goto err2; + } + strObj.streamReset(); + while ((n = strObj.streamGetBlock(blk, sizeof(blk))) > 0) { + fontBuf->append(blk, n); + } + strObj.streamClose(); + strObj.free(); +#else if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { error(errIO, -1, "Couldn't create temporary font file"); delete fontLoc; @@ -1141,21 +1212,39 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { goto err2; } strObj.streamReset(); - while ((c = strObj.streamGetChar()) != EOF) { - fputc(c, tmpFile); + while ((n = strObj.streamGetBlock(blk, sizeof(blk))) > 0) { + fwrite(blk, 1, n, tmpFile); } strObj.streamClose(); strObj.free(); fclose(tmpFile); fileName = tmpFileName; +#endif // external font } else { // gfxFontLocExternal +#if LOAD_FONTS_FROM_MEM + if (!(extFontFile = fopen(fontLoc->path->getCString(), "rb"))) { + error(errSyntaxError, -1, "Couldn't open external font file '{0:t}'", + fontLoc->path); + delete fontLoc; + goto err2; + } + fontBuf = new GString(); + while ((n = fread(blk, 1, sizeof(blk), extFontFile)) > 0) { + fontBuf->append(blk, n); + } + fclose(extFontFile); +#else fileName = fontLoc->path; +#endif fontNum = fontLoc->fontNum; if (fontLoc->substIdx >= 0) { id->setSubstIdx(fontLoc->substIdx); } + if (fontLoc->oblique != 0) { + id->setOblique(fontLoc->oblique); + } } // load the font file @@ -1163,8 +1252,12 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { case fontType1: if (!(fontFile = fontEngine->loadType1Font( id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else fileName->getCString(), fileName == tmpFileName, +#endif (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->getCString() @@ -1176,8 +1269,12 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { case fontType1C: if (!(fontFile = fontEngine->loadType1CFont( id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else fileName->getCString(), fileName == tmpFileName, +#endif (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->getCString() @@ -1189,8 +1286,12 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { case fontType1COT: if (!(fontFile = fontEngine->loadOpenTypeT1CFont( id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else fileName->getCString(), fileName == tmpFileName, +#endif (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) { error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->getCString() @@ -1201,7 +1302,12 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { break; case fontTrueType: case fontTrueTypeOT: - if ((ff = FoFiTrueType::load(fileName->getCString()))) { +#if LOAD_FONTS_FROM_MEM + if ((ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), + fontNum))) { +#else + if ((ff = FoFiTrueType::load(fileName->getCString(), fontNum))) { +#endif codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); n = 256; delete ff; @@ -1222,9 +1328,13 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { } if (!(fontFile = fontEngine->loadTrueTypeFont( id, - fileName->getCString(), fontNum, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), fileName == tmpFileName, - codeToGID, n, +#endif + fontNum, codeToGID, n, gfxFont->getEmbeddedFontName() ? gfxFont->getEmbeddedFontName()->getCString() : (char *)NULL))) { @@ -1239,8 +1349,14 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { case fontCIDType0C: if (!(fontFile = fontEngine->loadCIDFont( id, +#if LOAD_FONTS_FROM_MEM + fontBuf +#else fileName->getCString(), - fileName == tmpFileName))) { + fileName == tmpFileName +#endif + ))) { + error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); @@ -1260,8 +1376,12 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { } if (!(fontFile = fontEngine->loadOpenTypeCFFFont( id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else fileName->getCString(), fileName == tmpFileName, +#endif codeToGID, n))) { error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", gfxFont->getName() ? gfxFont->getName()->getCString() @@ -1281,11 +1401,18 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), n * sizeof(int)); } + } else if (!globalParams->getMapExtTrueTypeFontsViaUnicode()) { + codeToGID = NULL; + n = 0; } else { // create a CID-to-GID mapping, via Unicode if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) { - //~ this should use fontNum to load the correct font - if ((ff = FoFiTrueType::load(fileName->getCString()))) { +#if LOAD_FONTS_FROM_MEM + if ((ff = FoFiTrueType::make(fontBuf->getCString(), + fontBuf->getLength(), fontNum))) { +#else + if ((ff = FoFiTrueType::load(fileName->getCString(), fontNum))) { +#endif // look for a Unicode cmap for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { if ((ff->getCmapPlatform(cmap) == 3 && @@ -1296,7 +1423,11 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { } if (cmap < ff->getNumCmaps()) { // map CID -> Unicode -> GID - n = ctu->getLength(); + if (ctu->isIdentity()) { + n = 65536; + } else { + n = ctu->getLength(); + } codeToGID = (int *)gmallocn(n, sizeof(int)); for (code = 0; code < n; ++code) { if (ctu->mapToUnicode(code, uBuf, 8) > 0) { @@ -1318,9 +1449,13 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { } if (!(fontFile = fontEngine->loadTrueTypeFont( id, - fileName->getCString(), fontNum, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fileName->getCString(), fileName == tmpFileName, - codeToGID, n, +#endif + fontNum, codeToGID, n, gfxFont->getEmbeddedFontName() ? gfxFont->getEmbeddedFontName()->getCString() : (char *)NULL))) { @@ -1342,10 +1477,15 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { // get the font matrix textMat = state->getTextMat(); fontSize = state->getFontSize(); - m11 = textMat[0] * fontSize * state->getHorizScaling(); - m12 = textMat[1] * fontSize * state->getHorizScaling(); - m21 = textMat[2] * fontSize; - m22 = textMat[3] * fontSize; + oblique = ((SplashOutFontFileID *)fontFile->getID())->getOblique(); + m11 = state->getHorizScaling() * textMat[0]; + m12 = state->getHorizScaling() * textMat[1]; + m21 = oblique * m11 + textMat[2]; + m22 = oblique * m12 + textMat[3]; + m11 *= fontSize; + m12 *= fontSize; + m21 *= fontSize; + m22 *= fontSize; // for substituted fonts: adjust the font matrix -- compare the // widths of letters and digits (A-Z, a-z, 0-9) in the original font @@ -1393,18 +1533,26 @@ void SplashOutputDev::doUpdateFont(GfxState *state) { mat[2] = m21; mat[3] = m22; font = fontEngine->getFont(fontFile, mat, splash->getMatrix()); +#if !LOAD_FONTS_FROM_MEM if (tmpFileName) { delete tmpFileName; } +#endif return; err2: delete id; err1: +#if LOAD_FONTS_FROM_MEM + if (fontBuf) { + delete fontBuf; + } +#else if (tmpFileName) { unlink(tmpFileName->getCString()); delete tmpFileName; } +#endif return; } @@ -1447,7 +1595,8 @@ void SplashOutputDev::eoFill(GfxState *state) { delete path; } -void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, +void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, + Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -1529,7 +1678,7 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, ya = y * yStep; mat1[4] = xa * mat[0] + ya * mat[2] + mat[4]; mat1[5] = xa * mat[1] + ya * mat[3] + mat[5]; - gfx->drawForm(str, resDict, mat1, bbox); + gfx->drawForm(strRef, resDict, mat1, bbox); } } return; @@ -1542,6 +1691,7 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, colorMode, gTrue, bitmapTopDown); splash = new Splash(bitmap, vectorAntialias, origSplash->getScreen()); splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust(globalParams->getStrokeAdjust()); for (i = 0; i < splashMaxColorComps; ++i) { color[i] = 0; } @@ -1556,7 +1706,7 @@ void SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, // render the tile state->shiftCTM(-tileX0, -tileY0); updateCTM(state, 0, 0, 0, 0, 0, 0); - gfx->drawForm(str, resDict, mat, bbox); + gfx->drawForm(strRef, resDict, mat, bbox); state->shiftCTM(tileX0, tileY0); updateCTM(state, 0, 0, 0, 0, 0, 0); @@ -1889,8 +2039,8 @@ GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y, t3GlyphStack->cache = t3Font; t3GlyphStack->cacheTag = NULL; t3GlyphStack->cacheData = NULL; - - haveT3Dx = gFalse; + t3GlyphStack->haveDx = gFalse; + t3GlyphStack->doNotCache = gFalse; return gFalse; } @@ -1920,7 +2070,7 @@ void SplashOutputDev::endType3Char(GfxState *state) { } void SplashOutputDev::type3D0(GfxState *state, double wx, double wy) { - haveT3Dx = gTrue; + t3GlyphStack->haveDx = gTrue; } void SplashOutputDev::type3D1(GfxState *state, double wx, double wy, @@ -1932,10 +2082,14 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy, int i, j; // ignore multiple d0/d1 operators - if (haveT3Dx) { + if (t3GlyphStack->haveDx) { + return; + } + t3GlyphStack->haveDx = gTrue; + // don't cache if we got a gsave/grestore before the d1 + if (t3GlyphStack->doNotCache) { return; } - haveT3Dx = gTrue; t3Font = t3GlyphStack->cache; @@ -2026,6 +2180,7 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy, color[0] = 0xff; } splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust(t3GlyphStack->origSplash->getStrokeAdjust()); splash->setFillPattern(new SplashSolidColor(color)); splash->setStrokePattern(new SplashSolidColor(color)); //~ this should copy other state from t3GlyphStack->origSplash? @@ -2072,10 +2227,9 @@ GBool SplashOutputDev::imageMaskSrc(void *data, SplashColorPtr line) { SplashColorPtr q; int x; - if (imgMaskData->y == imgMaskData->height) { - return gFalse; - } - if (!(p = imgMaskData->imgStr->getLine())) { + if (imgMaskData->y == imgMaskData->height || + !(p = imgMaskData->imgStr->getLine())) { + memset(line, 0, imgMaskData->width); return gFalse; } for (x = 0, q = line; x < imgMaskData->width; ++x) { @@ -2087,7 +2241,7 @@ GBool SplashOutputDev::imageMaskSrc(void *data, SplashColorPtr line) { void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { + GBool inlineImg, GBool interpolate) { double *ctm; SplashCoord mat[6]; SplashOutImageMaskData imgMaskData; @@ -2106,6 +2260,8 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, mat[4] = ctm[2] + ctm[4]; mat[5] = ctm[3] + ctm[5]; + reduceImageResolution(str, ctm, &width, &height); + imgMaskData.imgStr = new ImageStream(str, width, 1, 1); imgMaskData.imgStr->reset(); imgMaskData.invert = invert ? 0 : 1; @@ -2114,7 +2270,7 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, imgMaskData.y = 0; splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat, - t3GlyphStack != NULL); + t3GlyphStack != NULL, interpolate); if (inlineImg) { while (imgMaskData.y < height) { imgMaskData.imgStr->getLine(); @@ -2130,7 +2286,8 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg) { + GBool inlineImg, + GBool interpolate) { double *ctm; SplashCoord mat[6]; SplashOutImageMaskData imgMaskData; @@ -2145,6 +2302,7 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state, mat[3] = -ctm[3]; mat[4] = ctm[2] + ctm[4]; mat[5] = ctm[3] + ctm[5]; + reduceImageResolution(str, ctm, &width, &height); imgMaskData.imgStr = new ImageStream(str, width, 1, 1); imgMaskData.imgStr->reset(); imgMaskData.invert = invert ? 0 : 1; @@ -2154,12 +2312,12 @@ void SplashOutputDev::setSoftMaskFromImageMask(GfxState *state, maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), 1, splashModeMono8, gFalse); maskSplash = new Splash(maskBitmap, gTrue); - maskColor[0] = 0; - maskSplash->clear(maskColor); + maskSplash->setStrokeAdjust(globalParams->getStrokeAdjust()); + clearMaskRegion(state, maskSplash, 0, 0, 1, 1); maskColor[0] = 0xff; maskSplash->setFillPattern(new SplashSolidColor(maskColor)); maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData, - width, height, mat, gFalse); + width, height, mat, gFalse, interpolate); delete imgMaskData.imgStr; str->close(); delete maskSplash; @@ -2180,17 +2338,12 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, SplashOutImageData *imgData = (SplashOutImageData *)data; Guchar *p; SplashColorPtr q, col; - GfxRGB rgb; - GfxGray gray; -#if SPLASH_CMYK - GfxCMYK cmyk; -#endif int nComps, x; - if (imgData->y == imgData->height) { - return gFalse; - } - if (!(p = imgData->imgStr->getLine())) { + if (imgData->y == imgData->height || + !(p = imgData->imgStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); return gFalse; } @@ -2229,29 +2382,15 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, switch (imgData->colorMode) { case splashModeMono1: case splashModeMono8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getGray(p, &gray); - *q++ = colToByte(gray); - } + imgData->colorMap->getGrayByteLine(p, colorLine, imgData->width); break; case splashModeRGB8: case splashModeBGR8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getRGB(p, &rgb); - *q++ = colToByte(rgb.r); - *q++ = colToByte(rgb.g); - *q++ = colToByte(rgb.b); - } + imgData->colorMap->getRGBByteLine(p, colorLine, imgData->width); break; #if SPLASH_CMYK case splashModeCMYK8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getCMYK(p, &cmyk); - *q++ = colToByte(cmyk.c); - *q++ = colToByte(cmyk.m); - *q++ = colToByte(cmyk.y); - *q++ = colToByte(cmyk.k); - } + imgData->colorMap->getCMYKByteLine(p, colorLine, imgData->width); break; #endif } @@ -2274,10 +2413,11 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine, Guchar alpha; int nComps, x, i; - if (imgData->y == imgData->height) { - return gFalse; - } - if (!(p = imgData->imgStr->getLine())) { + if (imgData->y == imgData->height || + !(p = imgData->imgStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); + memset(alphaLine, 0, imgData->width); return gFalse; } @@ -2353,7 +2493,8 @@ GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine, void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { + int *maskColors, GBool inlineImg, + GBool interpolate) { double *ctm; SplashCoord mat[6]; SplashOutImageData imgData; @@ -2378,6 +2519,8 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, mat[4] = ctm[2] + ctm[4]; mat[5] = ctm[3] + ctm[5]; + reduceImageResolution(str, ctm, &width, &height); + imgData.imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); @@ -2433,12 +2576,14 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, if (colorMode == splashModeMono1) { srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; } else { srcMode = colorMode; } src = maskColors ? &alphaImageSrc : &imageSrc; splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse, - width, height, mat); + width, height, mat, interpolate); if (inlineImg) { while (imgData.y < height) { imgData.imgStr->getLine(); @@ -2470,15 +2615,17 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine, #if SPLASH_CMYK GfxCMYK cmyk; #endif + static Guchar bitToByte[2] = {0x00, 0xff}; Guchar alpha; Guchar *maskPtr; - int maskBit; + int maskShift; int nComps, x; - if (imgData->y == imgData->height) { - return gFalse; - } - if (!(p = imgData->imgStr->getLine())) { + if (imgData->y == imgData->height || + !(p = imgData->imgStr->getLine())) { + memset(colorLine, 0, + imgData->width * splashColorModeNComps[imgData->colorMode]); + memset(alphaLine, 0, imgData->width); return gFalse; } @@ -2486,15 +2633,13 @@ GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine, maskPtr = imgData->mask->getDataPtr() + imgData->y * imgData->mask->getRowSize(); - maskBit = 0x80; + maskShift = 7; for (x = 0, q = colorLine, aq = alphaLine; x < imgData->width; ++x, p += nComps) { - alpha = (*maskPtr & maskBit) ? 0xff : 0x00; - if (!(maskBit >>= 1)) { - ++maskPtr; - maskBit = 0x80; - } + alpha = bitToByte[(*maskPtr >> maskShift) & 1]; + maskPtr += (8 - maskShift) >> 3; + maskShift = (maskShift - 1) & 7; if (imgData->lookup) { switch (imgData->colorMode) { case splashModeMono1: @@ -2555,7 +2700,8 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, - int maskHeight, GBool maskInvert) { + int maskHeight, GBool maskInvert, + GBool interpolate) { GfxImageColorMap *maskColorMap; Object maskDecode, decodeLow, decodeHigh; double *ctm; @@ -2577,6 +2723,10 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(), state->getOverprintMode(), NULL); + ctm = state->getCTM(); + reduceImageResolution(str, ctm, &width, &height); + reduceImageResolution(maskStr, ctm, &maskWidth, &maskHeight); + // If the mask is higher resolution than the image, use // drawSoftMaskedImage() instead. if (maskWidth > width || maskHeight > height) { @@ -2589,7 +2739,8 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, new GfxDeviceGrayColorSpace()); maskDecode.free(); drawSoftMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskColorMap); + maskStr, maskWidth, maskHeight, maskColorMap, + interpolate); delete maskColorMap; } else { @@ -2610,19 +2761,20 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, imgMaskData.y = 0; maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, gFalse); maskSplash = new Splash(maskBitmap, gFalse); + maskSplash->setStrokeAdjust(globalParams->getStrokeAdjust()); maskColor[0] = 0; maskSplash->clear(maskColor); maskColor[0] = 0xff; maskSplash->setFillPattern(new SplashSolidColor(maskColor)); + // use "glyph mode" here to get the correct scaled size maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData, - maskWidth, maskHeight, mat, gFalse); + maskWidth, maskHeight, mat, gTrue, interpolate); delete imgMaskData.imgStr; maskStr->close(); delete maskSplash; //----- draw the source image - ctm = state->getCTM(); mat[0] = ctm[0]; mat[1] = ctm[1]; mat[2] = -ctm[2]; @@ -2685,11 +2837,13 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, if (colorMode == splashModeMono1) { srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; } else { srcMode = colorMode; } splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue, - width, height, mat); + width, height, mat, interpolate); delete maskBitmap; gfree(imgData.lookup); @@ -2703,7 +2857,8 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap) { + GfxImageColorMap *maskColorMap, + GBool interpolate) { double *ctm; SplashCoord mat[6]; SplashOutImageData imgData; @@ -2711,7 +2866,6 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, SplashColorMode srcMode; SplashBitmap *maskBitmap; Splash *maskSplash; - SplashColor maskColor; GfxGray gray; GfxRGB rgb; #if SPLASH_CMYK @@ -2731,6 +2885,9 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, mat[4] = ctm[2] + ctm[4]; mat[5] = ctm[3] + ctm[5]; + reduceImageResolution(str, ctm, &width, &height); + reduceImageResolution(maskStr, ctm, &maskWidth, &maskHeight); + //----- set up the soft mask imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, @@ -2753,10 +2910,10 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), 1, splashModeMono8, gFalse); maskSplash = new Splash(maskBitmap, vectorAntialias); - maskColor[0] = 0; - maskSplash->clear(maskColor); + maskSplash->setStrokeAdjust(globalParams->getStrokeAdjust()); + clearMaskRegion(state, maskSplash, 0, 0, 1, 1); maskSplash->drawImage(&imageSrc, &imgMaskData, splashModeMono8, gFalse, - maskWidth, maskHeight, mat); + maskWidth, maskHeight, mat, interpolate); delete imgMaskData.imgStr; maskStr->close(); gfree(imgMaskData.lookup); @@ -2820,10 +2977,13 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, if (colorMode == splashModeMono1) { srcMode = splashModeMono8; + } else if (colorMode == splashModeBGR8) { + srcMode = splashModeRGB8; } else { srcMode = colorMode; } - splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat); + splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat, + interpolate); splash->setSoftMask(NULL); gfree(imgData.lookup); @@ -2831,6 +2991,98 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, str->close(); } +void SplashOutputDev::reduceImageResolution(Stream *str, double *ctm, + int *width, int *height) { + double sw, sh; + int reduction; + + if (str->getKind() == strJPX && + *width * *height > 10000000) { + sw = (double)*width / (fabs(ctm[2]) + fabs(ctm[3])); + sh = (double)*height / (fabs(ctm[0]) + fabs(ctm[1])); + if (sw > 8 && sh > 8) { + reduction = 3; + } else if (sw > 4 && sh > 4) { + reduction = 2; + } else if (sw > 2 && sh > 2) { + reduction = 1; + } else { + reduction = 0; + } + if (reduction > 0) { + ((JPXStream *)str)->reduceResolution(reduction); + *width >>= reduction; + *height >>= reduction; + } + } +} + +void SplashOutputDev::clearMaskRegion(GfxState *state, + Splash *maskSplash, + double xMin, double yMin, + double xMax, double yMax) { + SplashBitmap *maskBitmap; + double xxMin, yyMin, xxMax, yyMax, xx, yy; + int xxMinI, yyMinI, xxMaxI, yyMaxI, y, n; + Guchar *p; + + maskBitmap = maskSplash->getBitmap(); + xxMin = maskBitmap->getWidth(); + xxMax = 0; + yyMin = maskBitmap->getHeight(); + yyMax = 0; + state->transform(xMin, yMin, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + state->transform(xMin, yMax, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + state->transform(xMax, yMin, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + state->transform(xMax, yMax, &xx, &yy); + if (xx < xxMin) { xxMin = xx; } + if (xx > xxMax) { xxMax = xx; } + if (yy < yyMin) { yyMin = yy; } + if (yy > yyMax) { yyMax = yy; } + xxMinI = (int)floor(xxMin); + if (xxMinI < 0) { + xxMinI = 0; + } + xxMaxI = (int)ceil(xxMax); + if (xxMaxI > maskBitmap->getWidth()) { + xxMaxI = maskBitmap->getWidth(); + } + yyMinI = (int)floor(yyMin); + if (yyMinI < 0) { + yyMinI = 0; + } + yyMaxI = (int)ceil(yyMax); + if (yyMaxI > maskBitmap->getHeight()) { + yyMaxI = maskBitmap->getHeight(); + } + p = maskBitmap->getDataPtr() + yyMinI * maskBitmap->getRowSize(); + if (maskBitmap->getMode() == splashModeMono1) { + n = (xxMaxI + 7) / 8 - xxMinI / 8; + p += xxMinI / 8; + } else { + n = xxMaxI - xxMinI; + p += xxMinI; + } + if (xxMaxI > xxMinI) { + for (y = yyMinI; y < yyMaxI; ++y) { + memset(p, 0, n); + p += maskBitmap->getRowSize(); + } + } +} + void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout, @@ -2921,7 +3173,7 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, //~ not yet for transparency groups // switch to the blending color space - if (forSoftMask && isolated && blendingColorSpace) { + if (forSoftMask && isolated && !knockout && blendingColorSpace) { if (blendingColorSpace->getMode() == csDeviceGray || blendingColorSpace->getMode() == csCalGray || (blendingColorSpace->getMode() == csICCBased && @@ -2948,6 +3200,7 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, splash = new Splash(bitmap, vectorAntialias, transpGroup->origSplash->getScreen()); splash->setMinLineWidth(globalParams->getMinLineWidth()); + splash->setStrokeAdjust(globalParams->getStrokeAdjust()); //~ Acrobat apparently copies at least the fill and stroke colors, and //~ maybe other state(?) -- but not the clipping path (and not sure //~ what else) @@ -2962,8 +3215,9 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, splash->clear(color, 0); } else { splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h); - splash->setInNonIsolatedGroup(transpGroup->origBitmap, tx, ty); } + splash->setInTransparencyGroup(transpGroup->origBitmap, tx, ty, + !isolated, knockout); transpGroup->tBitmap = bitmap; state->shiftCTM(-tx, -ty); updateCTM(state, 0, 0, 0, 0, 0, 0); @@ -3022,7 +3276,7 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, #if SPLASH_CMYK GfxCMYK cmyk; #endif - double lum, lum2; + double backdrop, backdrop2, lum, lum2; int tx, ty, x, y; tx = transpGroupStack->tx; @@ -3030,11 +3284,13 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, tBitmap = transpGroupStack->tBitmap; // composite with backdrop color + backdrop = 0; if (!alpha && tBitmap->getMode() != splashModeMono1) { //~ need to correctly handle the case where no blending color //~ space is given tSplash = new Splash(tBitmap, vectorAntialias, transpGroupStack->origSplash->getScreen()); + tSplash->setStrokeAdjust(globalParams->getStrokeAdjust()); if (transpGroupStack->blendingColorSpace) { switch (tBitmap->getMode()) { case splashModeMono1: @@ -3042,12 +3298,16 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, break; case splashModeMono8: transpGroupStack->blendingColorSpace->getGray(backdropColor, &gray); + backdrop = colToDbl(gray); color[0] = colToByte(gray); tSplash->compositeBackground(color); break; case splashModeRGB8: case splashModeBGR8: transpGroupStack->blendingColorSpace->getRGB(backdropColor, &rgb); + backdrop = 0.3 * colToDbl(rgb.r) + + 0.59 * colToDbl(rgb.g) + + 0.11 * colToDbl(rgb.b); color[0] = colToByte(rgb.r); color[1] = colToByte(rgb.g); color[2] = colToByte(rgb.b); @@ -3056,6 +3316,13 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, #if SPLASH_CMYK case splashModeCMYK8: transpGroupStack->blendingColorSpace->getCMYK(backdropColor, &cmyk); + backdrop = (1 - colToDbl(cmyk.k)) + - 0.3 * colToDbl(cmyk.c) + - 0.59 * colToDbl(cmyk.m) + - 0.11 * colToDbl(cmyk.y); + if (backdrop < 0) { + backdrop = 0; + } color[0] = colToByte(cmyk.c); color[1] = colToByte(cmyk.m); color[2] = colToByte(cmyk.y); @@ -3067,10 +3334,15 @@ void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, delete tSplash; } } + if (transferFunc) { + transferFunc->transform(&backdrop, &backdrop2); + } else { + backdrop2 = backdrop; + } softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), 1, splashModeMono8, gFalse); - memset(softMask->getDataPtr(), 0, + memset(softMask->getDataPtr(), (int)(backdrop2 * 255.0 + 0.5), softMask->getRowSize() * softMask->getHeight()); if (tx < softMask->getWidth() && ty < softMask->getHeight()) { p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx; @@ -3198,12 +3470,19 @@ SplashFont *SplashOutputDev::getFont(GString *name, SplashCoord *textMatA) { Ref ref; SplashOutFontFileID *id; GfxFontLoc *fontLoc; +#if LOAD_FONTS_FROM_MEM + GString *fontBuf; + FILE *extFontFile; + char blk[4096]; + int n; +#endif SplashFontFile *fontFile; SplashFont *fontObj; FoFiTrueType *ff; int *codeToGID; Unicode u; SplashCoord textMat[4]; + SplashCoord oblique; int cmap, i; for (i = 0; i < nBuiltinFonts; ++i) { @@ -3227,11 +3506,40 @@ SplashFont *SplashOutputDev::getFont(GString *name, SplashCoord *textMatA) { if (!(fontLoc = GfxFont::locateBase14Font(name))) { return NULL; } +#if LOAD_FONTS_FROM_MEM + fontBuf = NULL; + if (fontLoc->fontType == fontType1 || + fontLoc->fontType == fontTrueType) { + if (!(extFontFile = fopen(fontLoc->path->getCString(), "rb"))) { + delete fontLoc; + delete id; + return NULL; + } + fontBuf = new GString(); + while ((n = fread(blk, 1, sizeof(blk), extFontFile)) > 0) { + fontBuf->append(blk, n); + } + fclose(extFontFile); + } +#endif if (fontLoc->fontType == fontType1) { - fontFile = fontEngine->loadType1Font(id, fontLoc->path->getCString(), - gFalse, winAnsiEncoding); + fontFile = fontEngine->loadType1Font(id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else + fontLoc->path->getCString(), + gFalse, +#endif + winAnsiEncoding); } else if (fontLoc->fontType == fontTrueType) { - if (!(ff = FoFiTrueType::load(fontLoc->path->getCString()))) { +#if LOAD_FONTS_FROM_MEM + if (!(ff = FoFiTrueType::make(fontBuf->getCString(), + fontBuf->getLength(), + fontLoc->fontNum))) { +#else + if (!(ff = FoFiTrueType::load(fontLoc->path->getCString(), + fontLoc->fontNum))) { +#endif delete fontLoc; delete id; return NULL; @@ -3259,9 +3567,14 @@ SplashFont *SplashOutputDev::getFont(GString *name, SplashCoord *textMatA) { } delete ff; fontFile = fontEngine->loadTrueTypeFont(id, +#if LOAD_FONTS_FROM_MEM + fontBuf, +#else fontLoc->path->getCString(), + gFalse, +#endif fontLoc->fontNum, - gFalse, codeToGID, 256, NULL); + codeToGID, 256, NULL); } else { delete fontLoc; delete id; @@ -3274,10 +3587,12 @@ SplashFont *SplashOutputDev::getFont(GString *name, SplashCoord *textMatA) { } // create the scaled font + oblique = (SplashCoord) + ((SplashOutFontFileID *)fontFile->getID())->getOblique(); textMat[0] = (SplashCoord)textMatA[0]; textMat[1] = (SplashCoord)textMatA[1]; - textMat[2] = (SplashCoord)textMatA[2]; - textMat[3] = (SplashCoord)textMatA[3]; + textMat[2] = oblique * textMatA[0] + textMatA[2]; + textMat[3] = oblique * textMatA[1] + textMatA[3]; fontObj = fontEngine->getFont(fontFile, textMat, splash->getMatrix()); return fontObj; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SplashOutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SplashOutputDev.h index c48b786402a..ebbf8a1bb4e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/SplashOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/SplashOutputDev.h @@ -110,7 +110,7 @@ public: virtual void stroke(GfxState *state); virtual void fill(GfxState *state); virtual void eoFill(GfxState *state); - virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, @@ -135,25 +135,26 @@ public: //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, - GBool inlineImg); + GBool inlineImg, GBool interpolate); virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); + int *maskColors, GBool inlineImg, GBool interpolate); virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); + GBool maskInvert, GBool interpolate); virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, Stream *maskStr, int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap); + GfxImageColorMap *maskColorMap, + GBool interpolate); //----- Type 3 font operators virtual void type3D0(GfxState *state, double wx, double wy); @@ -194,6 +195,10 @@ public: // for Windows BMP files). void setBitmapUpsideDown(GBool f) { bitmapUpsideDown = f; } + // Setting this to true disables the final composite (with the + // opaque paper color), resulting in transparent output. + void setNoComposite(GBool f) { noComposite = f; } + // Get the Splash object. Splash *getSplash() { return splash; } @@ -245,11 +250,18 @@ private: Guchar *alphaLine); static GBool maskedImageSrc(void *data, SplashColorPtr line, Guchar *alphaLine); + void reduceImageResolution(Stream *str, double *mat, + int *width, int *height); + void clearMaskRegion(GfxState *state, + Splash *maskSplash, + double xMin, double yMin, + double xMax, double yMax); SplashColorMode colorMode; int bitmapRowPad; GBool bitmapTopDown; GBool bitmapUpsideDown; + GBool noComposite; GBool allowAntialias; GBool vectorAntialias; GBool reverseVideo; // reverse video mode @@ -268,7 +280,6 @@ private: t3FontCache[splashOutT3FontCacheSize]; int nT3Fonts; // number of valid entries in t3FontCache T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack - GBool haveT3Dx; // set after seeing a d0/d1 operator SplashFont *font; // current font GBool needFontUpdate; // set when the font needs to be updated diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream-CCITT.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream-CCITT.h index f82150a79c0..f82150a79c0 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream-CCITT.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream-CCITT.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream.cc index d91b9419bba..71029669e1f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream.cc @@ -16,7 +16,7 @@ #include <stdlib.h> #include <stddef.h> #include <limits.h> -#ifndef WIN32 +#ifndef _WIN32 #include <unistd.h> #endif #include <string.h> @@ -98,11 +98,29 @@ char *Stream::getLine(char *buf, int size) { return buf; } +Guint Stream::discardChars(Guint n) { + char buf[4096]; + Guint count, i, j; + + count = 0; + while (count < n) { + if ((i = n - count) > sizeof(buf)) { + i = (Guint)sizeof(buf); + } + j = (Guint)getBlock(buf, (int)i); + count += j; + if (j != i) { + break; + } + } + return count; +} + GString *Stream::getPSFilter(int psLevel, const char *indent) { return new GString(); } -Stream *Stream::addFilters(Object *dict) { +Stream *Stream::addFilters(Object *dict, int recursion) { Object obj, obj2; Object params, params2; Stream *str; @@ -120,7 +138,7 @@ Stream *Stream::addFilters(Object *dict) { dict->dictLookup("DP", ¶ms); } if (obj.isName()) { - str = makeFilter(obj.getName(), str, ¶ms); + str = makeFilter(obj.getName(), str, ¶ms, recursion); } else if (obj.isArray()) { for (i = 0; i < obj.arrayGetLength(); ++i) { obj.arrayGet(i, &obj2); @@ -129,7 +147,7 @@ Stream *Stream::addFilters(Object *dict) { else params2.initNull(); if (obj2.isName()) { - str = makeFilter(obj2.getName(), str, ¶ms2); + str = makeFilter(obj2.getName(), str, ¶ms2, recursion); } else { error(errSyntaxError, getPos(), "Bad filter name"); str = new EOFStream(str); @@ -146,7 +164,8 @@ Stream *Stream::addFilters(Object *dict) { return str; } -Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { +Stream *Stream::makeFilter(char *name, Stream *str, Object *params, + int recursion) { int pred; // parameters int colors; int bits; @@ -168,23 +187,23 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { bits = 8; early = 1; if (params->isDict()) { - params->dictLookup("Predictor", &obj); + params->dictLookup("Predictor", &obj, recursion); if (obj.isInt()) pred = obj.getInt(); obj.free(); - params->dictLookup("Columns", &obj); + params->dictLookup("Columns", &obj, recursion); if (obj.isInt()) columns = obj.getInt(); obj.free(); - params->dictLookup("Colors", &obj); + params->dictLookup("Colors", &obj, recursion); if (obj.isInt()) colors = obj.getInt(); obj.free(); - params->dictLookup("BitsPerComponent", &obj); + params->dictLookup("BitsPerComponent", &obj, recursion); if (obj.isInt()) bits = obj.getInt(); obj.free(); - params->dictLookup("EarlyChange", &obj); + params->dictLookup("EarlyChange", &obj, recursion); if (obj.isInt()) early = obj.getInt(); obj.free(); @@ -201,37 +220,37 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { endOfBlock = gTrue; black = gFalse; if (params->isDict()) { - params->dictLookup("K", &obj); + params->dictLookup("K", &obj, recursion); if (obj.isInt()) { encoding = obj.getInt(); } obj.free(); - params->dictLookup("EndOfLine", &obj); + params->dictLookup("EndOfLine", &obj, recursion); if (obj.isBool()) { endOfLine = obj.getBool(); } obj.free(); - params->dictLookup("EncodedByteAlign", &obj); + params->dictLookup("EncodedByteAlign", &obj, recursion); if (obj.isBool()) { byteAlign = obj.getBool(); } obj.free(); - params->dictLookup("Columns", &obj); + params->dictLookup("Columns", &obj, recursion); if (obj.isInt()) { columns = obj.getInt(); } obj.free(); - params->dictLookup("Rows", &obj); + params->dictLookup("Rows", &obj, recursion); if (obj.isInt()) { rows = obj.getInt(); } obj.free(); - params->dictLookup("EndOfBlock", &obj); + params->dictLookup("EndOfBlock", &obj, recursion); if (obj.isBool()) { endOfBlock = obj.getBool(); } obj.free(); - params->dictLookup("BlackIs1", &obj); + params->dictLookup("BlackIs1", &obj, recursion); if (obj.isBool()) { black = obj.getBool(); } @@ -242,7 +261,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) { colorXform = -1; if (params->isDict()) { - if (params->dictLookup("ColorTransform", &obj)->isInt()) { + if (params->dictLookup("ColorTransform", &obj, recursion)->isInt()) { colorXform = obj.getInt(); } obj.free(); @@ -254,19 +273,19 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { colors = 1; bits = 8; if (params->isDict()) { - params->dictLookup("Predictor", &obj); + params->dictLookup("Predictor", &obj, recursion); if (obj.isInt()) pred = obj.getInt(); obj.free(); - params->dictLookup("Columns", &obj); + params->dictLookup("Columns", &obj, recursion); if (obj.isInt()) columns = obj.getInt(); obj.free(); - params->dictLookup("Colors", &obj); + params->dictLookup("Colors", &obj, recursion); if (obj.isInt()) colors = obj.getInt(); obj.free(); - params->dictLookup("BitsPerComponent", &obj); + params->dictLookup("BitsPerComponent", &obj, recursion); if (obj.isInt()) bits = obj.getInt(); obj.free(); @@ -274,7 +293,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { str = new FlateStream(str, pred, columns, colors, bits); } else if (!strcmp(name, "JBIG2Decode")) { if (params->isDict()) { - params->dictLookup("JBIG2Globals", &globals); + params->dictLookup("JBIG2Globals", &globals, recursion); } str = new JBIG2Stream(str, &globals); globals.free(); @@ -314,7 +333,7 @@ void FilterStream::close() { str->close(); } -void FilterStream::setPos(Guint pos, int dir) { +void FilterStream::setPos(GFileOffset pos, int dir) { error(errInternal, -1, "Called setPos() on FilterStream"); } @@ -365,6 +384,10 @@ void ImageStream::reset() { str->reset(); } +void ImageStream::close() { + str->close(); +} + GBool ImageStream::getPixel(Guchar *pix) { int i; @@ -405,6 +428,10 @@ Guchar *ImageStream::getLine() { } } else if (nBits == 8) { // special case: imgLine == inputLine + } else if (nBits == 16) { + for (i = 0; i < nVals; ++i) { + imgLine[i] = (Guchar)inputLine[2*i]; + } } else { bitMask = (1 << nBits) - 1; buf = 0; @@ -451,8 +478,8 @@ StreamPredictor::StreamPredictor(Stream *strA, int predictorA, return; } predLine = (Guchar *)gmalloc(rowBytes); - memset(predLine, 0, rowBytes); - predIdx = rowBytes; + + reset(); ok = gTrue; } @@ -461,6 +488,11 @@ StreamPredictor::~StreamPredictor() { gfree(predLine); } +void StreamPredictor::reset() { + memset(predLine, 0, rowBytes); + predIdx = rowBytes; +} + int StreamPredictor::lookChar() { if (predIdx >= rowBytes) { if (!getNextLine()) { @@ -573,19 +605,19 @@ GBool StreamPredictor::getNextLine() { // apply TIFF (component) predictor if (predictor == 2) { - if (nBits == 1) { - inBuf = predLine[pixBytes - 1]; - for (i = pixBytes; i < rowBytes; i += 8) { - // 1-bit add is just xor - inBuf = (inBuf << 8) | predLine[i]; - predLine[i] ^= inBuf >> nComps; - } - } else if (nBits == 8) { + if (nBits == 8) { for (i = pixBytes; i < rowBytes; ++i) { predLine[i] += predLine[i - nComps]; } + } else if (nBits == 16) { + for (i = pixBytes; i < rowBytes; i += 2) { + c = ((predLine[i] + predLine[i - 2*nComps]) << 8) + + predLine[i + 1] + predLine[i + 1 - 2*nComps]; + predLine[i] = (Guchar)(c >> 8); + predLine[i+1] = (Guchar)(c & 0xff); + } } else { - memset(upLeftBuf, 0, nComps + 1); + memset(upLeftBuf, 0, nComps); bitMask = (1 << nBits) - 1; inBuf = outBuf = 0; inBits = outBits = 0; @@ -624,8 +656,8 @@ GBool StreamPredictor::getNextLine() { // FileStream //------------------------------------------------------------------------ -FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, - Guint lengthA, Object *dictA): +FileStream::FileStream(FILE *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA): BaseStream(dictA) { f = fA; start = startA; @@ -641,22 +673,14 @@ FileStream::~FileStream() { close(); } -Stream *FileStream::makeSubStream(Guint startA, GBool limitedA, - Guint lengthA, Object *dictA) { +Stream *FileStream::makeSubStream(GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA) { return new FileStream(f, startA, limitedA, lengthA, dictA); } void FileStream::reset() { -#if HAVE_FSEEKO - savePos = (Guint)ftello(f); - fseeko(f, start, SEEK_SET); -#elif HAVE_FSEEK64 - savePos = (Guint)ftell64(f); - fseek64(f, start, SEEK_SET); -#else - savePos = (Guint)ftell(f); - fseek(f, start, SEEK_SET); -#endif + savePos = gftell(f); + gfseek(f, start, SEEK_SET); saved = gTrue; bufPtr = bufEnd = buf; bufPos = start; @@ -664,13 +688,7 @@ void FileStream::reset() { void FileStream::close() { if (saved) { -#if HAVE_FSEEKO - fseeko(f, savePos, SEEK_SET); -#elif HAVE_FSEEK64 - fseek64(f, savePos, SEEK_SET); -#else - fseek(f, savePos, SEEK_SET); -#endif + gfseek(f, savePos, SEEK_SET); saved = gFalse; } } @@ -705,7 +723,7 @@ GBool FileStream::fillBuf() { return gFalse; } if (limited && bufPos + fileStreamBufSize > start + length) { - n = start + length - bufPos; + n = (int)(start + length - bufPos); } else { n = fileStreamBufSize; } @@ -717,41 +735,20 @@ GBool FileStream::fillBuf() { return gTrue; } -void FileStream::setPos(Guint pos, int dir) { - Guint size; +void FileStream::setPos(GFileOffset pos, int dir) { + GFileOffset size; if (dir >= 0) { -#if HAVE_FSEEKO - fseeko(f, pos, SEEK_SET); -#elif HAVE_FSEEK64 - fseek64(f, pos, SEEK_SET); -#else - fseek(f, pos, SEEK_SET); -#endif + gfseek(f, pos, SEEK_SET); bufPos = pos; } else { -#if HAVE_FSEEKO - fseeko(f, 0, SEEK_END); - size = (Guint)ftello(f); -#elif HAVE_FSEEK64 - fseek64(f, 0, SEEK_END); - size = (Guint)ftell64(f); -#else - fseek(f, 0, SEEK_END); - size = (Guint)ftell(f); -#endif - if (pos > size) - pos = (Guint)size; -#if HAVE_FSEEKO - fseeko(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftello(f); -#elif HAVE_FSEEK64 - fseek64(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftell64(f); -#else - fseek(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftell(f); -#endif + gfseek(f, 0, SEEK_END); + size = gftell(f); + if (pos > size) { + pos = size; + } + gfseek(f, -pos, SEEK_END); + bufPos = gftell(f); } bufPtr = bufEnd = buf; } @@ -782,17 +779,24 @@ MemStream::~MemStream() { } } -Stream *MemStream::makeSubStream(Guint startA, GBool limited, - Guint lengthA, Object *dictA) { +Stream *MemStream::makeSubStream(GFileOffset startA, GBool limited, + GFileOffset lengthA, Object *dictA) { MemStream *subStr; - Guint newLength; + Guint newStart, newLength; - if (!limited || startA + lengthA > start + length) { - newLength = start + length - startA; + if (startA < start) { + newStart = start; + } else if (startA > start + length) { + newStart = start + (int)length; + } else { + newStart = (int)startA; + } + if (!limited || newStart + lengthA > start + length) { + newLength = start + length - newStart; } else { - newLength = lengthA; + newLength = (Guint)lengthA; } - subStr = new MemStream(buf, startA, newLength, dictA); + subStr = new MemStream(buf, newStart, newLength, dictA); return subStr; } @@ -819,13 +823,13 @@ int MemStream::getBlock(char *blk, int size) { return n; } -void MemStream::setPos(Guint pos, int dir) { +void MemStream::setPos(GFileOffset pos, int dir) { Guint i; if (dir >= 0) { - i = pos; + i = (Guint)pos; } else { - i = start + length - pos; + i = (Guint)(start + length - pos); } if (i < start) { i = start; @@ -846,7 +850,7 @@ void MemStream::moveStart(int delta) { //------------------------------------------------------------------------ EmbedStream::EmbedStream(Stream *strA, Object *dictA, - GBool limitedA, Guint lengthA): + GBool limitedA, GFileOffset lengthA): BaseStream(dictA) { str = strA; limited = limitedA; @@ -856,8 +860,8 @@ EmbedStream::EmbedStream(Stream *strA, Object *dictA, EmbedStream::~EmbedStream() { } -Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA, - Guint lengthA, Object *dictA) { +Stream *EmbedStream::makeSubStream(GFileOffset start, GBool limitedA, + GFileOffset lengthA, Object *dictA) { error(errInternal, -1, "Called makeSubStream() on EmbedStream"); return NULL; } @@ -887,11 +891,11 @@ int EmbedStream::getBlock(char *blk, int size) { return str->getBlock(blk, size); } -void EmbedStream::setPos(Guint pos, int dir) { +void EmbedStream::setPos(GFileOffset pos, int dir) { error(errInternal, -1, "Called setPos() on EmbedStream"); } -Guint EmbedStream::getStart() { +GFileOffset EmbedStream::getStart() { error(errInternal, -1, "Called getStart() on EmbedStream"); return 0; } @@ -1173,6 +1177,9 @@ int LZWStream::getBlock(char *blk, int size) { void LZWStream::reset() { str->reset(); + if (pred) { + pred->reset(); + } eof = gFalse; inputBits = 0; clearTable(); @@ -2068,14 +2075,16 @@ GBool CCITTFaxStream::isBinary(GBool last) { //------------------------------------------------------------------------ // IDCT constants (20.12 fixed point format) -#define dctCos1 4017 // cos(pi/16) -#define dctSin1 799 // sin(pi/16) -#define dctCos3 3406 // cos(3*pi/16) -#define dctSin3 2276 // sin(3*pi/16) -#define dctCos6 1567 // cos(6*pi/16) -#define dctSin6 3784 // sin(6*pi/16) -#define dctSqrt2 5793 // sqrt(2) -#define dctSqrt1d2 2896 // sqrt(2) / 2 +#define dctSqrt2 5793 // sqrt(2) +#define dctSqrt2Cos6 2217 // sqrt(2) * cos(6*pi/16) +#define dctSqrt2Cos6PSin6 7568 // sqrt(2) * (cos(6*pi/16) + sin(6*pi/16)) +#define dctSqrt2Sin6MCos6 3135 // sqrt(2) * (sin(6*pi/16) - cos(6*pi/16)) +#define dctCos3 3406 // cos(3*pi/16) +#define dctCos3PSin3 5681 // cos(3*pi/16) + sin(3*pi/16) +#define dctSin3MCos3 -1130 // sin(3*pi/16) - cos(3*pi/16) +#define dctCos1 4017 // cos(pi/16) +#define dctCos1PSin1 4816 // cos(pi/16) + sin(pi/16) +#define dctSin1MCos1 -3218 // sin(pi/16) - cos(pi/16) // color conversion parameters (16.16 fixed point format) #define dctCrToR 91881 // 1.4020 @@ -2083,10 +2092,47 @@ GBool CCITTFaxStream::isBinary(GBool last) { #define dctCrToG -46802 // -0.71413636 #define dctCbToB 116130 // 1.772 -// clip [-256,511] --> [0,255] -#define dctClipOffset 256 -static Guchar dctClip[768]; -static int dctClipInit = 0; +// The dctClip function clips signed integers to the [0,255] range. +// To handle valid DCT inputs, this must support an input range of at +// least [-256,511]. Invalid DCT inputs (e.g., from damaged PDF +// files) can result in arbitrary values, so we want to mask those +// out. We round the input range size up to a power of 2 (so we can +// use a bit mask), which gives us an input range of [-384,639]. The +// end result is: +// input output +// ---------- ------ +// <-384 X invalid inputs -> output is "don't care" +// -384..-257 0 invalid inputs, clipped +// -256..-1 0 valid inputs, need to be clipped +// 0..255 0..255 +// 256..511 255 valid inputs, need to be clipped +// 512..639 255 invalid inputs, clipped +// >=512 X invalid inputs -> output is "don't care" + +#define dctClipOffset 384 +#define dctClipMask 1023 +static Guchar dctClipData[1024]; + +static inline void dctClipInit() { + static int initDone = 0; + int i; + if (!initDone) { + for (i = -384; i < 0; ++i) { + dctClipData[dctClipOffset + i] = 0; + } + for (i = 0; i < 256; ++i) { + dctClipData[dctClipOffset + i] = i; + } + for (i = 256; i < 639; ++i) { + dctClipData[dctClipOffset + i] = 255; + } + initDone = 1; + } +} + +static inline int dctClip(int x) { + return dctClipData[(dctClipOffset + x) & dctClipMask]; +} // zig zag decode map static int dctZigZag[64] = { @@ -2109,7 +2155,7 @@ static int dctZigZag[64] = { DCTStream::DCTStream(Stream *strA, GBool colorXformA): FilterStream(strA) { - int i, j; + int i; colorXform = colorXformA; progressive = interleaved = gFalse; @@ -2117,23 +2163,15 @@ DCTStream::DCTStream(Stream *strA, GBool colorXformA): mcuWidth = mcuHeight = 0; numComps = 0; comp = 0; - x = y = dy = 0; + x = y = 0; for (i = 0; i < 4; ++i) { - for (j = 0; j < 32; ++j) { - rowBuf[i][j] = NULL; - } frameBuf[i] = NULL; } + rowBuf = NULL; + memset(dcHuffTables, 0, sizeof(dcHuffTables)); + memset(acHuffTables, 0, sizeof(acHuffTables)); - if (!dctClipInit) { - for (i = -256; i < 0; ++i) - dctClip[dctClipOffset + i] = 0; - for (i = 0; i < 256; ++i) - dctClip[dctClipOffset + i] = i; - for (i = 256; i < 512; ++i) - dctClip[dctClipOffset + i] = 255; - dctClipInit = 1; - } + dctClipInit(); } DCTStream::~DCTStream() { @@ -2142,7 +2180,7 @@ DCTStream::~DCTStream() { } void DCTStream::reset() { - int i, j; + int i; str->reset(); @@ -2157,6 +2195,8 @@ void DCTStream::reset() { restartInterval = 0; if (!readHeader()) { + // force an EOF condition + progressive = gTrue; y = height; return; } @@ -2229,17 +2269,11 @@ void DCTStream::reset() { // allocate a buffer for one row of MCUs bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - for (i = 0; i < numComps; ++i) { - for (j = 0; j < mcuHeight; ++j) { - rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar)); - } - } + rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); + rowBufPtr = rowBufEnd = rowBuf; // initialize counters - comp = 0; - x = 0; - y = 0; - dy = mcuHeight; + y = -mcuHeight; restartMarker = 0xd0; restart(); @@ -2247,26 +2281,24 @@ void DCTStream::reset() { } void DCTStream::close() { - int i, j; + int i; for (i = 0; i < 4; ++i) { - for (j = 0; j < 32; ++j) { - gfree(rowBuf[i][j]); - rowBuf[i][j] = NULL; - } gfree(frameBuf[i]); frameBuf[i] = NULL; } + gfree(rowBuf); + rowBuf = NULL; FilterStream::close(); } int DCTStream::getChar() { int c; - if (y >= height) { - return EOF; - } if (progressive || !interleaved) { + if (y >= height) { + return EOF; + } c = frameBuf[comp][y * bufWidth + x]; if (++comp == numComps) { comp = 0; @@ -2276,48 +2308,38 @@ int DCTStream::getChar() { } } } else { - if (dy >= mcuHeight) { + if (rowBufPtr == rowBufEnd) { + if (y + mcuHeight >= height) { + return EOF; + } + y += mcuHeight; if (!readMCURow()) { y = height; return EOF; } - comp = 0; - x = 0; - dy = 0; - } - c = rowBuf[comp][dy][x]; - if (++comp == numComps) { - comp = 0; - if (++x == width) { - x = 0; - ++y; - ++dy; - if (y == height) { - readTrailer(); - } - } } + c = *rowBufPtr++; } return c; } int DCTStream::lookChar() { - if (y >= height) { - return EOF; - } if (progressive || !interleaved) { + if (y >= height) { + return EOF; + } return frameBuf[comp][y * bufWidth + x]; } else { - if (dy >= mcuHeight) { + if (rowBufPtr == rowBufEnd) { + if (y + mcuHeight >= height) { + return EOF; + } if (!readMCURow()) { y = height; return EOF; } - comp = 0; - x = 0; - dy = 0; } - return rowBuf[comp][dy][x]; + return *rowBufPtr; } } @@ -2375,38 +2397,49 @@ GBool DCTStream::readMCURow() { } transformDataUnit(quantTables[compInfo[cc].quantTable], data1, data2); - if (hSub == 1 && vSub == 1) { + if (hSub == 1 && vSub == 1 && x1+x2+8 <= width) { for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - p1 = &rowBuf[cc][y2+y3][x1+x2]; - p1[0] = data2[i]; - p1[1] = data2[i+1]; - p1[2] = data2[i+2]; - p1[3] = data2[i+3]; - p1[4] = data2[i+4]; - p1[5] = data2[i+5]; - p1[6] = data2[i+6]; - p1[7] = data2[i+7]; + p1 = &rowBuf[((y2+y3) * width + (x1+x2)) * numComps + cc]; + p1[0] = data2[i]; + p1[ numComps] = data2[i+1]; + p1[2*numComps] = data2[i+2]; + p1[3*numComps] = data2[i+3]; + p1[4*numComps] = data2[i+4]; + p1[5*numComps] = data2[i+5]; + p1[6*numComps] = data2[i+6]; + p1[7*numComps] = data2[i+7]; } - } else if (hSub == 2 && vSub == 2) { + } else if (hSub == 2 && vSub == 2 && x1+x2+16 <= width) { for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { - p1 = &rowBuf[cc][y2+y3][x1+x2]; - p2 = &rowBuf[cc][y2+y3+1][x1+x2]; - p1[0] = p1[1] = p2[0] = p2[1] = data2[i]; - p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1]; - p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2]; - p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3]; - p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4]; - p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5]; - p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6]; - p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7]; + p1 = &rowBuf[((y2+y3) * width + (x1+x2)) * numComps + cc]; + p2 = p1 + width * numComps; + p1[0] = p1[numComps] = + p2[0] = p2[numComps] = data2[i]; + p1[2*numComps] = p1[3*numComps] = + p2[2*numComps] = p2[3*numComps] = data2[i+1]; + p1[4*numComps] = p1[5*numComps] = + p2[4*numComps] = p2[5*numComps] = data2[i+2]; + p1[6*numComps] = p1[7*numComps] = + p2[6*numComps] = p2[7*numComps] = data2[i+3]; + p1[8*numComps] = p1[9*numComps] = + p2[8*numComps] = p2[9*numComps] = data2[i+4]; + p1[10*numComps] = p1[11*numComps] = + p2[10*numComps] = p2[11*numComps] = data2[i+5]; + p1[12*numComps] = p1[13*numComps] = + p2[12*numComps] = p2[13*numComps] = data2[i+6]; + p1[14*numComps] = p1[15*numComps] = + p2[14*numComps] = p2[15*numComps] = data2[i+7]; } } else { + p1 = &rowBuf[(y2 * width + (x1+x2)) * numComps + cc]; i = 0; for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { - for (y5 = 0; y5 < vSub; ++y5) - for (x5 = 0; x5 < hSub; ++x5) - rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i]; + for (y5 = 0; y5 < vSub; ++y5) { + for (x5 = 0; x5 < hSub && x1+x2+x4+x5 < width; ++x5) { + p1[((y4+y5) * width + (x4+x5)) * numComps] = data2[i]; + } + } ++i; } } @@ -2415,42 +2448,46 @@ GBool DCTStream::readMCURow() { } } --restartCtr; + } - // color space conversion - if (colorXform) { - // convert YCbCr to RGB - if (numComps == 3) { - for (y2 = 0; y2 < mcuHeight; ++y2) { - for (x2 = 0; x2 < mcuWidth; ++x2) { - pY = rowBuf[0][y2][x1+x2]; - pCb = rowBuf[1][y2][x1+x2] - 128; - pCr = rowBuf[2][y2][x1+x2] - 128; - pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; - rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB]; - } - } - // convert YCbCrK to CMYK (K is passed through unchanged) - } else if (numComps == 4) { - for (y2 = 0; y2 < mcuHeight; ++y2) { - for (x2 = 0; x2 < mcuWidth; ++x2) { - pY = rowBuf[0][y2][x1+x2]; - pCb = rowBuf[1][y2][x1+x2] - 128; - pCr = rowBuf[2][y2][x1+x2] - 128; - pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; - rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB]; - } - } + // color space conversion + if (colorXform) { + // convert YCbCr to RGB + if (numComps == 3) { + for (i = 0, p1 = rowBuf; i < width * mcuHeight; ++i, p1 += 3) { + pY = p1[0]; + pCb = p1[1] - 128; + pCr = p1[2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + p1[0] = dctClip(pR); + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + p1[1] = dctClip(pG); + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + p1[2] = dctClip(pB); + } + // convert YCbCrK to CMYK (K is passed through unchanged) + } else if (numComps == 4) { + for (i = 0, p1 = rowBuf; i < width * mcuHeight; ++i, p1 += 4) { + pY = p1[0]; + pCb = p1[1] - 128; + pCr = p1[2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + p1[0] = 255 - dctClip(pR); + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + p1[1] = 255 - dctClip(pG); + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + p1[2] = 255 - dctClip(pB); } } } + + rowBufPtr = rowBuf; + if (y + mcuHeight <= height) { + rowBufEnd = rowBuf + numComps * width * mcuHeight; + } else { + rowBufEnd = rowBuf + numComps * width * (height - y); + } + return gTrue; } @@ -2609,7 +2646,7 @@ GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, return gTrue; } -// Read one data unit from a sequential JPEG stream. +// Read one data unit from a progressive JPEG stream. GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64]) { @@ -2635,7 +2672,13 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, if ((bit = readBit()) == 9999) { return gFalse; } - data[0] += bit << scanInfo.al; + if (bit) { + if (data[0] >= 0) { + data[0] += 1 << scanInfo.al; + } else { + data[0] -= 1 << scanInfo.al; + } + } } ++i; } @@ -2652,7 +2695,11 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, return gFalse; } if (bit) { - data[j] += 1 << scanInfo.al; + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } } } } @@ -2678,7 +2725,11 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, return gFalse; } if (bit) { - data[j] += 1 << scanInfo.al; + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } } } } @@ -2701,7 +2752,11 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, return gFalse; } if (bit) { - data[j] += 1 << scanInfo.al; + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } } } } @@ -2723,7 +2778,11 @@ GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, return gFalse; } if (bit) { - data[j] += 1 << scanInfo.al; + if (data[j] >= 0) { + data[j] += 1 << scanInfo.al; + } else { + data[j] -= 1 << scanInfo.al; + } } j = dctZigZag[i++]; } @@ -2837,12 +2896,12 @@ void DCTStream::decodeImage() { pCb = *p1 - 128; pCr = *p2 - 128; pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - *p0++ = dctClip[dctClipOffset + pR]; + *p0++ = dctClip(pR); pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; - *p1++ = dctClip[dctClipOffset + pG]; + *p1++ = dctClip(pG); pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - *p2++ = dctClip[dctClipOffset + pB]; + *p2++ = dctClip(pB); } } // convert YCbCrK to CMYK (K is passed through unchanged) @@ -2856,12 +2915,12 @@ void DCTStream::decodeImage() { pCb = *p1 - 128; pCr = *p2 - 128; pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - *p0++ = 255 - dctClip[dctClipOffset + pR]; + *p0++ = 255 - dctClip(pR); pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; - *p1++ = 255 - dctClip[dctClipOffset + pG]; + *p1++ = 255 - dctClip(pG); pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - *p2++ = 255 - dctClip[dctClipOffset + pB]; + *p2++ = 255 - dctClip(pB); } } } @@ -2880,71 +2939,76 @@ void DCTStream::decodeImage() { // paper. void DCTStream::transformDataUnit(Gushort *quantTable, int dataIn[64], Guchar dataOut[64]) { - int v0, v1, v2, v3, v4, v5, v6, v7, t; + int v0, v1, v2, v3, v4, v5, v6, v7, t0, t1, t2; int *p; + Gushort *q; int i; - // dequant - for (i = 0; i < 64; ++i) { - dataIn[i] *= quantTable[i]; - } - - // inverse DCT on rows + // dequant; inverse DCT on rows for (i = 0; i < 64; i += 8) { p = dataIn + i; + q = quantTable + i; // check for all-zero AC coefficients if (p[1] == 0 && p[2] == 0 && p[3] == 0 && p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) { - t = (dctSqrt2 * p[0] + 512) >> 10; - p[0] = t; - p[1] = t; - p[2] = t; - p[3] = t; - p[4] = t; - p[5] = t; - p[6] = t; - p[7] = t; + t0 = p[0] * q[0]; + p[0] = t0; + p[1] = t0; + p[2] = t0; + p[3] = t0; + p[4] = t0; + p[5] = t0; + p[6] = t0; + p[7] = t0; continue; } // stage 4 - v0 = (dctSqrt2 * p[0] + 128) >> 8; - v1 = (dctSqrt2 * p[4] + 128) >> 8; - v2 = p[2]; - v3 = p[6]; - v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8; - v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8; - v5 = p[3] << 4; - v6 = p[5] << 4; + v0 = p[0] * q[0]; + v1 = p[4] * q[4]; + v2 = p[2] * q[2]; + v3 = p[6] * q[6]; + t0 = p[1] * q[1]; + t1 = p[7] * q[7]; + v4 = t0 - t1; + v7 = t0 + t1; + v5 = (dctSqrt2 * p[3] * q[3]) >> 12; + v6 = (dctSqrt2 * p[5] * q[5]) >> 12; // stage 3 - t = (v0 - v1+ 1) >> 1; - v0 = (v0 + v1 + 1) >> 1; - v1 = t; - t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; - v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; - v3 = t; - t = (v4 - v6 + 1) >> 1; - v4 = (v4 + v6 + 1) >> 1; - v6 = t; - t = (v7 + v5 + 1) >> 1; - v5 = (v7 - v5 + 1) >> 1; - v7 = t; + t0 = v0 - v1; + v0 = v0 + v1; + v1 = t0; + t0 = dctSqrt2Cos6 * (v2 + v3); + t1 = dctSqrt2Cos6PSin6 * v3; + t2 = dctSqrt2Sin6MCos6 * v2; + v2 = (t0 - t1) >> 12; + v3 = (t0 + t2) >> 12; + t0 = v4 - v6; + v4 = v4 + v6; + v6 = t0; + t0 = v7 + v5; + v5 = v7 - v5; + v7 = t0; // stage 2 - t = (v0 - v3 + 1) >> 1; - v0 = (v0 + v3 + 1) >> 1; - v3 = t; - t = (v1 - v2 + 1) >> 1; - v1 = (v1 + v2 + 1) >> 1; - v2 = t; - t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; - v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; - v7 = t; - t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; - v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; - v6 = t; + t0 = v0 - v3; + v0 = v0 + v3; + v3 = t0; + t0 = v1 - v2; + v1 = v1 + v2; + v2 = t0; + t0 = dctCos3 * (v4 + v7); + t1 = dctCos3PSin3 * v7; + t2 = dctSin3MCos3 * v4; + v4 = (t0 - t1) >> 12; + v7 = (t0 + t2) >> 12; + t0 = dctCos1 * (v5 + v6); + t1 = dctCos1PSin1 * v6; + t2 = dctSin1MCos1 * v5; + v5 = (t0 - t1) >> 12; + v6 = (t0 + t2) >> 12; // stage 1 p[0] = v0 + v7; @@ -2964,55 +3028,60 @@ void DCTStream::transformDataUnit(Gushort *quantTable, // check for all-zero AC coefficients if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 && p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) { - t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; - p[0*8] = t; - p[1*8] = t; - p[2*8] = t; - p[3*8] = t; - p[4*8] = t; - p[5*8] = t; - p[6*8] = t; - p[7*8] = t; + t0 = p[0*8]; + p[1*8] = t0; + p[2*8] = t0; + p[3*8] = t0; + p[4*8] = t0; + p[5*8] = t0; + p[6*8] = t0; + p[7*8] = t0; continue; } // stage 4 - v0 = (dctSqrt2 * p[0*8] + 2048) >> 12; - v1 = (dctSqrt2 * p[4*8] + 2048) >> 12; + v0 = p[0*8]; + v1 = p[4*8]; v2 = p[2*8]; v3 = p[6*8]; - v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12; - v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12; - v5 = p[3*8]; - v6 = p[5*8]; + v4 = p[1*8] - p[7*8]; + v7 = p[1*8] + p[7*8]; + v5 = (dctSqrt2 * p[3*8]) >> 12; + v6 = (dctSqrt2 * p[5*8]) >> 12; // stage 3 - t = (v0 - v1 + 1) >> 1; - v0 = (v0 + v1 + 1) >> 1; - v1 = t; - t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; - v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; - v3 = t; - t = (v4 - v6 + 1) >> 1; - v4 = (v4 + v6 + 1) >> 1; - v6 = t; - t = (v7 + v5 + 1) >> 1; - v5 = (v7 - v5 + 1) >> 1; - v7 = t; + t0 = v0 - v1; + v0 = v0 + v1; + v1 = t0; + t0 = dctSqrt2Cos6 * (v2 + v3); + t1 = dctSqrt2Cos6PSin6 * v3; + t2 = dctSqrt2Sin6MCos6 * v2; + v2 = (t0 - t1) >> 12; + v3 = (t0 + t2) >> 12; + t0 = v4 - v6; + v4 = v4 + v6; + v6 = t0; + t0 = v7 + v5; + v5 = v7 - v5; + v7 = t0; // stage 2 - t = (v0 - v3 + 1) >> 1; - v0 = (v0 + v3 + 1) >> 1; - v3 = t; - t = (v1 - v2 + 1) >> 1; - v1 = (v1 + v2 + 1) >> 1; - v2 = t; - t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; - v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; - v7 = t; - t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; - v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; - v6 = t; + t0 = v0 - v3; + v0 = v0 + v3; + v3 = t0; + t0 = v1 - v2; + v1 = v1 + v2; + v2 = t0; + t0 = dctCos3 * (v4 + v7); + t1 = dctCos3PSin3 * v7; + t2 = dctSin3MCos3 * v4; + v4 = (t0 - t1) >> 12; + v7 = (t0 + t2) >> 12; + t0 = dctCos1 * (v5 + v6); + t1 = dctCos1PSin1 * v6; + t2 = dctSin1MCos1 * v5; + v5 = (t0 - t1) >> 12; + v6 = (t0 + t2) >> 12; // stage 1 p[0*8] = v0 + v7; @@ -3027,7 +3096,7 @@ void DCTStream::transformDataUnit(Gushort *quantTable, // convert to 8-bit integers for (i = 0; i < 64; ++i) { - dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)]; + dataOut[i] = dctClip(128 + (dataIn[i] >> 3)); } } @@ -3103,7 +3172,6 @@ GBool DCTStream::readHeader() { GBool doScan; int n; int c = 0; - int i; // read headers doScan = gFalse; @@ -3163,9 +3231,7 @@ GBool DCTStream::readHeader() { // skip APPn / COM / etc. if (c >= 0xe0) { n = read16() - 2; - for (i = 0; i < n; ++i) { - str->getChar(); - } + str->discardChars(n); } else { error(errSyntaxError, getPos(), "Unknown DCT marker <{0:02x}>", c); return gFalse; @@ -3178,12 +3244,11 @@ GBool DCTStream::readHeader() { } GBool DCTStream::readBaselineSOF() { - int length; int prec; int i; int c; - length = read16(); + read16(); // length prec = str->getChar(); height = read16(); width = read16(); @@ -3218,12 +3283,11 @@ GBool DCTStream::readBaselineSOF() { } GBool DCTStream::readProgressiveSOF() { - int length; int prec; int i; int c; - length = read16(); + read16(); // length prec = str->getChar(); height = read16(); width = read16(); @@ -4194,6 +4258,9 @@ void FlateStream::reset() { eof = gTrue; str->reset(); + if (pred) { + pred->reset(); + } // read header //~ need to look at window size? @@ -4274,10 +4341,10 @@ int FlateStream::getBlock(char *blk, int size) { n = 0; while (n < size) { - if (endOfBlock && eof) { - break; - } if (remain == 0) { + if (endOfBlock && eof) { + break; + } readSome(); } while (remain && n < size) { @@ -4969,3 +5036,149 @@ GBool RunLengthEncoder::fillBuf() { bufPtr = buf; return gTrue; } + +//------------------------------------------------------------------------ +// LZWEncoder +//------------------------------------------------------------------------ + +LZWEncoder::LZWEncoder(Stream *strA): + FilterStream(strA) +{ + inBufLen = 0; + outBufLen = 0; +} + +LZWEncoder::~LZWEncoder() { + if (str->isEncoder()) { + delete str; + } +} + +void LZWEncoder::reset() { + int i; + + str->reset(); + + // initialize code table + for (i = 0; i < 256; ++i) { + table[i].byte = i; + table[i].next = NULL; + table[i].children = NULL; + } + nextSeq = 258; + codeLen = 9; + + // initialize input buffer + inBufLen = str->getBlock((char *)inBuf, sizeof(inBuf)); + + // initialize output buffer with a clear-table code + outBuf = 256; + outBufLen = 9; + needEOD = gFalse; +} + +int LZWEncoder::getChar() { + int ret; + + if (inBufLen == 0 && !needEOD && outBufLen == 0) { + return EOF; + } + if (outBufLen < 8 && (inBufLen > 0 || needEOD)) { + fillBuf(); + } + if (outBufLen >= 8) { + ret = (outBuf >> (outBufLen - 8)) & 0xff; + outBufLen -= 8; + } else { + ret = (outBuf << (8 - outBufLen)) & 0xff; + outBufLen = 0; + } + return ret; +} + +int LZWEncoder::lookChar() { + if (inBufLen == 0 && !needEOD && outBufLen == 0) { + return EOF; + } + if (outBufLen < 8 && (inBufLen > 0 || needEOD)) { + fillBuf(); + } + if (outBufLen >= 8) { + return (outBuf >> (outBufLen - 8)) & 0xff; + } else { + return (outBuf << (8 - outBufLen)) & 0xff; + } +} + +// On input, outBufLen < 8. +// This function generates, at most, 2 12-bit codes +// --> outBufLen < 8 + 12 + 12 = 32 +void LZWEncoder::fillBuf() { + LZWEncoderNode *p0, *p1; + int seqLen, code, i; + + if (needEOD) { + outBuf = (outBuf << codeLen) | 257; + outBufLen += codeLen; + needEOD = gFalse; + return; + } + + // find longest matching sequence (if any) + p0 = table + inBuf[0]; + seqLen = 1; + while (inBufLen > seqLen) { + for (p1 = p0->children; p1; p1 = p1->next) { + if (p1->byte == inBuf[seqLen]) { + break; + } + } + if (!p1) { + break; + } + p0 = p1; + ++seqLen; + } + code = (int)(p0 - table); + + // generate an output code + outBuf = (outBuf << codeLen) | code; + outBufLen += codeLen; + + // update the table + table[nextSeq].byte = seqLen < inBufLen ? inBuf[seqLen] : 0; + table[nextSeq].children = NULL; + if (table[code].children) { + table[nextSeq].next = table[code].children; + } else { + table[nextSeq].next = NULL; + } + table[code].children = table + nextSeq; + ++nextSeq; + + // update the input buffer + memmove(inBuf, inBuf + seqLen, inBufLen - seqLen); + inBufLen -= seqLen; + inBufLen += str->getBlock((char *)inBuf + inBufLen, + sizeof(inBuf) - inBufLen); + + // increment codeLen; generate clear-table code + if (nextSeq == (1 << codeLen)) { + ++codeLen; + if (codeLen == 13) { + outBuf = (outBuf << 12) | 256; + outBufLen += 12; + for (i = 0; i < 256; ++i) { + table[i].next = NULL; + table[i].children = NULL; + } + nextSeq = 258; + codeLen = 9; + } + } + + // generate EOD next time + if (inBufLen == 0) { + needEOD = gTrue; + } +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream.h index 50710a6d9f2..c55d8023969 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/Stream.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Stream.h @@ -17,6 +17,7 @@ #include <stdio.h> #include "gtypes.h" +#include "gfile.h" #include "Object.h" class BaseStream; @@ -97,13 +98,18 @@ public: // Get next line from stream. virtual char *getLine(char *buf, int size); + // Discard the next <n> bytes from stream. Returns the number of + // bytes discarded, which will be less than <n> only if EOF is + // reached. + virtual Guint discardChars(Guint n); + // Get current position in file. - virtual int getPos() = 0; + virtual GFileOffset getPos() = 0; // Go to a position in the stream. If <dir> is negative, the // position is from the end of the file; otherwise the position is // from the start of the file. - virtual void setPos(Guint pos, int dir = 0) = 0; + virtual void setPos(GFileOffset pos, int dir = 0) = 0; // Get PostScript command for the filter(s). virtual GString *getPSFilter(int psLevel, const char *indent); @@ -133,11 +139,11 @@ public: // Add filters to this stream according to the parameters in <dict>. // Returns the new stream. - Stream *addFilters(Object *dict); + Stream *addFilters(Object *dict, int recursion = 0); private: - Stream *makeFilter(char *name, Stream *str, Object *params); + Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); int ref; // reference count }; @@ -153,9 +159,9 @@ public: BaseStream(Object *dictA); virtual ~BaseStream(); - virtual Stream *makeSubStream(Guint start, GBool limited, - Guint length, Object *dict) = 0; - virtual void setPos(Guint pos, int dir = 0) = 0; + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset length, Object *dict) = 0; + virtual void setPos(GFileOffset pos, int dir = 0) = 0; virtual GBool isBinary(GBool last = gTrue) { return last; } virtual BaseStream *getBaseStream() { return this; } virtual Stream *getUndecodedStream() { return this; } @@ -163,7 +169,7 @@ public: virtual GString *getFileName() { return NULL; } // Get/set position of first byte of stream within the file. - virtual Guint getStart() = 0; + virtual GFileOffset getStart() = 0; virtual void moveStart(int delta) = 0; private: @@ -183,8 +189,8 @@ public: FilterStream(Stream *strA); virtual ~FilterStream(); virtual void close(); - virtual int getPos() { return str->getPos(); } - virtual void setPos(Guint pos, int dir = 0); + virtual GFileOffset getPos() { return str->getPos(); } + virtual void setPos(GFileOffset pos, int dir = 0); virtual BaseStream *getBaseStream() { return str->getBaseStream(); } virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); } virtual Dict *getDict() { return str->getDict(); } @@ -212,6 +218,9 @@ public: // Reset the stream. void reset(); + // Close down the stream. + void close(); + // Gets the next pixel from the stream. <pix> should be able to hold // at least nComps elements. Returns false at end of file. GBool getPixel(Guchar *pix); @@ -252,6 +261,8 @@ public: GBool isOk() { return ok; } + void reset(); + int lookChar(); int getChar(); int getBlock(char *blk, int size); @@ -282,11 +293,11 @@ private: class FileStream: public BaseStream { public: - FileStream(FILE *fA, Guint startA, GBool limitedA, - Guint lengthA, Object *dictA); + FileStream(FILE *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); virtual ~FileStream(); - virtual Stream *makeSubStream(Guint startA, GBool limitedA, - Guint lengthA, Object *dictA); + virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); virtual StreamKind getKind() { return strFile; } virtual void reset(); virtual void close(); @@ -295,9 +306,9 @@ public: virtual int lookChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } virtual int getBlock(char *blk, int size); - virtual int getPos() { return bufPos + (int)(bufPtr - buf); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart() { return start; } + virtual GFileOffset getPos() { return bufPos + (int)(bufPtr - buf); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { return start; } virtual void moveStart(int delta); private: @@ -305,14 +316,14 @@ private: GBool fillBuf(); FILE *f; - Guint start; + GFileOffset start; GBool limited; - Guint length; + GFileOffset length; char buf[fileStreamBufSize]; char *bufPtr; char *bufEnd; - Guint bufPos; - int savePos; + GFileOffset bufPos; + GFileOffset savePos; GBool saved; }; @@ -325,8 +336,8 @@ public: MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); virtual ~MemStream(); - virtual Stream *makeSubStream(Guint start, GBool limited, - Guint lengthA, Object *dictA); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset lengthA, Object *dictA); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual void close(); @@ -335,9 +346,9 @@ public: virtual int lookChar() { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } virtual int getBlock(char *blk, int size); - virtual int getPos() { return (int)(bufPtr - buf); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart() { return start; } + virtual GFileOffset getPos() { return (GFileOffset)(bufPtr - buf); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { return start; } virtual void moveStart(int delta); private: @@ -363,25 +374,25 @@ private: class EmbedStream: public BaseStream { public: - EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA); + EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); virtual ~EmbedStream(); - virtual Stream *makeSubStream(Guint start, GBool limitedA, - Guint lengthA, Object *dictA); + virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, + GFileOffset lengthA, Object *dictA); virtual StreamKind getKind() { return str->getKind(); } virtual void reset() {} virtual int getChar(); virtual int lookChar(); virtual int getBlock(char *blk, int size); - virtual int getPos() { return str->getPos(); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart(); + virtual GFileOffset getPos() { return str->getPos(); } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart(); virtual void moveStart(int delta); private: Stream *str; GBool limited; - Guint length; + GFileOffset length; }; //------------------------------------------------------------------------ @@ -623,9 +634,11 @@ private: DCTHuffTable acHuffTables[4]; // AC Huffman tables int numDCHuffTables; // number of DC Huffman tables int numACHuffTables; // number of AC Huffman tables - Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode) + Guchar *rowBuf; + Guchar *rowBufPtr; // current position within rowBuf + Guchar *rowBufEnd; // end of valid data in rowBuf int *frameBuf[4]; // buffer for frame (progressive mode) - int comp, x, y, dy; // current position within image/MCU + int comp, x, y; // current position within image/MCU int restartCtr; // MCUs left until restart int restartMarker; // next restart marker int eobRun; // number of EOBs left in the current run @@ -902,4 +915,42 @@ private: GBool fillBuf(); }; +//------------------------------------------------------------------------ +// LZWEncoder +//------------------------------------------------------------------------ + +struct LZWEncoderNode { + int byte; + LZWEncoderNode *next; // next sibling + LZWEncoderNode *children; // first child +}; + +class LZWEncoder: public FilterStream { +public: + + LZWEncoder(Stream *strA); + virtual ~LZWEncoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + LZWEncoderNode table[4096]; + int nextSeq; + int codeLen; + Guchar inBuf[4096]; + int inBufLen; + int outBuf; + int outBufLen; + GBool needEOD; + + void fillBuf(); +}; + #endif diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.cc new file mode 100644 index 00000000000..be1fad2a2e9 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.cc @@ -0,0 +1,4463 @@ +//======================================================================== +// +// TextOutputDev.cc +// +// Copyright 1997-2014 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <math.h> +#include <ctype.h> +#ifdef _WIN32 +#include <fcntl.h> // for O_BINARY +#include <io.h> // for setmode +#endif +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "config.h" +#include "Error.h" +#include "GlobalParams.h" +#include "UnicodeMap.h" +#include "UnicodeTypeTable.h" +#include "GfxState.h" +#include "Link.h" +#include "TextOutputDev.h" + +//------------------------------------------------------------------------ +// parameters +//------------------------------------------------------------------------ + +// Size of bins used for horizontal and vertical profiles is +// splitPrecisionMul * minFontSize. +#define splitPrecisionMul 0.05 + +// Minimum allowed split precision. +#define minSplitPrecision 0.01 + +// yMin and yMax (or xMin and xMax for rot=1,3) are adjusted by this +// fraction of the text height, to allow for slightly overlapping +// lines (or large ascent/descent values). +#define ascentAdjustFactor 0 +#define descentAdjustFactor 0.35 + +// Gaps larger than max{gap} - splitGapSlack * avgFontSize are +// considered to be equivalent. +#define splitGapSlack 0.2 + +// The vertical gap threshold (minimum gap required to split +// vertically) depends on the (approximate) number of lines in the +// block: +// threshold = (max + slope * nLines) * avgFontSize +// with a min value of vertGapThresholdMin * avgFontSize. +#define vertGapThresholdMin 0.8 +#define vertGapThresholdMax 3 +#define vertGapThresholdSlope -0.5 + +// Vertical gap threshold for table mode. +#define vertGapThresholdTableMin 0.2 +#define vertGapThresholdTableMax 0.5 +#define vertGapThresholdTableSlope -0.02 + +// 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 + +// 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. +#define dupMaxPriDelta 0.1 +#define dupMaxSecDelta 0.2 + +// Inter-character spacing that varies by less than this multiple of +// font size is assumed to be equivalent. +#define uniformSpacing 0.07 + +// Typical word spacing, as a fraction of font size. This will be +// added to the minimum inter-character spacing, to account for wide +// character spacing. +#define wordSpacing 0.1 + +// Minimum paragraph indent from left margin, as a fraction of font +// size. +#define minParagraphIndent 0.5 + +// If the space between two lines is greater than +// paragraphSpacingThreshold * avgLineSpacing, start a new paragraph. +#define paragraphSpacingThreshold 1.2 + +// If font size changes by at least this much (measured in points) +// between lines, start a new paragraph. +#define paragraphFontSizeDelta 1 + +// Spaces at the start of a line in physical layout mode are this wide +// (as a multiple of font size). +#define physLayoutSpaceWidth 0.33 + +// Table cells (TextColumns) are allowed to overlap by this much +// in table layout mode (as a fraction of cell width or height). +#define tableCellOverlapSlack 0.05 + +// Primary axis delta which will cause a line break in raw mode +// (as a fraction of font size). +#define rawModeLineDelta 0.5 + +// Secondary axis delta which will cause a word break in raw mode +// (as a fraction of font size). +#define rawModeWordSpacing 0.15 + +// Secondary axis overlap which will cause a line break in raw mode +// (as a fraction of font size). +#define rawModeCharOverlap 0.2 + +// Max spacing (as a multiple of font size) allowed between the end of +// a line and a clipped character to be included in that line. +#define clippedTextMaxWordSpace 0.5 + +// Max width of underlines (in points). +#define maxUnderlineWidth 3 + +// Max horizontal distance between edge of word and start of underline +// (as a fraction of font size). +#define underlineSlack 0.2 + +// Max vertical distance between baseline of word and start of +// underline (as a fraction of font size). +#define underlineBaselineSlack 0.2 + +// Max distance between edge of text and edge of link border (as a +// fraction of font size). +#define hyperlinkSlack 0.2 + +//------------------------------------------------------------------------ +// TextChar +//------------------------------------------------------------------------ + +class TextChar { +public: + + TextChar(Unicode cA, int charPosA, int charLenA, + double xMinA, double yMinA, double xMaxA, double yMaxA, + int rotA, GBool clippedA, GBool invisibleA, + TextFontInfo *fontA, double fontSizeA, + double colorRA, double colorGA, double colorBA); + + static int cmpX(const void *p1, const void *p2); + static int cmpY(const void *p1, const void *p2); + + Unicode c; + int charPos; + int charLen; + double xMin, yMin, xMax, yMax; + Guchar rot; + char clipped; + char invisible; + TextFontInfo *font; + double fontSize; + double colorR, + colorG, + colorB; +}; + +TextChar::TextChar(Unicode cA, int charPosA, int charLenA, + double xMinA, double yMinA, double xMaxA, double yMaxA, + int rotA, GBool clippedA, GBool invisibleA, + TextFontInfo *fontA, double fontSizeA, + double colorRA, double colorGA, double colorBA) { + double t; + + c = cA; + charPos = charPosA; + charLen = charLenA; + xMin = xMinA; + yMin = yMinA; + xMax = xMaxA; + yMax = yMaxA; + // this can happen with vertical writing mode, or with odd values + // for the char/word spacing parameters + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + rot = (Guchar)rotA; + clipped = (char)clippedA; + invisible = (char)invisibleA; + font = fontA; + fontSize = fontSizeA; + colorR = colorRA; + colorG = colorGA; + colorB = colorBA; +} + +int TextChar::cmpX(const void *p1, const void *p2) { + const TextChar *ch1 = *(const TextChar **)p1; + const TextChar *ch2 = *(const TextChar **)p2; + + if (ch1->xMin < ch2->xMin) { + return -1; + } else if (ch1->xMin > ch2->xMin) { + return 1; + } else { + return 0; + } +} + +int TextChar::cmpY(const void *p1, const void *p2) { + const TextChar *ch1 = *(const TextChar **)p1; + const TextChar *ch2 = *(const TextChar **)p2; + + if (ch1->yMin < ch2->yMin) { + return -1; + } else if (ch1->yMin > ch2->yMin) { + return 1; + } else { + return 0; + } +} + +//------------------------------------------------------------------------ +// TextBlock +//------------------------------------------------------------------------ + +enum TextBlockType { + blkVertSplit, + blkHorizSplit, + blkLeaf +}; + +enum TextBlockTag { + blkTagMulticolumn, + blkTagColumn, + blkTagLine +}; + +class TextBlock { +public: + + TextBlock(TextBlockType typeA, int rotA); + ~TextBlock(); + void addChild(TextBlock *child); + void addChild(TextChar *child); + void prependChild(TextChar *child); + void updateBounds(int childIdx); + + TextBlockType type; + TextBlockTag tag; + int rot; + double xMin, yMin, xMax, yMax; + GBool smallSplit; // true for blkVertSplit/blkHorizSplit + // where the gap size is small + GList *children; // for blkLeaf, children are TextWord; + // for others, children are TextBlock +}; + +TextBlock::TextBlock(TextBlockType typeA, int rotA) { + type = typeA; + tag = blkTagMulticolumn; + rot = rotA; + xMin = yMin = xMax = yMax = 0; + smallSplit = gFalse; + children = new GList(); +} + +TextBlock::~TextBlock() { + if (type == blkLeaf) { + delete children; + } else { + deleteGList(children, TextBlock); + } +} + +void TextBlock::addChild(TextBlock *child) { + if (children->getLength() == 0) { + xMin = child->xMin; + yMin = child->yMin; + xMax = child->xMax; + yMax = child->yMax; + } else { + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } + } + children->append(child); +} + +void TextBlock::addChild(TextChar *child) { + if (children->getLength() == 0) { + xMin = child->xMin; + yMin = child->yMin; + xMax = child->xMax; + yMax = child->yMax; + } else { + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } + } + children->append(child); +} + +void TextBlock::prependChild(TextChar *child) { + if (children->getLength() == 0) { + xMin = child->xMin; + yMin = child->yMin; + xMax = child->xMax; + yMax = child->yMax; + } else { + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } + } + children->insert(0, child); +} + +void TextBlock::updateBounds(int childIdx) { + TextBlock *child; + + child = (TextBlock *)children->get(childIdx); + if (child->xMin < xMin) { + xMin = child->xMin; + } + if (child->yMin < yMin) { + yMin = child->yMin; + } + if (child->xMax > xMax) { + xMax = child->xMax; + } + if (child->yMax > yMax) { + yMax = child->yMax; + } +} + +//------------------------------------------------------------------------ +// TextUnderline +//------------------------------------------------------------------------ + +class TextUnderline { +public: + + TextUnderline(double x0A, double y0A, double x1A, double y1A) + { x0 = x0A; y0 = y0A; x1 = x1A; y1 = y1A; horiz = y0 == y1; } + ~TextUnderline() {} + + double x0, y0, x1, y1; + GBool horiz; +}; + +//------------------------------------------------------------------------ +// TextLink +//------------------------------------------------------------------------ + +class TextLink { +public: + + TextLink(double xMinA, double yMinA, double xMaxA, double yMaxA, + GString *uriA) + { xMin = xMinA; yMin = yMinA; xMax = xMaxA; yMax = yMaxA; uri = uriA; } + ~TextLink(); + + double xMin, yMin, xMax, yMax; + GString *uri; +}; + +TextLink::~TextLink() { + if (uri) { + delete uri; + } +} + +//------------------------------------------------------------------------ +// TextOutputControl +//------------------------------------------------------------------------ + +TextOutputControl::TextOutputControl() { + mode = textOutReadingOrder; + fixedPitch = 0; + fixedLineSpacing = 0; + html = gFalse; + clipText = gFalse; +} + + +//------------------------------------------------------------------------ +// TextFontInfo +//------------------------------------------------------------------------ + +TextFontInfo::TextFontInfo(GfxState *state) { + GfxFont *gfxFont; + + gfxFont = state->getFont(); + if (gfxFont) { + fontID = *gfxFont->getID(); + ascent = gfxFont->getAscent(); + descent = gfxFont->getDescent(); + // "odd" ascent/descent values cause trouble more often than not + // (in theory these could be legitimate values for oddly designed + // fonts -- but they are more often due to buggy PDF generators) + // (values that are too small are a different issue -- those seem + // to be more commonly legitimate) + if (ascent > 1) { + ascent = 0.75; + } + if (descent < -0.5) { + descent = -0.25; + } + } else { + fontID.num = -1; + fontID.gen = -1; + ascent = 0.75; + descent = -0.25; + } + fontName = (gfxFont && gfxFont->getName()) ? gfxFont->getName()->copy() + : (GString *)NULL; + flags = gfxFont ? gfxFont->getFlags() : 0; + mWidth = 0; + if (gfxFont && !gfxFont->isCIDFont()) { + char *name; + int code; + for (code = 0; code < 256; ++code) { + if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) && + name[0] == 'm' && name[1] == '\0') { + mWidth = ((Gfx8BitFont *)gfxFont)->getWidth(code); + break; + } + } + } +} + +TextFontInfo::~TextFontInfo() { + if (fontName) { + delete fontName; + } +} + +GBool TextFontInfo::matches(GfxState *state) { + Ref *id; + + if (!state->getFont()) { + return gFalse; + } + id = state->getFont()->getID(); + return id->num == fontID.num && id->gen == fontID.gen; +} + +//------------------------------------------------------------------------ +// TextWord +//------------------------------------------------------------------------ + +// Build a TextWord object, using chars[start .. start+len-1]. +// (If rot >= 2, the chars list is in reverse order.) +TextWord::TextWord(GList *chars, int start, int lenA, + int rotA, GBool spaceAfterA) { + TextChar *ch; + int i; + + rot = rotA; + len = lenA; + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + charPos = (int *)gmallocn(len + 1, sizeof(int)); + switch (rot) { + case 0: + default: + ch = (TextChar *)chars->get(start); + xMin = ch->xMin; + yMin = ch->yMin; + yMax = ch->yMax; + ch = (TextChar *)chars->get(start + len - 1); + xMax = ch->xMax; + break; + case 1: + ch = (TextChar *)chars->get(start); + xMin = ch->xMin; + xMax = ch->xMax; + yMin = ch->yMin; + ch = (TextChar *)chars->get(start + len - 1); + yMax = ch->yMax; + break; + case 2: + ch = (TextChar *)chars->get(start); + xMax = ch->xMax; + yMin = ch->yMin; + yMax = ch->yMax; + ch = (TextChar *)chars->get(start + len - 1); + xMin = ch->xMin; + break; + case 3: + ch = (TextChar *)chars->get(start); + xMin = ch->xMin; + xMax = ch->xMax; + yMax = ch->yMax; + ch = (TextChar *)chars->get(start + len - 1); + yMin = ch->yMin; + break; + } + for (i = 0; i < len; ++i) { + ch = (TextChar *)chars->get(rot >= 2 ? start + len - 1 - i : start + i); + text[i] = ch->c; + charPos[i] = ch->charPos; + if (i == len - 1) { + charPos[len] = ch->charPos + ch->charLen; + } + switch (rot) { + case 0: + default: + edge[i] = ch->xMin; + if (i == len - 1) { + edge[len] = ch->xMax; + } + break; + case 1: + edge[i] = ch->yMin; + if (i == len - 1) { + edge[len] = ch->yMax; + } + break; + case 2: + edge[i] = ch->xMax; + if (i == len - 1) { + edge[len] = ch->xMin; + } + break; + case 3: + edge[i] = ch->yMax; + if (i == len - 1) { + edge[len] = ch->yMin; + } + break; + } + } + ch = (TextChar *)chars->get(start); + font = ch->font; + fontSize = ch->fontSize; + spaceAfter = spaceAfterA; + underlined = gFalse; + link = NULL; + colorR = ch->colorR; + colorG = ch->colorG; + colorB = ch->colorB; + invisible = ch->invisible; +} + +TextWord::TextWord(TextWord *word) { + *this = *word; + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + memcpy(text, word->text, len * sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + memcpy(edge, word->edge, (len + 1) * sizeof(double)); + charPos = (int *)gmallocn(len + 1, sizeof(int)); + memcpy(charPos, word->charPos, (len + 1) * sizeof(int)); +} + +TextWord::~TextWord() { + gfree(text); + gfree(edge); + gfree(charPos); +} + +// This is used to append a clipped character to a word. +void TextWord::appendChar(TextChar *ch) { + if (ch->xMin < xMin) { + xMin = ch->xMin; + } + if (ch->xMax > xMax) { + xMax = ch->xMax; + } + if (ch->yMin < yMin) { + yMin = ch->yMin; + } + if (ch->yMax > yMax) { + yMax = ch->yMax; + } + text = (Unicode *)greallocn(text, len + 1, sizeof(Unicode)); + edge = (double *)greallocn(edge, len + 2, sizeof(double)); + charPos = (int *)greallocn(charPos, len + 2, sizeof(int)); + text[len] = ch->c; + charPos[len] = ch->charPos; + charPos[len+1] = ch->charPos + ch->charLen; + switch (rot) { + case 0: + default: + edge[len] = ch->xMin; + edge[len+1] = ch->xMax; + break; + case 1: + edge[len] = ch->yMin; + edge[len+1] = ch->yMax; + break; + case 2: + edge[len] = ch->xMax; + edge[len+1] = ch->xMin; + break; + case 3: + edge[len] = ch->yMax; + edge[len+1] = ch->yMin; + break; + } + ++len; +} + +int TextWord::cmpYX(const void *p1, const void *p2) { + const TextWord *word1 = *(const TextWord **)p1; + const TextWord *word2 = *(const TextWord **)p2; + double cmp; + + if ((cmp = word1->yMin - word2->yMin) == 0) { + cmp = word1->xMin - word2->xMin; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextWord::cmpCharPos(const void *p1, const void *p2) { + const TextWord *word1 = *(const TextWord **)p1; + const TextWord *word2 = *(const TextWord **)p2; + + return word1->charPos[0] - word2->charPos[0]; +} + +GString *TextWord::getText() { + GString *s; + UnicodeMap *uMap; + char buf[8]; + int n, i; + + s = new GString(); + if (!(uMap = globalParams->getTextEncoding())) { + return s; + } + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(text[i], buf, sizeof(buf)); + s->append(buf, n); + } + uMap->decRefCnt(); + return s; +} + +void TextWord::getCharBBox(int charIdx, double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { + if (charIdx < 0 || charIdx >= len) { + return; + } + switch (rot) { + case 0: + *xMinA = edge[charIdx]; + *xMaxA = edge[charIdx + 1]; + *yMinA = yMin; + *yMaxA = yMax; + break; + case 1: + *xMinA = xMin; + *xMaxA = xMax; + *yMinA = edge[charIdx]; + *yMaxA = edge[charIdx + 1]; + break; + case 2: + *xMinA = edge[charIdx + 1]; + *xMaxA = edge[charIdx]; + *yMinA = yMin; + *yMaxA = yMax; + break; + case 3: + *xMinA = xMin; + *xMaxA = xMax; + *yMinA = edge[charIdx + 1]; + *yMaxA = edge[charIdx]; + break; + } +} + +double TextWord::getBaseline() { + switch (rot) { + case 0: + default: + return yMax + fontSize * font->descent; + case 1: + return xMin - fontSize * font->descent; + case 2: + return yMin - fontSize * font->descent; + case 3: + return xMax + fontSize * font->descent; + } +} + +GString *TextWord::getLinkURI() { + return link ? link->uri : (GString *)NULL; +} + +//------------------------------------------------------------------------ +// TextLine +//------------------------------------------------------------------------ + +TextLine::TextLine(GList *wordsA, double xMinA, double yMinA, + double xMaxA, double yMaxA, double fontSizeA) { + TextWord *word; + int i, j, k; + + words = wordsA; + rot = 0; + xMin = xMinA; + yMin = yMinA; + xMax = xMaxA; + yMax = yMaxA; + fontSize = fontSizeA; + px = 0; + pw = 0; + + // build the text + len = 0; + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + len += word->len; + if (word->spaceAfter) { + ++len; + } + } + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + j = 0; + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + if (i == 0) { + rot = word->rot; + } + for (k = 0; k < word->len; ++k) { + text[j] = word->text[k]; + edge[j] = word->edge[k]; + ++j; + } + edge[j] = word->edge[word->len]; + if (word->spaceAfter) { + text[j] = (Unicode)0x0020; + ++j; + edge[j] = edge[j - 1]; + } + } + //~ need to check for other Unicode chars used as hyphens + hyphenated = text[len - 1] == (Unicode)'-'; +} + +TextLine::~TextLine() { + deleteGList(words, TextWord); + gfree(text); + gfree(edge); +} + +double TextLine::getBaseline() { + TextWord *word0; + + word0 = (TextWord *)words->get(0); + switch (rot) { + case 0: + default: + return yMax + fontSize * word0->font->descent; + case 1: + return xMin - fontSize * word0->font->descent; + case 2: + return yMin - fontSize * word0->font->descent; + case 3: + return xMax + fontSize * word0->font->descent; + } +} + +//------------------------------------------------------------------------ +// TextParagraph +//------------------------------------------------------------------------ + +TextParagraph::TextParagraph(GList *linesA) { + TextLine *line; + int i; + + lines = linesA; + xMin = yMin = xMax = yMax = 0; + for (i = 0; i < lines->getLength(); ++i) { + line = (TextLine *)lines->get(i); + if (i == 0 || line->xMin < xMin) { + xMin = line->xMin; + } + if (i == 0 || line->yMin < yMin) { + yMin = line->yMin; + } + if (i == 0 || line->xMax > xMax) { + xMax = line->xMax; + } + if (i == 0 || line->yMax > yMax) { + yMax = line->yMax; + } + } +} + +TextParagraph::~TextParagraph() { + deleteGList(lines, TextLine); +} + +//------------------------------------------------------------------------ +// TextColumn +//------------------------------------------------------------------------ + +TextColumn::TextColumn(GList *paragraphsA, double xMinA, double yMinA, + double xMaxA, double yMaxA) { + paragraphs = paragraphsA; + xMin = xMinA; + yMin = yMinA; + xMax = xMaxA; + yMax = yMaxA; + px = py = 0; + pw = ph = 0; +} + +TextColumn::~TextColumn() { + deleteGList(paragraphs, TextParagraph); +} + +int TextColumn::cmpX(const void *p1, const void *p2) { + const TextColumn *col1 = *(const TextColumn **)p1; + const TextColumn *col2 = *(const TextColumn **)p2; + + if (col1->xMin < col2->xMin) { + return -1; + } else if (col1->xMin > col2->xMin) { + return 1; + } else { + return 0; + } +} + +int TextColumn::cmpY(const void *p1, const void *p2) { + const TextColumn *col1 = *(const TextColumn **)p1; + const TextColumn *col2 = *(const TextColumn **)p2; + + if (col1->yMin < col2->yMin) { + return -1; + } else if (col1->yMin > col2->yMin) { + return 1; + } else { + return 0; + } +} + +int TextColumn::cmpPX(const void *p1, const void *p2) { + const TextColumn *col1 = *(const TextColumn **)p1; + const TextColumn *col2 = *(const TextColumn **)p2; + + if (col1->px < col2->px) { + return -1; + } else if (col1->px > col2->px) { + return 1; + } else { + return 0; + } +} + +//------------------------------------------------------------------------ +// TextWordList +//------------------------------------------------------------------------ + +TextWordList::TextWordList(GList *wordsA) { + words = wordsA; +} + +TextWordList::~TextWordList() { + deleteGList(words, TextWord); +} + +int TextWordList::getLength() { + return words->getLength(); +} + +TextWord *TextWordList::get(int idx) { + if (idx < 0 || idx >= words->getLength()) { + return NULL; + } + return (TextWord *)words->get(idx); +} + +//------------------------------------------------------------------------ +// TextPage +//------------------------------------------------------------------------ + +TextPage::TextPage(TextOutputControl *controlA) { + control = *controlA; + pageWidth = pageHeight = 0; + charPos = 0; + curFont = NULL; + curFontSize = 0; + curRot = 0; + nTinyChars = 0; + actualText = NULL; + actualTextLen = 0; + actualTextX0 = 0; + actualTextY0 = 0; + actualTextX1 = 0; + actualTextY1 = 0; + actualTextNBytes = 0; + + chars = new GList(); + fonts = new GList(); + + underlines = new GList(); + links = new GList(); + + findCols = NULL; + findLR = gTrue; + lastFindXMin = lastFindYMin = 0; + haveLastFind = gFalse; +} + +TextPage::~TextPage() { + clear(); + deleteGList(chars, TextChar); + deleteGList(fonts, TextFontInfo); + deleteGList(underlines, TextUnderline); + deleteGList(links, TextLink); + if (findCols) { + deleteGList(findCols, TextColumn); + } +} + +void TextPage::startPage(GfxState *state) { + clear(); + if (state) { + pageWidth = state->getPageWidth(); + pageHeight = state->getPageHeight(); + } else { + pageWidth = pageHeight = 0; + } +} + +void TextPage::clear() { + pageWidth = pageHeight = 0; + charPos = 0; + curFont = NULL; + curFontSize = 0; + curRot = 0; + nTinyChars = 0; + gfree(actualText); + actualText = NULL; + actualTextLen = 0; + actualTextNBytes = 0; + deleteGList(chars, TextChar); + chars = new GList(); + deleteGList(fonts, TextFontInfo); + fonts = new GList(); + deleteGList(underlines, TextUnderline); + underlines = new GList(); + deleteGList(links, TextLink); + links = new GList(); + + if (findCols) { + deleteGList(findCols, TextColumn); + findCols = NULL; + } + findLR = gTrue; + lastFindXMin = lastFindYMin = 0; + haveLastFind = gFalse; +} + +void TextPage::updateFont(GfxState *state) { + GfxFont *gfxFont; + double *fm; + char *name; + int code, mCode, letterCode, anyCode; + double w; + double m[4], m2[4]; + int i; + + // get the font info object + curFont = NULL; + for (i = 0; i < fonts->getLength(); ++i) { + curFont = (TextFontInfo *)fonts->get(i); + if (curFont->matches(state)) { + break; + } + curFont = NULL; + } + if (!curFont) { + curFont = new TextFontInfo(state); + fonts->append(curFont); + } + + // adjust the font size + gfxFont = state->getFont(); + curFontSize = state->getTransformedFontSize(); + if (gfxFont && gfxFont->getType() == fontType3) { + // This is a hack which makes it possible to deal with some Type 3 + // fonts. The problem is that it's impossible to know what the + // base coordinate system used in the font is without actually + // rendering the font. This code tries to guess by looking at the + // width of the character 'm' (which breaks if the font is a + // subset that doesn't contain 'm'). + mCode = letterCode = anyCode = -1; + for (code = 0; code < 256; ++code) { + name = ((Gfx8BitFont *)gfxFont)->getCharName(code); + if (name && name[0] == 'm' && name[1] == '\0') { + mCode = code; + } + if (letterCode < 0 && name && name[1] == '\0' && + ((name[0] >= 'A' && name[0] <= 'Z') || + (name[0] >= 'a' && name[0] <= 'z'))) { + letterCode = code; + } + if (anyCode < 0 && name && + ((Gfx8BitFont *)gfxFont)->getWidth(code) > 0) { + anyCode = code; + } + } + if (mCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth(mCode)) > 0) { + // 0.6 is a generic average 'm' width -- yes, this is a hack + curFontSize *= w / 0.6; + } else if (letterCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth(letterCode)) > 0) { + // even more of a hack: 0.5 is a generic letter width + curFontSize *= w / 0.5; + } else if (anyCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth(anyCode)) > 0) { + // better than nothing: 0.5 is a generic character width + curFontSize *= w / 0.5; + } + fm = gfxFont->getFontMatrix(); + if (fm[0] != 0) { + curFontSize *= fabs(fm[3] / fm[0]); + } + } + + // compute the rotation + state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]); + if (gfxFont && gfxFont->getType() == fontType3) { + fm = gfxFont->getFontMatrix(); + m2[0] = fm[0] * m[0] + fm[1] * m[2]; + m2[1] = fm[0] * m[1] + fm[1] * m[3]; + m2[2] = fm[2] * m[0] + fm[3] * m[2]; + m2[3] = fm[2] * m[1] + fm[3] * m[3]; + m[0] = m2[0]; + m[1] = m2[1]; + m[2] = m2[2]; + m[3] = m2[3]; + } + if (fabs(m[0] * m[3]) > fabs(m[1] * m[2])) { + curRot = (m[0] > 0 || m[3] < 0) ? 0 : 2; + } else { + curRot = (m[2] > 0) ? 1 : 3; + } +} + +void TextPage::addChar(GfxState *state, double x, double y, + double dx, double dy, + CharCode c, int nBytes, Unicode *u, int uLen) { + double x1, y1, x2, y2, w1, h1, dx2, dy2, ascent, descent, sp; + double xMin, yMin, xMax, yMax; + double clipXMin, clipYMin, clipXMax, clipYMax; + GfxRGB rgb; + GBool clipped, rtl; + int i, j; + + // if we're in an ActualText span, save the position info (the + // ActualText chars will be added by TextPage::endActualText()). + if (actualText) { + if (!actualTextNBytes) { + actualTextX0 = x; + actualTextY0 = y; + } + actualTextX1 = x + dx; + actualTextY1 = y + dy; + actualTextNBytes += nBytes; + return; + } + + // subtract char and word spacing from the dx,dy values + sp = state->getCharSpace(); + if (c == (CharCode)0x20) { + sp += state->getWordSpace(); + } + state->textTransformDelta(sp * state->getHorizScaling(), 0, &dx2, &dy2); + dx -= dx2; + dy -= dy2; + state->transformDelta(dx, dy, &w1, &h1); + + // throw away chars that aren't inside the page bounds + // (and also do a sanity check on the character size) + state->transform(x, y, &x1, &y1); + if (x1 + w1 < 0 || x1 > pageWidth || + y1 + h1 < 0 || y1 > pageHeight || + w1 > pageWidth || h1 > pageHeight) { + charPos += nBytes; + return; + } + + // check the tiny chars limit + if (!globalParams->getTextKeepTinyChars() && + fabs(w1) < 3 && fabs(h1) < 3) { + if (++nTinyChars > 50000) { + charPos += nBytes; + return; + } + } + + // skip space characters + if (uLen == 1 && u[0] == (Unicode)0x20) { + charPos += nBytes; + return; + } + + // check for clipping + clipped = gFalse; + if (control.clipText) { + state->getClipBBox(&clipXMin, &clipYMin, &clipXMax, &clipYMax); + if (x1 + 0.1 * w1 < clipXMin || x1 + 0.9 * w1 > clipXMax || + y1 + 0.1 * h1 < clipYMin || y1 + 0.9 * h1 > clipYMax) { + clipped = gTrue; + } + } + + // add the characters + if (uLen > 0) { + + // handle right-to-left ligatures: if there are multiple Unicode + // characters, and they're all right-to-left, insert them in + // right-to-left order + if (uLen > 1) { + rtl = gTrue; + for (i = 0; i < uLen; ++i) { + if (!unicodeTypeR(u[i])) { + rtl = gFalse; + break; + } + } + } else { + rtl = gFalse; + } + + w1 /= uLen; + h1 /= uLen; + ascent = curFont->ascent * curFontSize; + descent = curFont->descent * curFontSize; + for (i = 0; i < uLen; ++i) { + x2 = x1 + i * w1; + y2 = y1 + i * h1; + switch (curRot) { + case 0: + default: + xMin = x2; + xMax = x2 + w1; + yMin = y2 - ascent; + yMax = y2 - descent; + break; + case 1: + xMin = x2 + descent; + xMax = x2 + ascent; + yMin = y2; + yMax = y2 + h1; + break; + case 2: + xMin = x2 + w1; + xMax = x2; + yMin = y2 + descent; + yMax = y2 + ascent; + break; + case 3: + xMin = x2 - ascent; + xMax = x2 - descent; + yMin = y2 + h1; + yMax = y2; + break; + } + if ((state->getRender() & 3) == 1) { + state->getStrokeRGB(&rgb); + } else { + state->getFillRGB(&rgb); + } + if (rtl) { + j = uLen - 1 - i; + } else { + j = i; + } + chars->append(new TextChar(u[j], charPos, nBytes, xMin, yMin, xMax, yMax, + curRot, clipped, + state->getRender() == 3, + curFont, curFontSize, + colToDbl(rgb.r), colToDbl(rgb.g), + colToDbl(rgb.b))); + } + } + + charPos += nBytes; +} + +void TextPage::incCharCount(int nChars) { + charPos += nChars; +} + +void TextPage::beginActualText(GfxState *state, Unicode *u, int uLen) { + if (actualText) { + gfree(actualText); + } + actualText = (Unicode *)gmallocn(uLen, sizeof(Unicode)); + memcpy(actualText, u, uLen * sizeof(Unicode)); + actualTextLen = uLen; + actualTextNBytes = 0; +} + +void TextPage::endActualText(GfxState *state) { + Unicode *u; + + u = actualText; + actualText = NULL; // so we can call TextPage::addChar() + if (actualTextNBytes) { + // now that we have the position info for all of the text inside + // the marked content span, we feed the "ActualText" back through + // addChar() + addChar(state, actualTextX0, actualTextY0, + actualTextX1 - actualTextX0, actualTextY1 - actualTextY0, + 0, actualTextNBytes, u, actualTextLen); + } + gfree(u); + actualText = NULL; + actualTextLen = 0; + actualTextNBytes = gFalse; +} + +void TextPage::addUnderline(double x0, double y0, double x1, double y1) { + underlines->append(new TextUnderline(x0, y0, x1, y1)); +} + +void TextPage::addLink(double xMin, double yMin, double xMax, double yMax, + Link *link) { + GString *uri; + + if (link && link->getAction() && link->getAction()->getKind() == actionURI) { + uri = ((LinkURI *)link->getAction())->getURI()->copy(); + links->append(new TextLink(xMin, yMin, xMax, yMax, uri)); + } +} + +//------------------------------------------------------------------------ +// TextPage: output +//------------------------------------------------------------------------ + +void TextPage::write(void *outputStream, TextOutputFunc outputFunc) { + UnicodeMap *uMap; + char space[8], eol[16], eop[8]; + int spaceLen, eolLen, eopLen; + GBool pageBreaks; + + // get the output encoding + if (!(uMap = globalParams->getTextEncoding())) { + return; + } + spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); + eolLen = 0; // make gcc happy + switch (globalParams->getTextEOL()) { + case eolUnix: + eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); + break; + case eolDOS: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen); + break; + case eolMac: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + break; + } + eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop)); + pageBreaks = globalParams->getTextPageBreaks(); + + switch (control.mode) { + case textOutReadingOrder: + writeReadingOrder(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutPhysLayout: + case textOutTableLayout: + writePhysLayout(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutLinePrinter: + writeLinePrinter(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + case textOutRawOrder: + writeRaw(outputStream, outputFunc, uMap, space, spaceLen, + eol, eolLen); + break; + } + + // end of page + if (pageBreaks) { + (*outputFunc)(outputStream, eop, eopLen); + } + + uMap->decRefCnt(); +} + +void TextPage::writeReadingOrder(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextBlock *tree; + TextColumn *col; + TextParagraph *par; + TextLine *line; + GList *columns; + GBool primaryLR; + GString *s; + int colIdx, parIdx, lineIdx, rot, n; + + rot = rotateChars(chars); + primaryLR = checkPrimaryLR(chars); + tree = splitChars(chars); +#if 0 //~debug + dumpTree(tree); +#endif + if (!tree) { + // no text + unrotateChars(chars, rot); + return; + } + columns = buildColumns(tree); + delete tree; + unrotateChars(chars, rot); + if (control.html) { + rotateUnderlinesAndLinks(rot); + generateUnderlinesAndLinks(columns); + } +#if 0 //~debug + dumpColumns(columns); +#endif + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + n = line->len; + if (line->hyphenated && lineIdx + 1 < par->lines->getLength()) { + --n; + } + s = new GString(); + encodeFragment(line->text, n, uMap, primaryLR, s); + if (lineIdx + 1 < par->lines->getLength() && !line->hyphenated) { + s->append(space, spaceLen); + } + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + } + (*outputFunc)(outputStream, eol, eolLen); + } + (*outputFunc)(outputStream, eol, eolLen); + } + + deleteGList(columns, TextColumn); +} + +GList *TextPage::makeColumns() { + TextBlock *tree; + GList *columns; + + tree = splitChars(chars); + if (!tree) { + // no text + return new GList(); + } + columns = buildColumns(tree); + delete tree; + if (control.html) { + generateUnderlinesAndLinks(columns); + } + return columns; +} + +// This handles both physical layout and table layout modes. +void TextPage::writePhysLayout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextBlock *tree; + GString **out; + int *outLen; + TextColumn *col; + TextParagraph *par; + TextLine *line; + GList *columns; + GBool primaryLR; + int ph, colIdx, parIdx, lineIdx, rot, y, i; + +#if 0 //~debug + dumpChars(chars); +#endif + rot = rotateChars(chars); + primaryLR = checkPrimaryLR(chars); + tree = splitChars(chars); +#if 0 //~debug + dumpTree(tree); +#endif + if (!tree) { + // no text + unrotateChars(chars, rot); + return; + } + columns = buildColumns(tree); + delete tree; + unrotateChars(chars, rot); + if (control.html) { + rotateUnderlinesAndLinks(rot); + generateUnderlinesAndLinks(columns); + } + ph = assignPhysLayoutPositions(columns); +#if 0 //~debug + dumpColumns(columns); +#endif + + out = (GString **)gmallocn(ph, sizeof(GString *)); + outLen = (int *)gmallocn(ph, sizeof(int)); + for (i = 0; i < ph; ++i) { + out[i] = NULL; + outLen[i] = 0; + } + + columns->sort(&TextColumn::cmpPX); + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + y = col->py; + for (parIdx = 0; + parIdx < col->paragraphs->getLength() && y < ph; + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; + lineIdx < par->lines->getLength() && y < ph; + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + if (!out[y]) { + out[y] = new GString(); + } + while (outLen[y] < col->px + line->px) { + out[y]->append(space, spaceLen); + ++outLen[y]; + } + encodeFragment(line->text, line->len, uMap, primaryLR, out[y]); + outLen[y] += line->pw; + ++y; + } + if (parIdx + 1 < col->paragraphs->getLength()) { + ++y; + } + } + } + + for (i = 0; i < ph; ++i) { + if (out[i]) { + (*outputFunc)(outputStream, out[i]->getCString(), out[i]->getLength()); + delete out[i]; + } + (*outputFunc)(outputStream, eol, eolLen); + } + + gfree(out); + gfree(outLen); + + deleteGList(columns, TextColumn); +} + +void TextPage::writeLinePrinter(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextChar *ch, *ch2; + GList *line; + GString *s; + char buf[8]; + double pitch, lineSpacing, delta; + double yMin0, yShift, xMin0, xShift; + double y, x; + int rot, n, i, j, k; + + rot = rotateChars(chars); + chars->sort(&TextChar::cmpX); + removeDuplicates(chars, 0); + chars->sort(&TextChar::cmpY); + + // get character pitch + if (control.fixedPitch > 0) { + pitch = control.fixedPitch; + } else { + // compute (approximate) character pitch + pitch = pageWidth; + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + for (j = i + 1; j < chars->getLength(); ++j) { + ch2 = (TextChar *)chars->get(j); + if (ch2->yMin + ascentAdjustFactor * (ch2->yMax - ch2->yMin) < + ch->yMax - descentAdjustFactor * (ch->yMax - ch->yMin) && + ch->yMin + ascentAdjustFactor * (ch->yMax - ch->yMin) < + ch2->yMax - descentAdjustFactor * (ch2->yMax - ch2->yMin)) { + delta = fabs(ch2->xMin - ch->xMin); + if (delta > 0 && delta < pitch) { + pitch = delta; + } + } + } + } + } + + // get line spacing + if (control.fixedLineSpacing > 0) { + lineSpacing = control.fixedLineSpacing; + } else { + // compute (approximate) line spacing + lineSpacing = pageHeight; + i = 0; + while (i < chars->getLength()) { + ch = (TextChar *)chars->get(i); + // look for the first char that does not (substantially) + // vertically overlap this one + delta = 0; + for (++i; delta == 0 && i < chars->getLength(); ++i) { + ch2 = (TextChar *)chars->get(i); + if (ch2->yMin + ascentAdjustFactor * (ch2->yMax - ch2->yMin) > + ch->yMax - descentAdjustFactor * (ch->yMax - ch->yMin)) { + delta = ch2->yMin - ch->yMin; + } + } + if (delta > 0 && delta < lineSpacing) { + lineSpacing = delta; + } + } + } + + // shift the grid to avoid problems with floating point accuracy -- + // for fixed line spacing, this avoids problems with + // dropping/inserting blank lines + if (chars->getLength()) { + yMin0 = ((TextChar *)chars->get(0))->yMin; + yShift = yMin0 - (int)(yMin0 / lineSpacing + 0.5) * lineSpacing + - 0.5 * lineSpacing; + } else { + yShift = 0; + } + + // for each line... + i = 0; + j = chars->getLength() - 1; + for (y = yShift; y < pageHeight; y += lineSpacing) { + + // get the characters in this line + line = new GList; + while (i < chars->getLength() && + ((TextChar *)chars->get(i))->yMin < y + lineSpacing) { + line->append(chars->get(i++)); + } + line->sort(&TextChar::cmpX); + + // shift the grid to avoid problems with floating point accuracy + // -- for fixed char spacing, this avoids problems with + // dropping/inserting spaces + if (line->getLength()) { + xMin0 = ((TextChar *)line->get(0))->xMin; + xShift = xMin0 - (int)(xMin0 / pitch + 0.5) * pitch - 0.5 * pitch; + } else { + xShift = 0; + } + + // write the line + s = new GString(); + x = xShift; + k = 0; + while (k < line->getLength()) { + ch = (TextChar *)line->get(k); + if (ch->xMin < x + pitch) { + n = uMap->mapUnicode(ch->c, buf, sizeof(buf)); + s->append(buf, n); + ++k; + } else { + s->append(space, spaceLen); + n = spaceLen; + } + x += (uMap->isUnicode() ? 1 : n) * pitch; + } + s->append(eol, eolLen); + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + delete line; + } + + unrotateChars(chars, rot); +} + +void TextPage::writeRaw(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen) { + TextChar *ch, *ch2; + GString *s; + char buf[8]; + int n, i; + + s = new GString(); + + for (i = 0; i < chars->getLength(); ++i) { + + // process one char + ch = (TextChar *)chars->get(i); + n = uMap->mapUnicode(ch->c, buf, sizeof(buf)); + s->append(buf, n); + + // check for space or eol + if (i+1 < chars->getLength()) { + ch2 = (TextChar *)chars->get(i+1); + if (ch2->rot != ch->rot) { + s->append(eol, eolLen); + } else { + switch (ch->rot) { + case 0: + default: + if (fabs(ch2->yMin - ch->yMin) > rawModeLineDelta * ch->fontSize || + ch2->xMin - ch->xMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch2->xMin - ch->xMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + case 1: + if (fabs(ch->xMax - ch2->xMax) > rawModeLineDelta * ch->fontSize || + ch2->yMin - ch->yMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch2->yMin - ch->yMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + case 2: + if (fabs(ch->yMax - ch2->yMax) > rawModeLineDelta * ch->fontSize || + ch->xMin - ch2->xMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch->xMin - ch2->xMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + case 3: + if (fabs(ch2->xMin - ch->xMin) > rawModeLineDelta * ch->fontSize || + ch->yMin - ch2->yMax < -rawModeCharOverlap * ch->fontSize) { + s->append(eol, eolLen); + } else if (ch->yMin - ch2->yMax > + rawModeWordSpacing * ch->fontSize) { + s->append(space, spaceLen); + } + break; + } + } + } else { + s->append(eol, eolLen); + } + + if (s->getLength() > 1000) { + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + s->clear(); + } + } + + if (s->getLength() > 0) { + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + } + delete s; +} + +void TextPage::encodeFragment(Unicode *text, int len, UnicodeMap *uMap, + GBool primaryLR, GString *s) { + char lre[8], rle[8], popdf[8], buf[8]; + int lreLen, rleLen, popdfLen, n; + int i, j, k; + + if (uMap->isUnicode()) { + + lreLen = uMap->mapUnicode(0x202a, lre, sizeof(lre)); + rleLen = uMap->mapUnicode(0x202b, rle, sizeof(rle)); + popdfLen = uMap->mapUnicode(0x202c, popdf, sizeof(popdf)); + + if (primaryLR) { + + i = 0; + while (i < len) { + // output a left-to-right section + for (j = i; j < len && !unicodeTypeR(text[j]); ++j) ; + for (k = i; k < j; ++k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + } + i = j; + // output a right-to-left section + for (j = i; + j < len && !(unicodeTypeL(text[j]) || unicodeTypeNum(text[j])); + ++j) ; + if (j > i) { + s->append(rle, rleLen); + for (k = j - 1; k >= i; --k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + } + s->append(popdf, popdfLen); + i = j; + } + } + + } else { + + // 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) ; + for (k = i; k > j; --k) { + 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) ; + if (j < i) { + s->append(lre, lreLen); + for (k = j + 1; k <= i; ++k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + } + s->append(popdf, popdfLen); + i = j; + } + } + s->append(popdf, popdfLen); + } + + } else { + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(text[i], buf, sizeof(buf)); + s->append(buf, n); + } + } +} + +//------------------------------------------------------------------------ +// TextPage: layout analysis +//------------------------------------------------------------------------ + +// Determine primary (most common) rotation value. Rotate all chars +// to that primary rotation. +int TextPage::rotateChars(GList *charsA) { + TextChar *ch; + int nChars[4]; + double xMin, yMin, xMax, yMax, t; + int rot, i; + + // determine primary rotation + nChars[0] = nChars[1] = nChars[2] = nChars[3] = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + ++nChars[ch->rot]; + } + rot = 0; + for (i = 1; i < 4; ++i) { + if (nChars[i] > nChars[rot]) { + rot = i; + } + } + + // rotate + switch (rot) { + case 0: + default: + break; + case 1: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = ch->yMin; + xMax = ch->yMax; + yMin = pageWidth - ch->xMax; + yMax = pageWidth - ch->xMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 3) & 3; + } + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + break; + case 2: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageWidth - ch->xMax; + xMax = pageWidth - ch->xMin; + yMin = pageHeight - ch->yMax; + yMax = pageHeight - ch->yMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 2) & 3; + } + break; + case 3: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageHeight - ch->yMax; + xMax = pageHeight - ch->yMin; + yMin = ch->xMin; + yMax = ch->xMax; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 1) & 3; + } + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + break; + } + + return rot; +} + +// Rotate the TextUnderlines and TextLinks to match the transform +// performed by rotateChars(). +void TextPage::rotateUnderlinesAndLinks(int rot) { + TextUnderline *underline; + TextLink *link; + double xMin, yMin, xMax, yMax; + int i; + + switch (rot) { + case 0: + default: + break; + case 1: + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + xMin = underline->y0; + xMax = underline->y1; + yMin = pageWidth - underline->x1; + yMax = pageWidth - underline->x0; + underline->x0 = xMin; + underline->x1 = xMax; + underline->y0 = yMin; + underline->y1 = yMax; + underline->horiz = !underline->horiz; + } + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + xMin = link->yMin; + xMax = link->yMax; + yMin = pageWidth - link->xMax; + yMax = pageWidth - link->xMin; + link->xMin = xMin; + link->xMax = xMax; + link->yMin = yMin; + link->yMax = yMax; + } + break; + case 2: + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + xMin = pageWidth - underline->x1; + xMax = pageWidth - underline->x0; + yMin = pageHeight - underline->y1; + yMax = pageHeight - underline->y0; + underline->x0 = xMin; + underline->x1 = xMax; + underline->y0 = yMin; + underline->y1 = yMax; + } + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + xMin = pageWidth - link->xMax; + xMax = pageWidth - link->xMin; + yMin = pageHeight - link->yMax; + yMax = pageHeight - link->yMin; + link->xMin = xMin; + link->xMax = xMax; + link->yMin = yMin; + link->yMax = yMax; + } + break; + case 3: + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + xMin = pageHeight - underline->y1; + xMax = pageHeight - underline->y0; + yMin = underline->x0; + yMax = underline->x1; + underline->x0 = xMin; + underline->x1 = xMax; + underline->y0 = yMin; + underline->y1 = yMax; + underline->horiz = !underline->horiz; + } + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + xMin = pageHeight - link->yMax; + xMax = pageHeight - link->yMin; + yMin = link->xMin; + yMax = link->xMax; + link->xMin = xMin; + link->xMax = xMax; + link->yMin = yMin; + link->yMax = yMax; + } + break; + } +} + +// Undo the coordinate transform performed by rotateChars(). +void TextPage::unrotateChars(GList *charsA, int rot) { + TextChar *ch; + double xMin, yMin, xMax, yMax, t; + int i; + + switch (rot) { + case 0: + default: + // no transform + break; + case 1: + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageWidth - ch->yMax; + xMax = pageWidth - ch->yMin; + yMin = ch->xMin; + yMax = ch->xMax; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 1) & 3; + } + break; + case 2: + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = pageWidth - ch->xMax; + xMax = pageWidth - ch->xMin; + yMin = pageHeight - ch->yMax; + yMax = pageHeight - ch->yMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 2) & 3; + } + break; + case 3: + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xMin = ch->yMin; + xMax = ch->yMax; + yMin = pageHeight - ch->xMax; + yMax = pageHeight - ch->xMin; + ch->xMin = xMin; + ch->xMax = xMax; + ch->yMin = yMin; + ch->yMax = yMax; + ch->rot = (ch->rot + 3) & 3; + } + break; + } +} + +// Undo the coordinate transform performed by rotateChars(). +void TextPage::unrotateColumns(GList *columns, int rot) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + double xMin, yMin, xMax, yMax, t; + int colIdx, parIdx, lineIdx, wordIdx, i; + + switch (rot) { + case 0: + default: + // no transform + break; + case 1: + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + xMin = pageWidth - col->yMax; + xMax = pageWidth - col->yMin; + yMin = col->xMin; + yMax = col->xMax; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = pageWidth - par->yMax; + xMax = pageWidth - par->yMin; + yMin = par->xMin; + yMax = par->xMax; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = pageWidth - line->yMax; + xMax = pageWidth - line->yMin; + yMin = line->xMin; + yMax = line->xMax; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + line->rot = (line->rot + 1) & 3; + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = pageWidth - word->yMax; + xMax = pageWidth - word->yMin; + yMin = word->xMin; + yMax = word->xMax; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 1) & 3; + } + } + } + } + break; + case 2: + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + xMin = pageWidth - col->xMax; + xMax = pageWidth - col->xMin; + yMin = pageHeight - col->yMax; + yMax = pageHeight - col->yMin; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = pageWidth - par->xMax; + xMax = pageWidth - par->xMin; + yMin = pageHeight - par->yMax; + yMax = pageHeight - par->yMin; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = pageWidth - line->xMax; + xMax = pageWidth - line->xMin; + yMin = pageHeight - line->yMax; + yMax = pageHeight - line->yMin; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + line->rot = (line->rot + 2) & 3; + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageWidth - line->edge[i]; + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = pageWidth - word->xMax; + xMax = pageWidth - word->xMin; + yMin = pageHeight - word->yMax; + yMax = pageHeight - word->yMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 2) & 3; + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageWidth - word->edge[i]; + } + } + } + } + } + break; + case 3: + t = pageWidth; + pageWidth = pageHeight; + pageHeight = t; + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + xMin = col->yMin; + xMax = col->yMax; + yMin = pageHeight - col->xMax; + yMax = pageHeight - col->xMin; + col->xMin = xMin; + col->xMax = xMax; + col->yMin = yMin; + col->yMax = yMax; + for (parIdx = 0; + parIdx < col->paragraphs->getLength(); + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + xMin = par->yMin; + xMax = par->yMax; + yMin = pageHeight - par->xMax; + yMax = pageHeight - par->xMin; + par->xMin = xMin; + par->xMax = xMax; + par->yMin = yMin; + par->yMax = yMax; + for (lineIdx = 0; + lineIdx < par->lines->getLength(); + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + xMin = line->yMin; + xMax = line->yMax; + yMin = pageHeight - line->xMax; + yMax = pageHeight - line->xMin; + line->xMin = xMin; + line->xMax = xMax; + line->yMin = yMin; + line->yMax = yMax; + line->rot = (line->rot + 3) & 3; + for (i = 0; i <= line->len; ++i) { + line->edge[i] = pageHeight - line->edge[i]; + } + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + xMin = word->yMin; + xMax = word->yMax; + yMin = pageHeight - word->xMax; + yMax = pageHeight - word->xMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 3) & 3; + for (i = 0; i <= word->len; ++i) { + word->edge[i] = pageHeight - word->edge[i]; + } + } + } + } + } + break; + } +} + +void TextPage::unrotateWords(GList *words, int rot) { + TextWord *word; + double xMin, yMin, xMax, yMax; + int i, j; + + switch (rot) { + case 0: + default: + // no transform + break; + case 1: + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + xMin = pageWidth - word->yMax; + xMax = pageWidth - word->yMin; + yMin = word->xMin; + yMax = word->xMax; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 1) & 3; + } + break; + case 2: + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + xMin = pageWidth - word->xMax; + xMax = pageWidth - word->xMin; + yMin = pageHeight - word->yMax; + yMax = pageHeight - word->yMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 2) & 3; + for (j = 0; j <= word->len; ++j) { + word->edge[j] = pageWidth - word->edge[j]; + } + } + break; + case 3: + for (i = 0; i < words->getLength(); ++i) { + word = (TextWord *)words->get(i); + xMin = word->yMin; + xMax = word->yMax; + yMin = pageHeight - word->xMax; + yMax = pageHeight - word->xMin; + word->xMin = xMin; + word->xMax = xMax; + word->yMin = yMin; + word->yMax = yMax; + word->rot = (word->rot + 3) & 3; + for (j = 0; j <= word->len; ++j) { + word->edge[j] = pageHeight - word->edge[j]; + } + } + break; + } +} + +// Determine the primary text direction (LR vs RL). Returns true for +// LR, false for RL. +GBool TextPage::checkPrimaryLR(GList *charsA) { + TextChar *ch; + int i, lrCount; + + lrCount = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (unicodeTypeL(ch->c)) { + ++lrCount; + } else if (unicodeTypeR(ch->c)) { + --lrCount; + } + } + return lrCount >= 0; +} + +// Remove duplicate characters. The list of chars has been sorted -- +// by x for rot=0,2; by y for rot=1,3. +void TextPage::removeDuplicates(GList *charsA, int rot) { + TextChar *ch, *ch2; + double xDelta, yDelta; + int i, j; + + if (rot & 1) { + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xDelta = dupMaxSecDelta * ch->fontSize; + yDelta = dupMaxPriDelta * ch->fontSize; + j = i + 1; + while (j < charsA->getLength()) { + ch2 = (TextChar *)charsA->get(j); + if (ch2->yMin - ch->yMin >= yDelta) { + break; + } + if (ch2->c == ch->c && + fabs(ch2->xMin - ch->xMin) < xDelta && + fabs(ch2->xMax - ch->xMax) < xDelta && + fabs(ch2->yMax - ch->yMax) < yDelta) { + charsA->del(j); + } else { + ++j; + } + } + } + } else { + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + xDelta = dupMaxPriDelta * ch->fontSize; + yDelta = dupMaxSecDelta * ch->fontSize; + j = i + 1; + while (j < charsA->getLength()) { + ch2 = (TextChar *)charsA->get(j); + if (ch2->xMin - ch->xMin >= xDelta) { + break; + } + if (ch2->c == ch->c && + fabs(ch2->xMax - ch->xMax) < xDelta && + fabs(ch2->yMin - ch->yMin) < yDelta && + fabs(ch2->yMax - ch->yMax) < yDelta) { + charsA->del(j); + } else { + ++j; + } + } + } + } +} + +// Split the characters into trees of TextBlocks, one tree for each +// rotation. Merge into a single tree (with the primary rotation). +TextBlock *TextPage::splitChars(GList *charsA) { + TextBlock *tree[4]; + TextBlock *blk; + GList *chars2, *clippedChars; + TextChar *ch; + int rot, i; + + // split: build a tree of TextBlocks for each rotation + clippedChars = new GList(); + for (rot = 0; rot < 4; ++rot) { + chars2 = new GList(); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->rot == rot) { + chars2->append(ch); + } + } + tree[rot] = NULL; + if (chars2->getLength() > 0) { + chars2->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); + removeDuplicates(chars2, rot); + if (control.clipText) { + i = 0; + while (i < chars2->getLength()) { + ch = (TextChar *)chars2->get(i); + if (ch->clipped) { + ch = (TextChar *)chars2->del(i); + clippedChars->append(ch); + } else { + ++i; + } + } + } + if (chars2->getLength() > 0) { + tree[rot] = split(chars2, rot); + } + } + delete chars2; + } + + // if the page contains no (unclipped) text, just leave an empty + // column list + if (!tree[0]) { + delete clippedChars; + return NULL; + } + + // if the main tree is not a multicolumn node, insert one so that + // rotated text has somewhere to go + if (tree[0]->tag != blkTagMulticolumn) { + blk = new TextBlock(blkHorizSplit, 0); + blk->addChild(tree[0]); + blk->tag = blkTagMulticolumn; + tree[0] = blk; + } + + // merge non-primary-rotation text into the primary-rotation tree + for (rot = 1; rot < 4; ++rot) { + if (tree[rot]) { + insertIntoTree(tree[rot], tree[0]); + tree[rot] = NULL; + } + } + + if (clippedChars->getLength()) { + insertClippedChars(clippedChars, tree[0]); + } + delete clippedChars; + +#if 0 //~debug + dumpTree(tree[0]); +#endif + + return tree[0]; +} + +// Generate a tree of TextBlocks, marked as columns, lines, and words. +TextBlock *TextPage::split(GList *charsA, int rot) { + TextBlock *blk; + GList *chars2, *chars3; + int *horizProfile, *vertProfile; + double xMin, yMin, xMax, yMax; + int xMinI, yMinI, xMaxI, yMaxI; + int xMinI2, yMinI2, xMaxI2, yMaxI2; + TextChar *ch; + double minFontSize, avgFontSize, splitPrecision; + double nLines, vertGapThreshold, ascentAdjust, descentAdjust, minChunk; + int horizGapSize, vertGapSize; + double horizGapSize2, vertGapSize2; + int minHorizChunkWidth, minVertChunkWidth, nHorizGaps, nVertGaps; + double largeCharSize; + int nLargeChars; + GBool doHorizSplit, doVertSplit, smallSplit; + int i, x, y, prev, start; + + //----- compute bbox, min font size, average font size, and + // split precision for this block + + xMin = yMin = xMax = yMax = 0; // make gcc happy + minFontSize = avgFontSize = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (i == 0 || ch->xMin < xMin) { + xMin = ch->xMin; + } + if (i == 0 || ch->yMin < yMin) { + yMin = ch->yMin; + } + if (i == 0 || ch->xMax > xMax) { + xMax = ch->xMax; + } + if (i == 0 || ch->yMax > yMax) { + yMax = ch->yMax; + } + avgFontSize += ch->fontSize; + if (i == 0 || ch->fontSize < minFontSize) { + minFontSize = ch->fontSize; + } + } + avgFontSize /= charsA->getLength(); + splitPrecision = splitPrecisionMul * minFontSize; + if (splitPrecision < minSplitPrecision) { + splitPrecision = minSplitPrecision; + } + + //----- compute the horizontal and vertical profiles + + // add some slack to the array bounds to avoid floating point + // precision problems + xMinI = (int)floor(xMin / splitPrecision) - 1; + yMinI = (int)floor(yMin / splitPrecision) - 1; + xMaxI = (int)floor(xMax / splitPrecision) + 1; + yMaxI = (int)floor(yMax / splitPrecision) + 1; + horizProfile = (int *)gmallocn(yMaxI - yMinI + 1, sizeof(int)); + vertProfile = (int *)gmallocn(xMaxI - xMinI + 1, sizeof(int)); + memset(horizProfile, 0, (yMaxI - yMinI + 1) * sizeof(int)); + memset(vertProfile, 0, (xMaxI - xMinI + 1) * sizeof(int)); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + // yMinI2 and yMaxI2 are adjusted to allow for slightly overlapping lines + switch (rot) { + case 0: + default: + xMinI2 = (int)floor(ch->xMin / splitPrecision); + xMaxI2 = (int)floor(ch->xMax / splitPrecision); + ascentAdjust = ascentAdjustFactor * (ch->yMax - ch->yMin); + yMinI2 = (int)floor((ch->yMin + ascentAdjust) / splitPrecision); + descentAdjust = descentAdjustFactor * (ch->yMax - ch->yMin); + yMaxI2 = (int)floor((ch->yMax - descentAdjust) / splitPrecision); + break; + case 1: + descentAdjust = descentAdjustFactor * (ch->xMax - ch->xMin); + xMinI2 = (int)floor((ch->xMin + descentAdjust) / splitPrecision); + ascentAdjust = ascentAdjustFactor * (ch->xMax - ch->xMin); + xMaxI2 = (int)floor((ch->xMax - ascentAdjust) / splitPrecision); + yMinI2 = (int)floor(ch->yMin / splitPrecision); + yMaxI2 = (int)floor(ch->yMax / splitPrecision); + break; + case 2: + xMinI2 = (int)floor(ch->xMin / splitPrecision); + xMaxI2 = (int)floor(ch->xMax / splitPrecision); + descentAdjust = descentAdjustFactor * (ch->yMax - ch->yMin); + yMinI2 = (int)floor((ch->yMin + descentAdjust) / splitPrecision); + ascentAdjust = ascentAdjustFactor * (ch->yMax - ch->yMin); + yMaxI2 = (int)floor((ch->yMax - ascentAdjust) / splitPrecision); + break; + case 3: + ascentAdjust = ascentAdjustFactor * (ch->xMax - ch->xMin); + xMinI2 = (int)floor((ch->xMin + ascentAdjust) / splitPrecision); + descentAdjust = descentAdjustFactor * (ch->xMax - ch->xMin); + xMaxI2 = (int)floor((ch->xMax - descentAdjust) / splitPrecision); + yMinI2 = (int)floor(ch->yMin / splitPrecision); + yMaxI2 = (int)floor(ch->yMax / splitPrecision); + break; + } + for (y = yMinI2; y <= yMaxI2; ++y) { + ++horizProfile[y - yMinI]; + } + for (x = xMinI2; x <= xMaxI2; ++x) { + ++vertProfile[x - xMinI]; + } + } + + //----- find the largest gaps in the horizontal and vertical profiles + + horizGapSize = 0; + for (start = yMinI; start < yMaxI && !horizProfile[start - yMinI]; ++start) ; + for (y = start; y < yMaxI; ++y) { + if (horizProfile[y - yMinI] && !horizProfile[y + 1 - yMinI]) { + start = y; + } else if (!horizProfile[y - yMinI] && horizProfile[y + 1 - yMinI]) { + if (y - start > horizGapSize) { + horizGapSize = y - start; + } + } + } + vertGapSize = 0; + for (start = xMinI; start < xMaxI && !vertProfile[start - xMinI]; ++start) ; + for (x = start; x < xMaxI; ++x) { + if (vertProfile[x - xMinI] && !vertProfile[x + 1 - xMinI]) { + start = x; + } else if (!vertProfile[x - xMinI] && vertProfile[x + 1 - xMinI]) { + if (x - start > vertGapSize) { + vertGapSize = x - start; + } + } + } + horizGapSize2 = horizGapSize - splitGapSlack * avgFontSize / splitPrecision; + if (horizGapSize2 < 0.99) { + horizGapSize2 = 0.99; + } + vertGapSize2 = vertGapSize - splitGapSlack * avgFontSize / splitPrecision; + if (vertGapSize2 < 0.99) { + vertGapSize2 = 0.99; + } + + //----- count horiz/vert gaps equivalent to largest gaps + + minHorizChunkWidth = yMaxI - yMinI; + nHorizGaps = 0; + for (start = yMinI; start < yMaxI && !horizProfile[start - yMinI]; ++start) ; + prev = start - 1; + for (y = start; y < yMaxI; ++y) { + if (horizProfile[y - yMinI] && !horizProfile[y + 1 - yMinI]) { + start = y; + } else if (!horizProfile[y - yMinI] && horizProfile[y + 1 - yMinI]) { + if (y - start > horizGapSize2) { + ++nHorizGaps; + if (start - prev < minHorizChunkWidth) { + minHorizChunkWidth = start - prev; + } + prev = y; + } + } + } + minVertChunkWidth = xMaxI - xMinI; + nVertGaps = 0; + for (start = xMinI; start < xMaxI && !vertProfile[start - xMinI]; ++start) ; + prev = start - 1; + for (x = start; x < xMaxI; ++x) { + if (vertProfile[x - xMinI] && !vertProfile[x + 1 - xMinI]) { + start = x; + } else if (!vertProfile[x - xMinI] && vertProfile[x + 1 - xMinI]) { + if (x - start > vertGapSize2) { + ++nVertGaps; + if (start - prev < minVertChunkWidth) { + minVertChunkWidth = start - prev; + } + prev = x; + } + } + } + + //----- 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 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; + } + } else { + vertGapThreshold = vertGapThresholdMax + vertGapThresholdSlope * nLines; + if (vertGapThreshold < vertGapThresholdMin) { + vertGapThreshold = vertGapThresholdMin; + } + } + vertGapThreshold = vertGapThreshold * avgFontSize / splitPrecision; + + // compute the minimum allowed chunk width + if (control.mode == textOutTableLayout) { + minChunk = 0; + } else { + minChunk = vertSplitChunkThreshold * avgFontSize / splitPrecision; + } + + // look for large chars + // -- this kludge (multiply by 256, convert to int, divide by 256.0) + // prevents floating point stability issues on x86 with gcc, where + // largeCharSize could otherwise have slightly different values + // here and where it's used below to do the large char partition + // (because it gets truncated from 80 to 64 bits when spilled) + largeCharSize = (int)(largeCharThreshold * avgFontSize * 256) / 256.0; + nLargeChars = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->fontSize > largeCharSize) { + ++nLargeChars; + } + } + + // figure out which type of split to do + doHorizSplit = doVertSplit = gFalse; + smallSplit = gFalse; + if (rot & 1) { + if (nHorizGaps > 0 && + (horizGapSize > vertGapSize || control.mode == textOutTableLayout) && + horizGapSize > vertGapThreshold && + minHorizChunkWidth > minChunk) { + doHorizSplit = gTrue; + } else if (nVertGaps > 0) { + doVertSplit = gTrue; + } else if (nLargeChars == 0 && nHorizGaps > 0) { + doHorizSplit = gTrue; + smallSplit = gTrue; + } + } else { + if (nVertGaps > 0 && + (vertGapSize > horizGapSize || control.mode == textOutTableLayout) && + vertGapSize > vertGapThreshold && + minVertChunkWidth > minChunk) { + doVertSplit = gTrue; + } else if (nHorizGaps > 0) { + doHorizSplit = gTrue; + } else if (nLargeChars == 0 && nVertGaps > 0) { + doVertSplit = gTrue; + smallSplit = gTrue; + } + } + + //----- split the block + + //~ this could use "other content" (vector graphics, rotated text) -- + //~ presence of other content in a gap means we should definitely split + + // split vertically + if (doVertSplit) { + blk = new TextBlock(blkVertSplit, rot); + blk->smallSplit = smallSplit; + for (start = xMinI; start < xMaxI && !vertProfile[start - xMinI]; ++start) ; + prev = start - 1; + for (x = start; x < xMaxI; ++x) { + if (vertProfile[x - xMinI] && !vertProfile[x + 1 - xMinI]) { + start = x; + } else if (!vertProfile[x - xMinI] && vertProfile[x + 1 - xMinI]) { + if (x - start > vertGapSize2) { + chars2 = getChars(charsA, (prev + 0.5) * splitPrecision, yMin - 1, + (start + 1.5) * splitPrecision, yMax + 1); + blk->addChild(split(chars2, rot)); + delete chars2; + prev = x; + } + } + } + chars2 = getChars(charsA, (prev + 0.5) * splitPrecision, yMin - 1, + xMax + 1, yMax + 1); + blk->addChild(split(chars2, rot)); + delete chars2; + + // split horizontally + } else if (doHorizSplit) { + blk = new TextBlock(blkHorizSplit, rot); + blk->smallSplit = smallSplit; + for (start = yMinI; + start < yMaxI && !horizProfile[start - yMinI]; + ++start) ; + prev = start - 1; + for (y = start; y < yMaxI; ++y) { + if (horizProfile[y - yMinI] && !horizProfile[y + 1 - yMinI]) { + start = y; + } else if (!horizProfile[y - yMinI] && horizProfile[y + 1 - yMinI]) { + if (y - start > horizGapSize2) { + chars2 = getChars(charsA, xMin - 1, (prev + 0.5) * splitPrecision, + xMax + 1, (start + 1.5) * splitPrecision); + blk->addChild(split(chars2, rot)); + delete chars2; + prev = y; + } + } + } + chars2 = getChars(charsA, xMin - 1, (prev + 0.5) * splitPrecision, + xMax + 1, yMax + 1); + blk->addChild(split(chars2, rot)); + delete chars2; + + // split into larger and smaller chars + } else if (nLargeChars > 0) { + chars2 = new GList(); + chars3 = new GList(); + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + if (ch->fontSize > largeCharSize) { + chars2->append(ch); + } else { + chars3->append(ch); + } + } + blk = split(chars3, rot); + insertLargeChars(chars2, blk); + delete chars2; + delete chars3; + + // create a leaf node + } else { + blk = new TextBlock(blkLeaf, rot); + for (i = 0; i < charsA->getLength(); ++i) { + blk->addChild((TextChar *)charsA->get(i)); + } + } + + gfree(horizProfile); + gfree(vertProfile); + + tagBlock(blk); + + return blk; +} + +// Return the subset of chars inside a rectangle. +GList *TextPage::getChars(GList *charsA, double xMin, double yMin, + double xMax, double yMax) { + GList *ret; + TextChar *ch; + double x, y; + int i; + + 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 + x = 0.5 * (ch->xMin + ch->xMax); + y = 0.5 * (ch->yMin + ch->yMax); + if (x > xMin && x < xMax && y > yMin && y < yMax) { + ret->append(ch); + } + } + return ret; +} + +// Decide whether this block is a line, column, or multiple columns: +// - all leaf nodes are lines +// - horiz split nodes whose children are lines or columns are columns +// - other horiz split nodes are multiple columns +// - vert split nodes, with small gaps, whose children are lines are lines +// - other vert split nodes are multiple columns +// (for rot=1,3: the horiz and vert splits are swapped) +// In table layout mode: +// - all leaf nodes are lines +// - vert split nodes, with small gaps, whose children are lines are lines +// - everything else is multiple columns +void TextPage::tagBlock(TextBlock *blk) { + TextBlock *child; + int i; + + if (control.mode == textOutTableLayout) { + if (blk->type == blkLeaf) { + blk->tag = blkTagLine; + } else if (blk->type == ((blk->rot & 1) ? blkHorizSplit : blkVertSplit) && + blk->smallSplit) { + blk->tag = blkTagLine; + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (child->tag != blkTagLine) { + blk->tag = blkTagMulticolumn; + break; + } + } + } else { + blk->tag = blkTagMulticolumn; + } + return; + } + + if (blk->type == blkLeaf) { + blk->tag = blkTagLine; + + } else { + if (blk->type == ((blk->rot & 1) ? blkVertSplit : blkHorizSplit)) { + blk->tag = blkTagColumn; + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (child->tag != blkTagColumn && child->tag != blkTagLine) { + blk->tag = blkTagMulticolumn; + break; + } + } + } else { + if (blk->smallSplit) { + blk->tag = blkTagLine; + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (child->tag != blkTagLine) { + blk->tag = blkTagMulticolumn; + break; + } + } + } else { + blk->tag = blkTagMulticolumn; + } + } + } +} + +// Insert a list of large characters into a tree. +void TextPage::insertLargeChars(GList *largeChars, TextBlock *blk) { + TextChar *ch, *ch2; + GBool singleLine; + double xLimit, yLimit, minOverlap; + int i; + + //~ this currently works only for characters in the primary rotation + + // check to see if the large chars are a single line, in the + // upper-left corner of blk (this is just a rough estimate) + xLimit = blk->xMin + 0.5 * (blk->xMin + blk->xMax); + yLimit = blk->yMin + 0.5 * (blk->yMin + blk->yMax); + singleLine = gTrue; + // note: largeChars are already sorted by x + for (i = 0; i < largeChars->getLength(); ++i) { + ch2 = (TextChar *)largeChars->get(i); + if (ch2->xMax > xLimit || ch2->yMax > yLimit) { + singleLine = gFalse; + break; + } + if (i > 0) { + ch = (TextChar *)largeChars->get(i-1); + minOverlap = 0.5 * (ch->fontSize < ch2->fontSize ? ch->fontSize + : ch2->fontSize); + if (ch->yMax - ch2->yMin < minOverlap || + ch2->yMax - ch->yMin < minOverlap) { + singleLine = gFalse; + break; + } + } + } + + if (singleLine) { + // if the large chars are a single line, prepend them to the first + // leaf node in blk + insertLargeCharsInFirstLeaf(largeChars, blk); + } else { + // if the large chars are not a single line, prepend each one to + // the appropriate leaf node -- this handles cases like bullets + // drawn in a large font, on the left edge of a column + for (i = largeChars->getLength() - 1; i >= 0; --i) { + ch = (TextChar *)largeChars->get(i); + insertLargeCharInLeaf(ch, blk); + } + } +} + +// Find the first leaf (in depth-first order) in blk, and prepend a +// list of large chars. +void TextPage::insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk) { + TextChar *ch; + int i; + + if (blk->type == blkLeaf) { + for (i = largeChars->getLength() - 1; i >= 0; --i) { + ch = (TextChar *)largeChars->get(i); + blk->prependChild(ch); + } + } else { + insertLargeCharsInFirstLeaf(largeChars, (TextBlock *)blk->children->get(0)); + blk->updateBounds(0); + } +} + +// Find the leaf in <blk> where large char <ch> belongs, and prepend +// it. +void TextPage::insertLargeCharInLeaf(TextChar *ch, TextBlock *blk) { + TextBlock *child; + double y; + int i; + + //~ this currently works only for characters in the primary rotation + + //~ this currently just looks down the left edge of blk + //~ -- it could be extended to do more + + // estimate the baseline of ch + y = ch->yMin + 0.75 * (ch->yMax - ch->yMin); + + if (blk->type == blkLeaf) { + blk->prependChild(ch); + } else if (blk->type == blkHorizSplit) { + for (i = 0; i < blk->children->getLength(); ++i) { + child = (TextBlock *)blk->children->get(i); + if (y < child->yMax || i == blk->children->getLength() - 1) { + insertLargeCharInLeaf(ch, child); + blk->updateBounds(i); + break; + } + } + } else { + insertLargeCharInLeaf(ch, (TextBlock *)blk->children->get(0)); + blk->updateBounds(0); + } +} + +// Merge blk (rot != 0) into primaryTree (rot == 0). +void TextPage::insertIntoTree(TextBlock *blk, TextBlock *primaryTree) { + TextBlock *child; + + // we insert a whole column at a time - so call insertIntoTree + // recursively until we get to a column (or line) + + if (blk->tag == blkTagMulticolumn) { + while (blk->children->getLength()) { + child = (TextBlock *)blk->children->del(0); + insertIntoTree(child, primaryTree); + } + delete blk; + } else { + insertColumnIntoTree(blk, primaryTree); + } +} + +// Insert a column (as an atomic subtree) into tree. +// Requirement: tree is not a leaf node. +void TextPage::insertColumnIntoTree(TextBlock *column, TextBlock *tree) { + TextBlock *child; + int i; + + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (child->tag == blkTagMulticolumn && + column->xMin >= child->xMin && + column->yMin >= child->yMin && + column->xMax <= child->xMax && + column->yMax <= child->yMax) { + insertColumnIntoTree(column, child); + tree->tag = blkTagMulticolumn; + return; + } + } + + if (tree->type == blkVertSplit) { + if (tree->rot == 1 || tree->rot == 2) { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->xMax > 0.5 * (child->xMin + child->xMax)) { + break; + } + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->xMin < 0.5 * (child->xMin + child->xMax)) { + break; + } + } + } + } else if (tree->type == blkHorizSplit) { + if (tree->rot >= 2) { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->yMax > 0.5 * (child->yMin + child->yMax)) { + break; + } + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if (column->yMin < 0.5 * (child->yMin + child->yMax)) { + break; + } + } + } + } else { + // this should never happen + return; + } + tree->children->insert(i, column); + tree->tag = blkTagMulticolumn; +} + +// Insert clipped characters back into the TextBlock tree. +void TextPage::insertClippedChars(GList *clippedChars, TextBlock *tree) { + TextChar *ch, *ch2; + TextBlock *leaf; + double y; + int i; + + //~ this currently works only for characters in the primary rotation + + clippedChars->sort(TextChar::cmpX); + while (clippedChars->getLength()) { + ch = (TextChar *)clippedChars->del(0); + if (ch->rot != 0) { + continue; + } + if (!(leaf = findClippedCharLeaf(ch, tree))) { + continue; + } + leaf->addChild(ch); + i = 0; + while (i < clippedChars->getLength()) { + ch2 = (TextChar *)clippedChars->get(i); + if (ch2->xMin > ch->xMax + clippedTextMaxWordSpace * ch->fontSize) { + break; + } + y = 0.5 * (ch2->yMin + ch2->yMax); + if (y > leaf->yMin && y < leaf->yMax) { + ch2 = (TextChar *)clippedChars->del(i); + leaf->addChild(ch2); + ch = ch2; + } else { + ++i; + } + } + } +} + +// Find the leaf in <tree> to which clipped char <ch> can be appended. +// Returns NULL if there is no appropriate append point. +TextBlock *TextPage::findClippedCharLeaf(TextChar *ch, TextBlock *tree) { + TextBlock *ret, *child; + double y; + int i; + + //~ this currently works only for characters in the primary rotation + + y = 0.5 * (ch->yMin + ch->yMax); + if (tree->type == blkLeaf) { + if (tree->rot == 0) { + if (y > tree->yMin && y < tree->yMax && + ch->xMin <= tree->xMax + clippedTextMaxWordSpace * ch->fontSize) { + return tree; + } + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + child = (TextBlock *)tree->children->get(i); + if ((ret = findClippedCharLeaf(ch, child))) { + return ret; + } + } + } + return NULL; +} + +// Convert the tree of TextBlocks into a list of TextColumns. +GList *TextPage::buildColumns(TextBlock *tree) { + GList *columns; + + columns = new GList(); + buildColumns2(tree, columns); + return columns; +} + +void TextPage::buildColumns2(TextBlock *blk, GList *columns) { + TextColumn *col; + int i; + + switch (blk->tag) { + case blkTagLine: + case blkTagColumn: + col = buildColumn(blk); + columns->append(col); + break; + case blkTagMulticolumn: + for (i = 0; i < blk->children->getLength(); ++i) { + buildColumns2((TextBlock *)blk->children->get(i), columns); + } + break; + } +} + +TextColumn *TextPage::buildColumn(TextBlock *blk) { + GList *lines, *parLines; + GList *paragraphs; + TextLine *line0, *line1; + double spaceThresh, indent0, indent1, fontSize0, fontSize1; + int i; + + lines = new GList(); + buildLines(blk, lines); + + spaceThresh = paragraphSpacingThreshold * getAverageLineSpacing(lines); + + //~ could look for bulleted lists here: look for the case where + //~ all out-dented lines start with the same char + + // build the paragraphs + paragraphs = new GList(); + i = 0; + while (i < lines->getLength()) { + + // get the first line of the paragraph + parLines = new GList(); + line0 = (TextLine *)lines->get(i); + parLines->append(line0); + ++i; + + if (i < lines->getLength()) { + line1 = (TextLine *)lines->get(i); + indent0 = getLineIndent(line0, blk); + indent1 = getLineIndent(line1, blk); + fontSize0 = line0->fontSize; + fontSize1 = line1->fontSize; + + // inverted indent + if (indent1 - indent0 > minParagraphIndent * fontSize0 && + fabs(fontSize0 - fontSize1) <= paragraphFontSizeDelta && + getLineSpacing(line0, line1) <= spaceThresh) { + parLines->append(line1); + indent0 = indent1; + for (++i; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + fontSize1 = line1->fontSize; + if (indent0 - indent1 > minParagraphIndent * fontSize0) { + break; + } + if (fabs(fontSize0 - fontSize1) > paragraphFontSizeDelta) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + + // drop cap + } else if (fontSize0 > largeCharThreshold * fontSize1 && + indent1 - indent0 > minParagraphIndent * fontSize1 && + getLineSpacing(line0, line1) < 0) { + parLines->append(line1); + fontSize0 = fontSize1; + for (++i; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + if (indent1 - indent0 <= minParagraphIndent * fontSize0) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + for (; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + fontSize1 = line1->fontSize; + if (indent1 - indent0 > minParagraphIndent * fontSize0) { + break; + } + if (fabs(fontSize0 - fontSize1) > paragraphFontSizeDelta) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + + // regular indent or no indent + } else if (fabs(fontSize0 - fontSize1) <= paragraphFontSizeDelta && + getLineSpacing(line0, line1) <= spaceThresh) { + parLines->append(line1); + indent0 = indent1; + for (++i; i < lines->getLength(); ++i) { + line1 = (TextLine *)lines->get(i); + indent1 = getLineIndent(line1, blk); + fontSize1 = line1->fontSize; + if (indent1 - indent0 > minParagraphIndent * fontSize0) { + break; + } + if (fabs(fontSize0 - fontSize1) > paragraphFontSizeDelta) { + break; + } + if (getLineSpacing((TextLine *)lines->get(i - 1), line1) + > spaceThresh) { + break; + } + parLines->append(line1); + } + } + } + + paragraphs->append(new TextParagraph(parLines)); + } + + delete lines; + + return new TextColumn(paragraphs, blk->xMin, blk->yMin, + blk->xMax, blk->yMax); +} + +double TextPage::getLineIndent(TextLine *line, TextBlock *blk) { + double indent; + + switch (line->rot) { + case 0: + default: indent = line->xMin - blk->xMin; break; + case 1: indent = line->yMin - blk->yMin; break; + case 2: indent = blk->xMax - line->xMax; break; + case 3: indent = blk->yMax - line->yMax; break; + } + return indent; +} + +// Compute average line spacing in column. +double TextPage::getAverageLineSpacing(GList *lines) { + double avg, sp; + int n, i; + + avg = 0; + n = 0; + for (i = 1; i < lines->getLength(); ++i) { + sp = getLineSpacing((TextLine *)lines->get(i - 1), + (TextLine *)lines->get(i)); + if (sp > 0) { + avg += sp; + ++n; + } + } + if (n > 0) { + avg /= n; + } + return avg; +} + +// Compute the space between two lines. +double TextPage::getLineSpacing(TextLine *line0, TextLine *line1) { + double sp; + + switch (line0->rot) { + case 0: + default: sp = line1->yMin - line0->yMax; break; + case 1: sp = line0->xMin - line1->xMax; break; + case 2: sp = line0->yMin - line1->yMin; break; + case 3: sp = line1->xMin - line1->xMax; break; + } + return sp; +} + +void TextPage::buildLines(TextBlock *blk, GList *lines) { + TextLine *line; + int i; + + switch (blk->tag) { + case blkTagLine: + line = buildLine(blk); + if (blk->rot == 1 || blk->rot == 2) { + lines->insert(0, line); + } else { + lines->append(line); + } + break; + case blkTagColumn: + case blkTagMulticolumn: // multicolumn should never happen here + for (i = 0; i < blk->children->getLength(); ++i) { + buildLines((TextBlock *)blk->children->get(i), lines); + } + break; + } +} + +TextLine *TextPage::buildLine(TextBlock *blk) { + GList *charsA; + GList *words; + TextChar *ch, *ch2; + TextWord *word; + double wordSp, lineFontSize, sp; + GBool spaceAfter, spaceAfter2; + int i, j; + + charsA = new GList(); + getLineChars(blk, charsA); + + wordSp = computeWordSpacingThreshold(charsA, blk->rot); + + words = new GList(); + lineFontSize = 0; + spaceAfter = gFalse; + i = 0; + while (i < charsA->getLength()) { + sp = wordSp - 1; + for (j = i+1; j < charsA->getLength(); ++j) { + ch = (TextChar *)charsA->get(j-1); + ch2 = (TextChar *)charsA->get(j); + sp = (blk->rot & 1) ? (ch2->yMin - ch->yMax) : (ch2->xMin - ch->xMax); + if (sp > wordSp || + ch->font != ch2->font || + fabs(ch->fontSize - ch2->fontSize) > 0.01 || + (control.mode == textOutRawOrder && + ch2->charPos != ch->charPos + ch->charLen)) { + break; + } + sp = wordSp - 1; + } + spaceAfter2 = spaceAfter; + spaceAfter = sp > wordSp; + word = new TextWord(charsA, i, j - i, blk->rot, + (blk->rot >= 2) ? spaceAfter2 : spaceAfter); + i = j; + if (blk->rot >= 2) { + words->insert(0, word); + } else { + words->append(word); + } + if (i == 0 || word->fontSize > lineFontSize) { + lineFontSize = word->fontSize; + } + } + + delete charsA; + + return new TextLine(words, blk->xMin, blk->yMin, blk->xMax, blk->yMax, + lineFontSize); +} + +void TextPage::getLineChars(TextBlock *blk, GList *charsA) { + int i; + + if (blk->type == blkLeaf) { + charsA->append(blk->children); + } else { + for (i = 0; i < blk->children->getLength(); ++i) { + getLineChars((TextBlock *)blk->children->get(i), charsA); + } + } +} + +// Compute the inter-word spacing threshold for a line of chars. +// Spaces greater than this threshold will be considered inter-word +// spaces. +double TextPage::computeWordSpacingThreshold(GList *charsA, int rot) { + TextChar *ch, *ch2; + double avgFontSize, minSp, maxSp, sp; + int i; + + avgFontSize = 0; + minSp = maxSp = 0; + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + avgFontSize += ch->fontSize; + if (i < charsA->getLength() - 1) { + ch2 = (TextChar *)charsA->get(i+1); + sp = (rot & 1) ? (ch2->yMin - ch->yMax) : (ch2->xMin - ch->xMax); + if (i == 0 || sp < minSp) { + minSp = sp; + } + if (sp > maxSp) { + maxSp = sp; + } + } + } + avgFontSize /= charsA->getLength(); + if (minSp < 0) { + minSp = 0; + } + + // if spacing is completely uniform, assume it's a single word + // (technically it could be either "ABC" or "A B C", but it's + // essentially impossible to tell) + if (maxSp - minSp < uniformSpacing * avgFontSize) { + return maxSp + 1; + + // if there is some variation in spacing, but it's small, assume + // there are some inter-word spaces + } else if (maxSp - minSp < wordSpacing * avgFontSize) { + return 0.5 * (minSp + maxSp); + + // otherwise, assume a reasonable threshold for inter-word spacing + // (we can't use something like 0.5*(minSp+maxSp) here because there + // can be outliers at the high end) + } else { + return minSp + wordSpacing * avgFontSize; + } +} + +int TextPage::assignPhysLayoutPositions(GList *columns) { + assignLinePhysPositions(columns); + return assignColumnPhysPositions(columns); +} + +// Assign a physical x coordinate for each TextLine (relative to the +// containing TextColumn). This also computes TextColumn width and +// height. +void TextPage::assignLinePhysPositions(GList *columns) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + UnicodeMap *uMap; + int colIdx, parIdx, lineIdx; + + if (!(uMap = globalParams->getTextEncoding())) { + return; + } + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + col->pw = col->ph = 0; + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + computeLinePhysWidth(line, uMap); + if (control.fixedPitch > 0) { + line->px = (int)((line->xMin - col->xMin) / control.fixedPitch); + } else if (fabs(line->fontSize) < 0.001) { + line->px = 0; + } else { + line->px = (int)((line->xMin - col->xMin) / + (physLayoutSpaceWidth * line->fontSize)); + } + if (line->px + line->pw > col->pw) { + col->pw = line->px + line->pw; + } + } + col->ph += par->lines->getLength(); + } + col->ph += col->paragraphs->getLength() - 1; + } + + uMap->decRefCnt(); +} + +void TextPage::computeLinePhysWidth(TextLine *line, UnicodeMap *uMap) { + char buf[8]; + int n, i; + + if (uMap->isUnicode()) { + line->pw = line->len; + } else { + line->pw = 0; + for (i = 0; i < line->len; ++i) { + n = uMap->mapUnicode(line->text[i], buf, sizeof(buf)); + line->pw += n; + } + } +} + +// Assign physical x and y coordinates for each TextColumn. Returns +// the text height (max physical y + 1). +int TextPage::assignColumnPhysPositions(GList *columns) { + TextColumn *col, *col2; + double slack, xOverlap, yOverlap; + int ph, i, j; + + if (control.mode == textOutTableLayout) { + slack = tableCellOverlapSlack; + } else { + slack = 0; + } + + // assign x positions + columns->sort(&TextColumn::cmpX); + for (i = 0; i < columns->getLength(); ++i) { + col = (TextColumn *)columns->get(i); + if (control.fixedPitch) { + col->px = (int)(col->xMin / control.fixedPitch); + } else { + col->px = 0; + for (j = 0; j < i; ++j) { + col2 = (TextColumn *)columns->get(j); + xOverlap = col2->xMax - col->xMin; + if (xOverlap < slack * (col2->xMax - col2->xMin)) { + if (col2->px + col2->pw + 2 > col->px) { + col->px = col2->px + col2->pw + 2; + } + } else { + yOverlap = (col->yMax < col2->yMax ? col->yMax : col2->yMax) - + (col->yMin > col2->yMin ? col->yMin : col2->yMin); + if (yOverlap > 0 && xOverlap < yOverlap) { + if (col2->px + col2->pw > col->px) { + col->px = col2->px + col2->pw; + } + } else { + if (col2->px > col->px) { + col->px = col2->px; + } + } + } + } + } + } + + // assign y positions + ph = 0; + columns->sort(&TextColumn::cmpY); + for (i = 0; i < columns->getLength(); ++i) { + col = (TextColumn *)columns->get(i); + col->py = 0; + for (j = 0; j < i; ++j) { + col2 = (TextColumn *)columns->get(j); + yOverlap = col2->yMax - col->yMin; + if (yOverlap < slack * (col2->yMax - col2->yMin)) { + if (col2->py + col2->ph + 1 > col->py) { + col->py = col2->py + col2->ph + 1; + } + } else { + xOverlap = (col->xMax < col2->xMax ? col->xMax : col2->xMax) - + (col->xMin > col2->xMin ? col->xMin : col2->xMin); + if (xOverlap > 0 && yOverlap < xOverlap) { + if (col2->py + col2->ph > col->py) { + col->py = col2->py + col2->ph; + } + } else { + if (col2->py > col->py) { + col->py = col2->py; + } + } + } + } + if (col->py + col->ph > ph) { + ph = col->py + col->ph; + } + } + + return ph; +} + +void TextPage::generateUnderlinesAndLinks(GList *columns) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + TextUnderline *underline; + TextLink *link; + double base, uSlack, ubSlack, hSlack; + int colIdx, parIdx, lineIdx, wordIdx, i; + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + base = word->getBaseline(); + uSlack = underlineSlack * word->fontSize; + ubSlack = underlineBaselineSlack * word->fontSize; + hSlack = hyperlinkSlack * word->fontSize; + + //----- handle underlining + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + if (underline->horiz) { + if (word->rot == 0 || word->rot == 2) { + if (fabs(underline->y0 - base) < ubSlack && + underline->x0 < word->xMin + uSlack && + word->xMax - uSlack < underline->x1) { + word->underlined = gTrue; + } + } + } else { + if (word->rot == 1 || word->rot == 3) { + if (fabs(underline->x0 - base) < ubSlack && + underline->y0 < word->yMin + uSlack && + word->yMax - uSlack < underline->y1) { + word->underlined = gTrue; + } + } + } + } + + //----- handle links + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + if (link->xMin < word->xMin + hSlack && + word->xMax - hSlack < link->xMax && + link->yMin < word->yMin + hSlack && + word->yMax - hSlack < link->yMax) { + word->link = link; + } + } + } + } + } + } +} + +//------------------------------------------------------------------------ +// TextPage: access +//------------------------------------------------------------------------ + +GBool TextPage::findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + GBool wholeWord, + double *xMin, double *yMin, + double *xMax, double *yMax) { + TextBlock *tree; + TextColumn *column; + TextParagraph *par; + TextLine *line; + Unicode *s2, *txt; + Unicode *p; + double xStart, yStart, xStop, yStop; + double xMin0, yMin0, xMax0, yMax0; + double xMin1, yMin1, xMax1, yMax1; + GBool found; + int txtSize, m, rot, colIdx, parIdx, lineIdx, i, j, k; + + //~ need to handle right-to-left text + + if (!findCols) { + rot = rotateChars(chars); + if ((tree = splitChars(chars))) { + findCols = buildColumns(tree); + delete tree; + } else { + // no text + findCols = new GList(); + } + unrotateChars(chars, rot); + unrotateColumns(findCols, rot); + } + + // convert the search string to uppercase + if (!caseSensitive) { + s2 = (Unicode *)gmallocn(len, sizeof(Unicode)); + for (i = 0; i < len; ++i) { + s2[i] = unicodeToUpper(s[i]); + } + } else { + s2 = s; + } + + txt = NULL; + txtSize = 0; + + xStart = yStart = xStop = yStop = 0; + if (startAtLast && haveLastFind) { + xStart = lastFindXMin; + yStart = lastFindYMin; + } else if (!startAtTop) { + xStart = *xMin; + yStart = *yMin; + } + if (stopAtLast && haveLastFind) { + xStop = lastFindXMin; + yStop = lastFindYMin; + } else if (!stopAtBottom) { + xStop = *xMax; + yStop = *yMax; + } + + found = gFalse; + xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy + xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy + + for (colIdx = backward ? findCols->getLength() - 1 : 0; + backward ? colIdx >= 0 : colIdx < findCols->getLength(); + colIdx += backward ? -1 : 1) { + column = (TextColumn *)findCols->get(colIdx); + + // check: is the column above the top limit? + if (!startAtTop && (backward ? column->yMin > yStart + : column->yMax < yStart)) { + continue; + } + + // check: is the column below the bottom limit? + if (!stopAtBottom && (backward ? column->yMax < yStop + : column->yMin > yStop)) { + continue; + } + + for (parIdx = backward ? column->paragraphs->getLength() - 1 : 0; + backward ? parIdx >= 0 : parIdx < column->paragraphs->getLength(); + parIdx += backward ? -1 : 1) { + par = (TextParagraph *)column->paragraphs->get(parIdx); + + // check: is the paragraph above the top limit? + if (!startAtTop && (backward ? par->yMin > yStart + : par->yMax < yStart)) { + continue; + } + + // check: is the paragraph below the bottom limit? + if (!stopAtBottom && (backward ? par->yMax < yStop + : par->yMin > yStop)) { + continue; + } + + for (lineIdx = backward ? par->lines->getLength() - 1 : 0; + backward ? lineIdx >= 0 : lineIdx < par->lines->getLength(); + lineIdx += backward ? -1 : 1) { + line = (TextLine *)par->lines->get(lineIdx); + + // check: is the line above the top limit? + if (!startAtTop && (backward ? line->yMin > yStart + : line->yMax < yStart)) { + continue; + } + + // check: is the line below the bottom limit? + if (!stopAtBottom && (backward ? line->yMax < yStop + : line->yMin > yStop)) { + continue; + } + + // convert the line to uppercase + m = line->len; + if (!caseSensitive) { + if (m > txtSize) { + txt = (Unicode *)greallocn(txt, m, sizeof(Unicode)); + txtSize = m; + } + for (k = 0; k < m; ++k) { + txt[k] = unicodeToUpper(line->text[k]); + } + } else { + txt = line->text; + } + + // search each position in this line + j = backward ? m - len : 0; + p = txt + j; + while (backward ? j >= 0 : j <= m - len) { + if (!wholeWord || + ((j == 0 || !unicodeTypeWord(txt[j - 1])) && + (j + len == m || !unicodeTypeWord(txt[j + len])))) { + + // compare the strings + for (k = 0; k < len; ++k) { + if (p[k] != s2[k]) { + break; + } + } + + // found it + if (k == len) { + switch (line->rot) { + case 0: + xMin1 = line->edge[j]; + xMax1 = line->edge[j + len]; + yMin1 = line->yMin; + yMax1 = line->yMax; + break; + case 1: + xMin1 = line->xMin; + xMax1 = line->xMax; + yMin1 = line->edge[j]; + yMax1 = line->edge[j + len]; + break; + case 2: + xMin1 = line->edge[j + len]; + xMax1 = line->edge[j]; + yMin1 = line->yMin; + yMax1 = line->yMax; + break; + case 3: + xMin1 = line->xMin; + xMax1 = line->xMax; + yMin1 = line->edge[j + len]; + yMax1 = line->edge[j]; + break; + } + if (backward) { + if ((startAtTop || + yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) && + (stopAtBottom || + yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) { + if (!found || + yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) { + xMin0 = xMin1; + xMax0 = xMax1; + yMin0 = yMin1; + yMax0 = yMax1; + found = gTrue; + } + } + } else { + if ((startAtTop || + yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) && + (stopAtBottom || + yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) { + if (!found || + yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) { + xMin0 = xMin1; + xMax0 = xMax1; + yMin0 = yMin1; + yMax0 = yMax1; + found = gTrue; + } + } + } + } + } + if (backward) { + --j; + --p; + } else { + ++j; + ++p; + } + } + } + } + } + + if (!caseSensitive) { + gfree(s2); + gfree(txt); + } + + if (found) { + *xMin = xMin0; + *xMax = xMax0; + *yMin = yMin0; + *yMax = yMax0; + lastFindXMin = xMin0; + lastFindYMin = yMin0; + haveLastFind = gTrue; + return gTrue; + } + + return gFalse; +} + +GString *TextPage::getText(double xMin, double yMin, + double xMax, double yMax) { + UnicodeMap *uMap; + char space[8], eol[16]; + int spaceLen, eolLen; + GList *chars2; + GString **out; + int *outLen; + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextChar *ch; + GBool primaryLR; + TextBlock *tree; + GList *columns; + GString *ret; + double xx, yy; + int rot, colIdx, parIdx, lineIdx, ph, y, i; + + // get the output encoding + if (!(uMap = globalParams->getTextEncoding())) { + return NULL; + } + spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); + eolLen = 0; // make gcc happy + switch (globalParams->getTextEOL()) { + case eolUnix: + eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); + break; + case eolDOS: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen); + break; + case eolMac: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + break; + } + + // get all chars in the rectangle + // (i.e., all chars whose center lies inside the rectangle) + chars2 = new GList(); + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + xx = 0.5 * (ch->xMin + ch->xMax); + yy = 0.5 * (ch->yMin + ch->yMax); + if (xx > xMin && xx < xMax && yy > yMin && yy < yMax) { + chars2->append(ch); + } + } +#if 0 //~debug + dumpChars(chars2); +#endif + + rot = rotateChars(chars2); + primaryLR = checkPrimaryLR(chars2); + tree = splitChars(chars2); + if (!tree) { + unrotateChars(chars2, rot); + delete chars2; + return new GString(); + } +#if 0 //~debug + dumpTree(tree); +#endif + columns = buildColumns(tree); + delete tree; + ph = assignPhysLayoutPositions(columns); +#if 0 //~debug + dumpColumns(columns); +#endif + unrotateChars(chars2, rot); + delete chars2; + + out = (GString **)gmallocn(ph, sizeof(GString *)); + outLen = (int *)gmallocn(ph, sizeof(int)); + for (i = 0; i < ph; ++i) { + out[i] = NULL; + outLen[i] = 0; + } + + columns->sort(&TextColumn::cmpPX); + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + y = col->py; + for (parIdx = 0; + parIdx < col->paragraphs->getLength() && y < ph; + ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; + lineIdx < par->lines->getLength() && y < ph; + ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + if (!out[y]) { + out[y] = new GString(); + } + while (outLen[y] < col->px + line->px) { + out[y]->append(space, spaceLen); + ++outLen[y]; + } + encodeFragment(line->text, line->len, uMap, primaryLR, out[y]); + outLen[y] += line->pw; + ++y; + } + if (parIdx + 1 < col->paragraphs->getLength()) { + ++y; + } + } + } + + ret = new GString(); + for (i = 0; i < ph; ++i) { + if (out[i]) { + ret->append(out[i]); + delete out[i]; + } + if (ph > 1) { + ret->append(eol, eolLen); + } + } + + gfree(out); + gfree(outLen); + deleteGList(columns, TextColumn); + uMap->decRefCnt(); + + return ret; +} + +GBool TextPage::findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax) { + TextChar *ch; + double xMin2, yMin2, xMax2, yMax2; + GBool first; + int i; + + //~ this doesn't correctly handle ranges split across multiple lines + //~ (the highlighted region is the bounding box of all the parts of + //~ the range) + + xMin2 = yMin2 = xMax2 = yMax2 = 0; + first = gTrue; + for (i = 0; i < chars->getLength(); ++i) { + ch = (TextChar *)chars->get(i); + if (ch->charPos >= pos && ch->charPos < pos + length) { + if (first || ch->xMin < xMin2) { + xMin2 = ch->xMin; + } + if (first || ch->yMin < yMin2) { + yMin2 = ch->yMin; + } + if (first || ch->xMax > xMax2) { + xMax2 = ch->xMax; + } + if (first || ch->yMax > yMax2) { + yMax2 = ch->yMax; + } + first = gFalse; + } + } + if (first) { + return gFalse; + } + *xMin = xMin2; + *yMin = yMin2; + *xMax = xMax2; + *yMax = yMax2; + return gTrue; +} + +TextWordList *TextPage::makeWordList() { + TextBlock *tree; + GList *columns; + TextColumn *col; + TextParagraph *par; + TextLine *line; + TextWord *word; + GList *words; + int rot, colIdx, parIdx, lineIdx, wordIdx; + + rot = rotateChars(chars); + tree = splitChars(chars); + if (!tree) { + // no text + unrotateChars(chars, rot); + return new TextWordList(new GList()); + } + columns = buildColumns(tree); + delete tree; + unrotateChars(chars, rot); + if (control.html) { + rotateUnderlinesAndLinks(rot); + generateUnderlinesAndLinks(columns); + } + + words = new GList(); + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + for (wordIdx = 0; wordIdx < line->words->getLength(); ++wordIdx) { + word = (TextWord *)line->words->get(wordIdx); + words->append(word->copy()); + } + } + } + } + + switch (control.mode) { + case textOutReadingOrder: + // already in reading order + break; + case textOutPhysLayout: + case textOutTableLayout: + case textOutLinePrinter: + words->sort(&TextWord::cmpYX); + break; + case textOutRawOrder: + words->sort(&TextWord::cmpCharPos); + break; + } + + // this has to be done after sorting with cmpYX + unrotateColumns(columns, rot); + unrotateWords(words, rot); + + deleteGList(columns, TextColumn); + + return new TextWordList(words); +} + +//------------------------------------------------------------------------ +// TextPage: debug +//------------------------------------------------------------------------ + +#if 0 //~debug + +void TextPage::dumpChars(GList *charsA) { + TextChar *ch; + int i; + + for (i = 0; i < charsA->getLength(); ++i) { + ch = (TextChar *)charsA->get(i); + printf("char: U+%04x '%c' xMin=%g yMin=%g xMax=%g yMax=%g fontSize=%g rot=%d\n", + ch->c, ch->c & 0xff, ch->xMin, ch->yMin, ch->xMax, ch->yMax, + ch->fontSize, ch->rot); + } +} + +void TextPage::dumpTree(TextBlock *tree, int indent) { + TextChar *ch; + int i; + + printf("%*sblock: type=%s tag=%s small=%d rot=%d xMin=%g yMin=%g xMax=%g yMax=%g\n", + indent, "", + tree->type == blkLeaf ? "leaf" : + tree->type == blkHorizSplit ? "horiz" : "vert", + tree->tag == blkTagMulticolumn ? "multicolumn" : + tree->tag == blkTagColumn ? "column" : "line", + tree->smallSplit, + tree->rot, tree->xMin, tree->yMin, tree->xMax, tree->yMax); + if (tree->type == blkLeaf) { + for (i = 0; i < tree->children->getLength(); ++i) { + ch = (TextChar *)tree->children->get(i); + printf("%*schar: '%c' xMin=%g yMin=%g xMax=%g yMax=%g font=%d.%d\n", + indent + 2, "", ch->c & 0xff, + ch->xMin, ch->yMin, ch->xMax, ch->yMax, + ch->font->fontID.num, ch->font->fontID.gen); + } + } else { + for (i = 0; i < tree->children->getLength(); ++i) { + dumpTree((TextBlock *)tree->children->get(i), indent + 2); + } + } +} + +void TextPage::dumpColumns(GList *columns) { + TextColumn *col; + TextParagraph *par; + TextLine *line; + int colIdx, parIdx, lineIdx, i; + + for (colIdx = 0; colIdx < columns->getLength(); ++colIdx) { + col = (TextColumn *)columns->get(colIdx); + printf("column: xMin=%g yMin=%g xMax=%g yMax=%g px=%d py=%d pw=%d ph=%d\n", + col->xMin, col->yMin, col->xMax, col->yMax, + col->px, col->py, col->pw, col->ph); + for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { + par = (TextParagraph *)col->paragraphs->get(parIdx); + printf(" paragraph:\n"); + for (lineIdx = 0; lineIdx < par->lines->getLength(); ++lineIdx) { + line = (TextLine *)par->lines->get(lineIdx); + printf(" line: xMin=%g yMin=%g xMax=%g yMax=%g px=%d pw=%d rot=%d\n", + line->xMin, line->yMin, line->xMax, line->yMax, + line->px, line->pw, line->rot); + printf(" "); + for (i = 0; i < line->len; ++i) { + printf("%c", line->text[i] & 0xff); + } + printf("\n"); + } + } + } +} + +#endif //~debug + +//------------------------------------------------------------------------ +// TextOutputDev +//------------------------------------------------------------------------ + +static void outputToFile(void *stream, const char *text, int len) { + fwrite(text, 1, len, (FILE *)stream); +} + +TextOutputDev::TextOutputDev(char *fileName, TextOutputControl *controlA, + GBool append) { + text = NULL; + control = *controlA; + ok = gTrue; + + // open file + needClose = gFalse; + if (fileName) { + if (!strcmp(fileName, "-")) { + outputStream = stdout; +#ifdef WIN32 + // keep DOS from munging the end-of-line characters + setmode(fileno(stdout), O_BINARY); +#endif + } else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) { + needClose = gTrue; + } else { + error(errIO, -1, "Couldn't open text file '{0:s}'", fileName); + ok = gFalse; + return; + } + outputFunc = &outputToFile; + } else { + outputStream = NULL; + } + + // set up text object + text = new TextPage(&control); +} + +TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, + TextOutputControl *controlA) { + outputFunc = func; + outputStream = stream; + needClose = gFalse; + control = *controlA; + text = new TextPage(&control); + ok = gTrue; +} + +TextOutputDev::~TextOutputDev() { + if (needClose) { + fclose((FILE *)outputStream); + } + if (text) { + delete text; + } +} + +void TextOutputDev::startPage(int pageNum, GfxState *state) { + text->startPage(state); +} + +void TextOutputDev::endPage() { + if (outputStream) { + text->write(outputStream, outputFunc); + } +} + +void TextOutputDev::restoreState(GfxState *state) { + text->updateFont(state); +} + +void TextOutputDev::updateFont(GfxState *state) { + text->updateFont(state); +} + +void TextOutputDev::beginString(GfxState *state, GString *s) { +} + +void TextOutputDev::endString(GfxState *state) { +} + +void TextOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode c, int nBytes, Unicode *u, int uLen) { + text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen); +} + +void TextOutputDev::incCharCount(int nChars) { + text->incCharCount(nChars); +} + +void TextOutputDev::beginActualText(GfxState *state, Unicode *u, int uLen) { + text->beginActualText(state, u, uLen); +} + +void TextOutputDev::endActualText(GfxState *state) { + text->endActualText(state); +} + +void TextOutputDev::stroke(GfxState *state) { + GfxPath *path; + GfxSubpath *subpath; + double x[2], y[2]; + + if (!control.html) { + return; + } + path = state->getPath(); + if (path->getNumSubpaths() != 1) { + return; + } + subpath = path->getSubpath(0); + if (subpath->getNumPoints() != 2) { + return; + } + state->transform(subpath->getX(0), subpath->getY(0), &x[0], &y[0]); + state->transform(subpath->getX(1), subpath->getY(1), &x[1], &y[1]); + + // look for a vertical or horizontal line + if (x[0] == x[1] || y[0] == y[1]) { + text->addUnderline(x[0], y[0], x[1], y[1]); + } +} + +void TextOutputDev::fill(GfxState *state) { + GfxPath *path; + GfxSubpath *subpath; + double x[5], y[5]; + double rx0, ry0, rx1, ry1, t; + int i; + + if (!control.html) { + return; + } + path = state->getPath(); + if (path->getNumSubpaths() != 1) { + return; + } + subpath = path->getSubpath(0); + if (subpath->getNumPoints() != 5) { + return; + } + for (i = 0; i < 5; ++i) { + if (subpath->getCurve(i)) { + return; + } + state->transform(subpath->getX(i), subpath->getY(i), &x[i], &y[i]); + } + + // look for a rectangle + if (x[0] == x[1] && y[1] == y[2] && x[2] == x[3] && y[3] == y[4] && + x[0] == x[4] && y[0] == y[4]) { + rx0 = x[0]; + ry0 = y[0]; + rx1 = x[2]; + ry1 = y[1]; + } else if (y[0] == y[1] && x[1] == x[2] && y[2] == y[3] && x[3] == x[4] && + x[0] == x[4] && y[0] == y[4]) { + rx0 = x[0]; + ry0 = y[0]; + rx1 = x[1]; + ry1 = y[2]; + } else { + return; + } + if (rx1 < rx0) { + t = rx0; + rx0 = rx1; + rx1 = t; + } + if (ry1 < ry0) { + t = ry0; + ry0 = ry1; + ry1 = t; + } + + // skinny horizontal rectangle + if (ry1 - ry0 < rx1 - rx0) { + if (ry1 - ry0 < maxUnderlineWidth) { + ry0 = 0.5 * (ry0 + ry1); + text->addUnderline(rx0, ry0, rx1, ry0); + } + + // skinny vertical rectangle + } else { + if (rx1 - rx0 < maxUnderlineWidth) { + rx0 = 0.5 * (rx0 + rx1); + text->addUnderline(rx0, ry0, rx0, ry1); + } + } +} + +void TextOutputDev::eoFill(GfxState *state) { + if (!control.html) { + return; + } + fill(state); +} + +void TextOutputDev::processLink(Link *link) { + double x1, y1, x2, y2; + int xMin, yMin, xMax, yMax, x, y; + + if (!control.html) { + return; + } + link->getRect(&x1, &y1, &x2, &y2); + cvtUserToDev(x1, y1, &x, &y); + xMin = xMax = x; + yMin = yMax = y; + cvtUserToDev(x1, y2, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + cvtUserToDev(x2, y1, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + cvtUserToDev(x2, y2, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + text->addLink(xMin, yMin, xMax, yMax, link); +} + +GBool TextOutputDev::findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + GBool wholeWord, + double *xMin, double *yMin, + double *xMax, double *yMax) { + return text->findText(s, len, startAtTop, stopAtBottom, + startAtLast, stopAtLast, + caseSensitive, backward, wholeWord, + xMin, yMin, xMax, yMax); +} + +GString *TextOutputDev::getText(double xMin, double yMin, + double xMax, double yMax) { + return text->getText(xMin, yMin, xMax, yMax); +} + +GBool TextOutputDev::findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax) { + return text->findCharRange(pos, length, xMin, yMin, xMax, yMax); +} + +TextWordList *TextOutputDev::makeWordList() { + return text->makeWordList(); +} + +TextPage *TextOutputDev::takeText() { + TextPage *ret; + + ret = text; + text = new TextPage(&control); + return ret; +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.h index e3bb26c676d..4399029ea31 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/TextOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextOutputDev.h @@ -2,7 +2,7 @@ // // TextOutputDev.h // -// Copyright 1997-2003 Glyph & Cog, LLC +// Copyright 1997-2012 Glyph & Cog, LLC // //======================================================================== @@ -20,20 +20,12 @@ #include "GfxFont.h" #include "OutputDev.h" -class GString; class GList; -class GfxFont; -class GfxState; class UnicodeMap; -class Link; -class TextWord; -class TextPool; -class TextLine; -class TextLineFrag; class TextBlock; -class TextFlow; -class TextWordList; +class TextChar; +class TextLink; class TextPage; //------------------------------------------------------------------------ @@ -41,6 +33,37 @@ class TextPage; typedef void (*TextOutputFunc)(void *stream, const char *text, int len); //------------------------------------------------------------------------ +// TextOutputControl +//------------------------------------------------------------------------ + +enum TextOutputMode { + textOutReadingOrder, // format into reading order + textOutPhysLayout, // maintain original physical layout + textOutTableLayout, // similar to PhysLayout, but optimized + // for tables + textOutLinePrinter, // strict fixed-pitch/height layout + textOutRawOrder // keep text in content stream order +}; + +class TextOutputControl { +public: + + TextOutputControl(); + ~TextOutputControl() {} + + TextOutputMode mode; // formatting mode + double fixedPitch; // if this is non-zero, assume fixed-pitch + // characters with this width + // (only relevant for PhysLayout, Table, + // and LinePrinter modes) + double fixedLineSpacing; // fixed line spacing (only relevant for + // LinePrinter mode) + GBool html; // enable extra processing for HTML + GBool clipText; // separate clipped text and add it back + // in after forming columns +}; + +//------------------------------------------------------------------------ // TextFontInfo //------------------------------------------------------------------------ @@ -52,7 +75,6 @@ public: GBool matches(GfxState *state); -#if TEXTOUT_WORD_LIST // Get the font name (which may be NULL). GString *getFontName() { return fontName; } @@ -62,18 +84,21 @@ public: GBool isSymbolic() { return flags & fontSymbolic; } GBool isItalic() { return flags & fontItalic; } GBool isBold() { return flags & fontBold; } -#endif + + // Get the width of the 'm' character, if available. + double getMWidth() { return mWidth; } private: - GfxFont *gfxFont; -#if TEXTOUT_WORD_LIST + Ref fontID; GString *fontName; int flags; -#endif + double mWidth; + double ascent, descent; - friend class TextWord; + friend class TextLine; friend class TextPage; + friend class TextWord; }; //------------------------------------------------------------------------ @@ -83,44 +108,21 @@ private: class TextWord { public: - // Constructor. - TextWord(GfxState *state, int rotA, double x0, double y0, - TextFontInfo *fontA, double fontSize); - - // Destructor. + TextWord(GList *chars, int start, int lenA, + int rotA, GBool spaceAfterA); ~TextWord(); - - // Add a character to the word. - void addChar(GfxState *state, double x, double y, - double dx, double dy, int charPosA, int charLen, - Unicode u); - - // Merge <word> onto the end of <this>. - void merge(TextWord *word); - - // Compares <this> to <word>, returning -1 (<), 0 (=), or +1 (>), - // based on a primary-axis comparison, e.g., x ordering if rot=0. - int primaryCmp(TextWord *word); - - // Return the distance along the primary axis between <this> and - // <word>. - double primaryDelta(TextWord *word); - - static int cmpYX(const void *p1, const void *p2); + TextWord *copy() { return new TextWord(this); } // Get the TextFontInfo object associated with this word. TextFontInfo *getFontInfo() { return font; } - // Get the next TextWord on the linked list. - TextWord *getNext() { return next; } - -#if TEXTOUT_WORD_LIST int getLength() { return len; } Unicode getChar(int idx) { return text[idx]; } GString *getText(); GString *getFontName() { return font->fontName; } void getColor(double *r, double *g, double *b) { *r = colorR; *g = colorG; *b = colorB; } + GBool isInvisible() { return invisible; } void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } void getCharBBox(int charIdx, double *xMinA, double *yMinA, @@ -130,76 +132,43 @@ public: int getCharPos() { return charPos[0]; } int getCharLen() { return charPos[len] - charPos[0]; } GBool getSpaceAfter() { return spaceAfter; } -#endif - + double getBaseline(); GBool isUnderlined() { return underlined; } - Link *getLink() { return link; } + GString *getLinkURI(); private: + TextWord(TextWord *word); + void appendChar(TextChar *ch); + static int cmpYX(const void *p1, const void *p2); + static int cmpCharPos(const void *p1, const void *p2); + int rot; // rotation, multiple of 90 degrees // (0, 1, 2, or 3) double xMin, xMax; // bounding box x coordinates double yMin, yMax; // bounding box y coordinates - double base; // baseline x or y coordinate Unicode *text; // the text - double *edge; // "near" edge x or y coord of each char - // (plus one extra entry for the last char) int *charPos; // character position (within content stream) // of each char (plus one extra entry for // the last char) - int len; // length of text/edge/charPos arrays - int size; // size of text/edge/charPos arrays + double *edge; // "near" edge x or y coord of each char + // (plus one extra entry for the last char) + int len; // number of characters TextFontInfo *font; // font information double fontSize; // font size GBool spaceAfter; // set if there is a space between this // word and the next word on the line - TextWord *next; // next word in line -#if TEXTOUT_WORD_LIST + GBool underlined; + TextLink *link; + double colorR, // word color colorG, colorB; -#endif - - GBool underlined; - Link *link; - - friend class TextPool; - friend class TextLine; - friend class TextBlock; - friend class TextFlow; - friend class TextWordList; - friend class TextPage; -}; - -//------------------------------------------------------------------------ -// TextPool -//------------------------------------------------------------------------ - -class TextPool { -public: - - TextPool(); - ~TextPool(); - - TextWord *getPool(int baseIdx) { return pool[baseIdx - minBaseIdx]; } - void setPool(int baseIdx, TextWord *p) { pool[baseIdx - minBaseIdx] = p; } - - int getBaseIdx(double base); - - void addWord(TextWord *word); - -private: - - int minBaseIdx; // min baseline bucket index - int maxBaseIdx; // max baseline bucket index - TextWord **pool; // array of linked lists, one for each - // baseline value (multiple of 4 pts) - TextWord *cursor; // pointer to last-accessed word - int cursorBaseIdx; // baseline bucket index of last-accessed word + GBool invisible; // set for invisible text (render mode 3) friend class TextBlock; + friend class TextLine; friend class TextPage; }; @@ -210,168 +179,92 @@ private: class TextLine { public: - TextLine(TextBlock *blkA, int rotA, double baseA); + TextLine(GList *wordsA, double xMinA, double yMinA, + double xMaxA, double yMaxA, double fontSizeA); ~TextLine(); - void addWord(TextWord *word); - - // Return the distance along the primary axis between <this> and - // <line>. - double primaryDelta(TextLine *line); - - // Compares <this> to <line>, returning -1 (<), 0 (=), or +1 (>), - // based on a primary-axis comparison, e.g., x ordering if rot=0. - int primaryCmp(TextLine *line); - - // Compares <this> to <line>, returning -1 (<), 0 (=), or +1 (>), - // based on a secondary-axis comparison of the baselines, e.g., y - // ordering if rot=0. - int secondaryCmp(TextLine *line); - - int cmpYX(TextLine *line); - - static int cmpXY(const void *p1, const void *p2); - - void coalesce(UnicodeMap *uMap); - - // Get the head of the linked list of TextWords. - TextWord *getWords() { return words; } - - // Get the next TextLine on the linked list. - TextLine *getNext() { return next; } - - // Returns true if the last char of the line is a hyphen. - GBool isHyphenated() { return hyphenated; } + double getXMin() { return xMin; } + double getYMin() { return yMin; } + double getBaseline(); + int getRotation() { return rot; } + GList *getWords() { return words; } private: - TextBlock *blk; // parent block - int rot; // text rotation + GList *words; // [TextWord] + int rot; // rotation, multiple of 90 degrees + // (0, 1, 2, or 3) double xMin, xMax; // bounding box x coordinates double yMin, yMax; // bounding box y coordinates - double base; // baseline x or y coordinate - TextWord *words; // words in this line - TextWord *lastWord; // last word in this line + double fontSize; // main (max) font size for this line Unicode *text; // Unicode text of the line, including // spaces between words double *edge; // "near" edge x or y coord of each char // (plus one extra entry for the last char) - int *col; // starting column number of each Unicode char int len; // number of Unicode chars - int convertedLen; // total number of converted characters GBool hyphenated; // set if last char is a hyphen - TextLine *next; // next line in block + int px; // x offset (in characters, relative to + // containing column) in physical layout mode + int pw; // line width (in characters) in physical + // layout mode - friend class TextLineFrag; - friend class TextBlock; - friend class TextFlow; - friend class TextWordList; friend class TextPage; + friend class TextParagraph; }; //------------------------------------------------------------------------ -// TextBlock +// TextParagraph //------------------------------------------------------------------------ -class TextBlock { +class TextParagraph { public: - TextBlock(TextPage *pageA, int rotA); - ~TextBlock(); - - void addWord(TextWord *word); - - void coalesce(UnicodeMap *uMap, double fixedPitch); - - // Update this block's priMin and priMax values, looking at <blk>. - void updatePriMinMax(TextBlock *blk); - - static int cmpXYPrimaryRot(const void *p1, const void *p2); - - static int cmpYXPrimaryRot(const void *p1, const void *p2); - - int primaryCmp(TextBlock *blk); + TextParagraph(GList *linesA); + ~TextParagraph(); - double secondaryDelta(TextBlock *blk); - - // Returns true if <this> is below <blk>, relative to the page's - // primary rotation. - GBool isBelow(TextBlock *blk); - - // Get the head of the linked list of TextLines. - TextLine *getLines() { return lines; } - - // Get the next TextBlock on the linked list. - TextBlock *getNext() { return next; } + // Get the list of TextLine objects. + GList *getLines() { return lines; } private: - TextPage *page; // the parent page - int rot; // text rotation + GList *lines; // [TextLine] double xMin, xMax; // bounding box x coordinates double yMin, yMax; // bounding box y coordinates - double priMin, priMax; // whitespace bounding box along primary axis - - TextPool *pool; // pool of words (used only until lines - // are built) - TextLine *lines; // linked list of lines - TextLine *curLine; // most recently added line - int nLines; // number of lines - int charCount; // number of characters in the block - int col; // starting column - int nColumns; // number of columns in the block - TextBlock *next; - TextBlock *stackNext; - - friend class TextLine; - friend class TextLineFrag; - friend class TextFlow; - friend class TextWordList; friend class TextPage; }; //------------------------------------------------------------------------ -// TextFlow +// TextColumn //------------------------------------------------------------------------ -class TextFlow { +class TextColumn { public: - TextFlow(TextPage *pageA, TextBlock *blk); - ~TextFlow(); - - // Add a block to the end of this flow. - void addBlock(TextBlock *blk); - - // Returns true if <blk> fits below <prevBlk> in the flow, i.e., (1) - // it uses a font no larger than the last block added to the flow, - // and (2) it fits within the flow's [priMin, priMax] along the - // primary axis. - GBool blockFits(TextBlock *blk, TextBlock *prevBlk); + TextColumn(GList *paragraphsA, double xMinA, double yMinA, + double xMaxA, double yMaxA); + ~TextColumn(); - // Get the head of the linked list of TextBlocks. - TextBlock *getBlocks() { return blocks; } - - // Get the next TextFlow on the linked list. - TextFlow *getNext() { return next; } + // Get the list of TextParagraph objects. + GList *getParagraphs() { return paragraphs; } private: - TextPage *page; // the parent page + static int cmpX(const void *p1, const void *p2); + static int cmpY(const void *p1, const void *p2); + static int cmpPX(const void *p1, const void *p2); + + GList *paragraphs; // [TextParagraph] double xMin, xMax; // bounding box x coordinates double yMin, yMax; // bounding box y coordinates - double priMin, priMax; // whitespace bounding box along primary axis - TextBlock *blocks; // blocks in flow - TextBlock *lastBlk; // last block in this flow - TextFlow *next; + int px, py; // x, y position (in characters) in physical + // layout mode + int pw, ph; // column width, height (in characters) in + // physical layout mode - friend class TextWordList; friend class TextPage; }; -#if TEXTOUT_WORD_LIST - //------------------------------------------------------------------------ // TextWordList //------------------------------------------------------------------------ @@ -379,11 +272,7 @@ private: class TextWordList { public: - // Build a flat word list, in content stream order (if - // text->rawOrder is true), physical layout order (if <physLayout> - // is true and text->rawOrder is false), or reading order (if both - // flags are false). - TextWordList(TextPage *text, GBool physLayout); + TextWordList(GList *wordsA); ~TextWordList(); @@ -398,8 +287,6 @@ private: GList *words; // [TextWord] }; -#endif // TEXTOUT_WORD_LIST - //------------------------------------------------------------------------ // TextPage //------------------------------------------------------------------------ @@ -407,52 +294,11 @@ private: class TextPage { public: - // Constructor. - TextPage(GBool rawOrderA); - - // Destructor. + TextPage(TextOutputControl *controlA); ~TextPage(); - // Start a new page. - void startPage(GfxState *state); - - // End the current page. - void endPage(); - - // Update the current font. - void updateFont(GfxState *state); - - // Begin a new word. - void beginWord(GfxState *state, double x0, double y0); - - // Add a character to the current word. - void addChar(GfxState *state, double x, double y, - double dx, double dy, - CharCode c, int nBytes, Unicode *u, int uLen); - - // Add <nChars> invisible characters. - void incCharCount(int nChars); - - // Begin/end an "ActualText" span, where the char indexes are - // supplied by a marked content operator rather than the text - // drawing operators. - void beginActualText(GfxState *state, Unicode *u, int uLen); - void endActualText(GfxState *state); - - // End the current word, sorting it into the list of words. - void endWord(); - - // Add a word, sorting it into the list of words. - void addWord(TextWord *word); - - // Add a (potential) underline. - void addUnderline(double x0, double y0, double x1, double y1); - - // Add a hyperlink. - void addLink(int xMin, int yMin, int xMax, int yMax, Link *link); - - // Coalesce strings that look like parts of the same line. - void coalesce(GBool physLayout, double fixedPitch, GBool doHTML); + // Write contents of page to a stream. + void write(void *outputStream, TextOutputFunc outputFunc); // Find a string. If <startAtTop> is true, starts looking at the // top of the page; else if <startAtLast> is true, starts looking @@ -480,39 +326,106 @@ public: double *xMin, double *yMin, double *xMax, double *yMax); - // Dump contents of page to a file. - void dump(void *outputStream, TextOutputFunc outputFunc, - GBool physLayout); + // Create and return a list of TextColumn objects. + GList *makeColumns(); - // Get the head of the linked list of TextFlows. - TextFlow *getFlows() { return flows; } + // Get the list of all TextFontInfo objects used on this page. + GList *getFonts() { return fonts; } -#if TEXTOUT_WORD_LIST - // Build a flat word list, in content stream order (if - // this->rawOrder is true), physical layout order (if <physLayout> - // is true and this->rawOrder is false), or reading order (if both - // flags are false). - TextWordList *makeWordList(GBool physLayout); -#endif + // Build a flat word list, in the specified ordering. + TextWordList *makeWordList(); private: + void startPage(GfxState *state); void clear(); - void assignColumns(TextLineFrag *frags, int nFrags, int rot); - int dumpFragment(Unicode *text, int len, UnicodeMap *uMap, GString *s); + void updateFont(GfxState *state); + void addChar(GfxState *state, double x, double y, + double dx, double dy, + CharCode c, int nBytes, Unicode *u, int uLen); + void incCharCount(int nChars); + void beginActualText(GfxState *state, Unicode *u, int uLen); + void endActualText(GfxState *state); + void addUnderline(double x0, double y0, double x1, double y1); + void addLink(double xMin, double yMin, double xMax, double yMax, + Link *link); + + // output + void writeReadingOrder(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writePhysLayout(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writeLinePrinter(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void writeRaw(void *outputStream, + TextOutputFunc outputFunc, + UnicodeMap *uMap, + char *space, int spaceLen, + char *eol, int eolLen); + void encodeFragment(Unicode *text, int len, UnicodeMap *uMap, + GBool primaryLR, GString *s); + + // analysis + int rotateChars(GList *charsA); + void rotateUnderlinesAndLinks(int rot); + void unrotateChars(GList *charsA, int rot); + void unrotateColumns(GList *columns, int rot); + void unrotateWords(GList *words, int rot); + GBool checkPrimaryLR(GList *charsA); + void removeDuplicates(GList *charsA, int rot); + TextBlock *splitChars(GList *charsA); + TextBlock *split(GList *charsA, int rot); + GList *getChars(GList *charsA, double xMin, double yMin, + double xMax, double yMax); + void tagBlock(TextBlock *blk); + void insertLargeChars(GList *largeChars, TextBlock *blk); + void insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk); + void insertLargeCharInLeaf(TextChar *ch, TextBlock *blk); + void insertIntoTree(TextBlock *subtree, TextBlock *primaryTree); + void insertColumnIntoTree(TextBlock *column, TextBlock *tree); + void insertClippedChars(GList *clippedChars, TextBlock *tree); + TextBlock *findClippedCharLeaf(TextChar *ch, TextBlock *tree); + GList *buildColumns(TextBlock *tree); + void buildColumns2(TextBlock *blk, GList *columns); + TextColumn *buildColumn(TextBlock *tree); + double getLineIndent(TextLine *line, TextBlock *blk); + double getAverageLineSpacing(GList *lines); + double getLineSpacing(TextLine *line0, TextLine *line1); + void buildLines(TextBlock *blk, GList *lines); + TextLine *buildLine(TextBlock *blk); + void getLineChars(TextBlock *blk, GList *charsA); + double computeWordSpacingThreshold(GList *charsA, int rot); + int assignPhysLayoutPositions(GList *columns); + void assignLinePhysPositions(GList *columns); + void computeLinePhysWidth(TextLine *line, UnicodeMap *uMap); + int assignColumnPhysPositions(GList *columns); + void generateUnderlinesAndLinks(GList *columns); + + // debug +#if 0 //~debug + void dumpChars(GList *charsA); + void dumpTree(TextBlock *tree, int indent = 0); + void dumpColumns(GList *columns); +#endif - GBool rawOrder; // keep text in content stream order + TextOutputControl control; // formatting parameters double pageWidth, pageHeight; // width and height of current page - TextWord *curWord; // currently active string int charPos; // next character position (within content // stream) TextFontInfo *curFont; // current font double curFontSize; // current font size - int nest; // current nesting level (for Type 3 fonts) + int curRot; // current rotation int nTinyChars; // number of "tiny" chars seen so far - GBool lastCharOverlap; // set if the last added char overlapped the - // previous char Unicode *actualText; // current "ActualText" span int actualTextLen; double actualTextX0, @@ -521,32 +434,22 @@ private: actualTextY1; int actualTextNBytes; - TextPool *pools[4]; // a "pool" of TextWords for each rotation - TextFlow *flows; // linked list of flows - TextBlock **blocks; // array of blocks, in yx order - int nBlocks; // number of blocks - int primaryRot; // primary rotation - GBool primaryLR; // primary direction (true means L-to-R, - // false means R-to-L) - TextWord *rawWords; // list of words, in raw order (only if - // rawOrder is set) - TextWord *rawLastWord; // last word on rawWords list - + GList *chars; // [TextChar] GList *fonts; // all font info objects used on this // page [TextFontInfo] + GList *underlines; // [TextUnderline] + GList *links; // [TextLink] + + GList *findCols; // text used by the findText function + // [TextColumn] + GBool findLR; // primary text direction, used by the + // findText function double lastFindXMin, // coordinates of the last "find" result lastFindYMin; GBool haveLastFind; - GList *underlines; // [TextUnderline] - GList *links; // [TextLink] - - friend class TextLine; - friend class TextLineFrag; - friend class TextBlock; - friend class TextFlow; - friend class TextWordList; + friend class TextOutputDev; }; //------------------------------------------------------------------------ @@ -561,8 +464,7 @@ public: // <physLayoutA> is true, the original physical layout of the text // is maintained. If <rawOrder> is true, the text is kept in // content stream order. - TextOutputDev(char *fileName, GBool physLayoutA, - double fixedPitchA, GBool rawOrderA, + TextOutputDev(char *fileName, TextOutputControl *controlA, GBool append); // Create a TextOutputDev which will write to a generic stream. If @@ -570,8 +472,7 @@ public: // is maintained. If <rawOrder> is true, the text is kept in // content stream order. TextOutputDev(TextOutputFunc func, void *stream, - GBool physLayoutA, double fixedPitchA, - GBool rawOrderA); + TextOutputControl *controlA); // Destructor. virtual ~TextOutputDev(); @@ -660,20 +561,18 @@ public: double *xMin, double *yMin, double *xMax, double *yMax); -#if TEXTOUT_WORD_LIST // Build a flat word list, in content stream order (if // this->rawOrder is true), physical layout order (if // this->physLayout is true and this->rawOrder is false), or reading // order (if both flags are false). TextWordList *makeWordList(); -#endif // Returns the TextPage object for the last rasterized page, // transferring ownership to the caller. TextPage *takeText(); // Turn extra processing for HTML conversion on or off. - void enableHTMLExtras(GBool doHTMLA) { doHTML = doHTMLA; } + void enableHTMLExtras(GBool html) { control.html = html; } private: @@ -682,13 +581,7 @@ private: GBool needClose; // need to close the output file? // (only if outputStream is a FILE*) TextPage *text; // text for the current page - GBool physLayout; // maintain original physical layout when - // dumping text - double fixedPitch; // if physLayout is true and this is non-zero, - // assume fixed-pitch characters with this - // width - GBool rawOrder; // keep text in content stream order - GBool doHTML; // extra processing for HTML conversion + TextOutputControl control; // formatting parameters GBool ok; // set up ok? }; diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.cc new file mode 100644 index 00000000000..5bc9de2fab0 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.cc @@ -0,0 +1,164 @@ +//======================================================================== +// +// TextString.cc +// +// Copyright 2011-2013 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <string.h> +#include "gmem.h" +#include "GString.h" +#include "PDFDocEncoding.h" +#include "TextString.h" + +//------------------------------------------------------------------------ + +TextString::TextString() { + u = NULL; + len = size = 0; +} + +TextString::TextString(GString *s) { + u = NULL; + len = size = 0; + append(s); +} + +TextString::TextString(TextString *s) { + len = size = s->len; + if (len) { + u = (Unicode *)gmallocn(size, sizeof(Unicode)); + memcpy(u, s->u, len * sizeof(Unicode)); + } else { + u = NULL; + } +} + +TextString::~TextString() { + gfree(u); +} + +TextString *TextString::append(Unicode c) { + expand(1); + u[len] = c; + ++len; + return this; +} + +TextString *TextString::append(GString *s) { + int n, i; + + if ((s->getChar(0) & 0xff) == 0xfe && + (s->getChar(1) & 0xff) == 0xff) { + n = (s->getLength() - 2) / 2; + expand(n); + for (i = 0; i < n; ++i) { + u[len + i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | + (s->getChar(3 + 2*i) & 0xff); + } + len += n; + } else { + n = s->getLength(); + expand(n); + for (i = 0; i < n; ++i) { + u[len + i] = pdfDocEncoding[s->getChar(i) & 0xff]; + } + len += n; + } + return this; +} + +TextString *TextString::insert(int idx, Unicode c) { + if (idx >= 0 && idx <= len) { + expand(1); + if (idx < len) { + memmove(u + idx + 1, u + idx, (len - idx) * sizeof(Unicode)); + } + u[idx] = c; + ++len; + } + return this; +} + +TextString *TextString::insert(int idx, GString *s) { + int n, i; + + if (idx >= 0 && idx <= len) { + if ((s->getChar(0) & 0xff) == 0xfe && + (s->getChar(1) & 0xff) == 0xff) { + n = (s->getLength() - 2) / 2; + expand(n); + if (idx < len) { + memmove(u + idx + n, u + idx, (len - idx) * sizeof(Unicode)); + } + for (i = 0; i < n; ++i) { + u[idx + i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | + (s->getChar(3 + 2*i) & 0xff); + } + len += n; + } else { + n = s->getLength(); + expand(n); + if (idx < len) { + memmove(u + idx + n, u + idx, (len - idx) * sizeof(Unicode)); + } + for (i = 0; i < n; ++i) { + u[idx + i] = pdfDocEncoding[s->getChar(i) & 0xff]; + } + len += n; + } + } + return this; +} + +void TextString::expand(int delta) { + int newLen; + + newLen = len + delta; + if (delta > INT_MAX - len) { + // trigger an out-of-memory error + size = -1; + } else if (newLen <= size) { + return; + } else if (size > 0 && size <= INT_MAX / 2 && size*2 >= newLen) { + size *= 2; + } else { + size = newLen; + } + u = (Unicode *)greallocn(u, size, sizeof(Unicode)); +} + +GString *TextString::toPDFTextString() { + GString *s; + GBool useUnicode; + int i; + + useUnicode = gFalse; + for (i = 0; i < len; ++i) { + if (u[i] >= 0x80) { + useUnicode = gTrue; + break; + } + } + s = new GString(); + if (useUnicode) { + s->append((char)0xfe); + s->append((char)0xff); + for (i = 0; i < len; ++i) { + s->append((char)(u[i] >> 8)); + s->append((char)u[i]); + } + } else { + for (i = 0; i < len; ++i) { + s->append((char)u[i]); + } + } + return s; +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.h new file mode 100644 index 00000000000..fac15e94319 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/TextString.h @@ -0,0 +1,66 @@ +//======================================================================== +// +// TextString.h +// +// Copyright 2011-2013 Glyph & Cog, LLC +// +// Represents a PDF "text string", which can either be a UTF-16BE +// string (with a leading byte order marker), or an 8-bit string in +// PDFDocEncoding. +// +//======================================================================== + +#ifndef TEXTSTRING_H +#define TEXTSTRING_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +class GString; + +//------------------------------------------------------------------------ + +class TextString { +public: + + // Create an empty TextString. + TextString(); + + // Create a TextString from a PDF text string. + TextString(GString *s); + + // Copy a TextString. + TextString(TextString *s); + + ~TextString(); + + // Append a Unicode character or PDF text string to this TextString. + TextString *append(Unicode c); + TextString *append(GString *s); + + // Insert a Unicode character or PDF text string in this TextString. + TextString *insert(int idx, Unicode c); + TextString *insert(int idx, GString *s); + + // Get the Unicode characters in the TextString. + int getLength() { return len; } + Unicode *getUnicode() { return u; } + + // Create a PDF text string from a TextString. + GString *toPDFTextString(); + +private: + + void expand(int delta); + + Unicode *u; // NB: not null-terminated + int len; + int size; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UTF8.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UTF8.h index 8536dbf9436..8536dbf9436 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UTF8.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UTF8.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMap.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMap.cc index 31f0c218eb9..31f0c218eb9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMap.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMap.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMap.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMap.h index 66c482ca79f..66c482ca79f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMap.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMap.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMapTables.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMapTables.h index 073e474e6be..073e474e6be 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeMapTables.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeMapTables.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeTypeTable.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeTypeTable.cc index edd29701a2f..34e68dc774d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeTypeTable.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeTypeTable.cc @@ -2,7 +2,7 @@ // // UnicodeTypeTable.cc // -// Copyright 2004 Glyph & Cog, LLC +// Copyright 2004-2013 Glyph & Cog, LLC // //======================================================================== @@ -20,21 +20,21 @@ struct UnicodeCaseTableVector { }; static UnicodeMapTableEntry typeTable[256] = { - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN###NNNNN################NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#N####NNNNLNNNNN####NLNNN#LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N....NNNNLNNNNN..##NLNNN#LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLNNNNNNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, - { "RRRR#########RNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNN####################RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' }, + { "RRRR.........RNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNN#################.##RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' }, { "RRRRRRRRRRRRRRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'N' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL##LLLLLLLNNNNN", 'X' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLL##NNNNNNNNNNNNNN", 'X' }, - { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN#NLLLLL", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL..LLLLLLLNNNNN", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLL..NNNNNNNNNNNNNN", 'X' }, + { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN.NLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNN#####LLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNN.....LLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, @@ -43,7 +43,7 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL#LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL.LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNNNLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'L' }, @@ -52,9 +52,9 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' }, - { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRN#####NNNNNNNNNNNNNNN#NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#L##########NNNL############NNN###################################NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL#LLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNN##NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRN.....NNNNNNNNNNNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#L########..NNNL##########..NNN...................................NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL.LLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNN..NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN####################LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { NULL, 'N' }, @@ -271,11 +271,11 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { NULL, 'L' }, { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRR#RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, { NULL, 'R' }, { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN#N#NN#NNNNNNNNN#NN##NNNNN##NRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, - { "NNN###NNNNN################NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL#####NNN##NNNNNNNNNNNNNNNNNNNNNNNLL", 'X' } + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N.NN.NNNNNNNNN.NN..NNNNN..NRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "NNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.....NNN..NNNNNNNNNNNNNNNNNNNNNNNLL", 'X' } }; static UnicodeCaseTableVector caseTable00 = {{ @@ -935,13 +935,23 @@ GBool unicodeTypeR(Unicode c) { } GBool unicodeTypeNum(Unicode c) { - return getType(c) == '#'; + char t; + + t = getType(c); + return t == '#' || t == '.'; } GBool unicodeTypeAlphaNum(Unicode c) { char t; t = getType(c); + return t == 'L' || t == 'R' || t == '#' || t == '.'; +} + +GBool unicodeTypeWord(Unicode c) { + char t; + + t = getType(c); return t == 'L' || t == 'R' || t == '#'; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeTypeTable.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeTypeTable.h index 879363d2827..3230d927891 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/UnicodeTypeTable.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/UnicodeTypeTable.h @@ -2,7 +2,7 @@ // // UnicodeTypeTable.h // -// Copyright 2003 Glyph & Cog, LLC +// Copyright 2003-2013 Glyph & Cog, LLC // //======================================================================== @@ -19,6 +19,8 @@ extern GBool unicodeTypeNum(Unicode c); extern GBool unicodeTypeAlphaNum(Unicode c); +extern GBool unicodeTypeWord(Unicode c); + extern Unicode unicodeToUpper(Unicode c); #endif diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.cc new file mode 100644 index 00000000000..fd420a9e424 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.cc @@ -0,0 +1,1458 @@ +//======================================================================== +// +// XFAForm.cc +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "Error.h" +#include "Object.h" +#include "PDFDoc.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "Zoox.h" +#include "XFAForm.h" + +#ifdef _WIN32 +# define strcasecmp stricmp +# define strncasecmp strnicmp +#endif + +//------------------------------------------------------------------------ + +// 5 bars + 5 spaces -- each can be wide (1) or narrow (0) +// (there are always exactly 3 wide elements; +// the last space is always narrow) +static Guchar code3Of9Data[128][10] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x00 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x10 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 0, 0, 0 }, // ' ' = 0x20 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 }, // '$' = 0x24 + { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0 }, // '%' = 0x25 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 0, 1, 0, 1, 0, 0, 0 }, // '*' = 0x2a + { 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 }, // '+' = 0x2b + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 }, // '-' = 0x2d + { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0 }, // '.' = 0x2e + { 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }, // '/' = 0x2f + { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0 }, // '0' = 0x30 + { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0 }, // '1' + { 0, 0, 1, 1, 0, 0, 0, 0, 1, 0 }, // '2' + { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, // '3' + { 0, 0, 0, 1, 1, 0, 0, 0, 1, 0 }, // '4' + { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // '5' + { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, // '6' + { 0, 0, 0, 1, 0, 0, 1, 0, 1, 0 }, // '7' + { 1, 0, 0, 1, 0, 0, 1, 0, 0, 0 }, // '8' + { 0, 0, 1, 1, 0, 0, 1, 0, 0, 0 }, // '9' + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x40 + { 1, 0, 0, 0, 0, 1, 0, 0, 1, 0 }, // 'A' = 0x41 + { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 }, // 'B' + { 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 }, // 'C' + { 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 }, // 'D' + { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // 'E' + { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 }, // 'F' + { 0, 0, 0, 0, 0, 1, 1, 0, 1, 0 }, // 'G' + { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0 }, // 'H' + { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0 }, // 'I' + { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, // 'J' + { 1, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 'K' + { 0, 0, 1, 0, 0, 0, 0, 1, 1, 0 }, // 'L' + { 1, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, // 'M' + { 0, 0, 0, 0, 1, 0, 0, 1, 1, 0 }, // 'N' + { 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, // 'O' + { 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, // 'P' = 0x50 + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0 }, // 'Q' + { 1, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 'R' + { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, // 'S' + { 0, 0, 0, 0, 1, 0, 1, 1, 0, 0 }, // 'T' + { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0 }, // 'U' + { 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 }, // 'V' + { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // 'W' + { 0, 1, 0, 0, 1, 0, 0, 0, 1, 0 }, // 'X' + { 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, // 'Y' + { 0, 1, 1, 0, 1, 0, 0, 0, 0, 0 }, // 'Z' + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x60 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0x70 + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +//------------------------------------------------------------------------ +// XFAForm +//------------------------------------------------------------------------ + +XFAForm *XFAForm::load(PDFDoc *docA, Object *acroFormObj, Object *xfaObj) { + XFAForm *xfaForm; + ZxDoc *xmlA; + ZxElement *tmpl; + Object catDict, resourceDictA, obj1; + GString *data; + GBool fullXFAA; + GString *name; + char buf[4096]; + int n, i; + + docA->getXRef()->getCatalog(&catDict); + catDict.dictLookup("NeedsRendering", &obj1); + fullXFAA = obj1.isBool() && obj1.getBool(); + obj1.free(); + catDict.free(); + + if (xfaObj->isStream()) { + data = new GString(); + xfaObj->streamReset(); + while ((n = xfaObj->getStream()->getBlock(buf, sizeof(buf))) > 0) { + data->append(buf, n); + } + } else if (xfaObj->isArray()) { + data = new GString(); + for (i = 1; i < xfaObj->arrayGetLength(); i += 2) { + if (!xfaObj->arrayGet(i, &obj1)->isStream()) { + error(errSyntaxError, -1, "XFA array element is wrong type"); + obj1.free(); + delete data; + return NULL; + } + obj1.streamReset(); + while ((n = obj1.getStream()->getBlock(buf, sizeof(buf))) > 0) { + data->append(buf, n); + } + obj1.free(); + } + } else { + error(errSyntaxError, -1, "XFA object is wrong type"); + return NULL; + } + + xmlA = ZxDoc::loadMem(data->getCString(), data->getLength()); + delete data; + if (!xmlA) { + error(errSyntaxError, -1, "Invalid XML in XFA form"); + return NULL; + } + + if (acroFormObj->isDict()) { + acroFormObj->dictLookup("DR", &resourceDictA); + } + + xfaForm = new XFAForm(docA, xmlA, &resourceDictA, fullXFAA); + + resourceDictA.free(); + + if (xfaForm->xml->getRoot()) { + if ((tmpl = xfaForm->xml->getRoot()->findFirstChildElement("template"))) { + name = new GString("form"); + xfaForm->curPageNum = 1; + xfaForm->curXOffset = xfaForm->curYOffset = 0; + xfaForm->scanFields(tmpl, name, name); + delete name; + } + } + + return xfaForm; +} + +XFAForm::XFAForm(PDFDoc *docA, ZxDoc *xmlA, Object *resourceDictA, + GBool fullXFAA): Form(docA) { + xml = xmlA; + fields = new GList(); + resourceDictA->copy(&resourceDict); + fullXFA = fullXFAA; +} + +XFAForm::~XFAForm() { + delete xml; + deleteGList(fields, XFAFormField); + resourceDict.free(); +} + +void XFAForm::scanFields(ZxElement *elem, GString *name, GString *dataName) { + ZxAttr *attr; + ZxNode *child; + ZxElement *bindElem; + GHash *names1, *names2; + GString *childName, *fullName, *fullDataName; + int i; + + //~ need to handle subform + + //~ need to handle exclGroup + //~ - fields in an exclGroup may/must(?) not have names + //~ - each field has an items element with the the value when that + //~ field is selected + + if (elem->isElement("field")) { + fields->append(new XFAFormField(this, elem, name->copy(), + dataName->copy(), curPageNum, + curXOffset, curYOffset)); + } else if (elem->isElement("breakBefore")) { + if ((attr = elem->findAttr("targetType")) && + !attr->getValue()->cmp("pageArea") && + (attr = elem->findAttr("startNew")) && + !attr->getValue()->cmp("1")) { + ++curPageNum; + } + } else if (elem->isElement("break")) { + if ((attr = elem->findAttr("before")) && + !attr->getValue()->cmp("pageArea") && + (attr = elem->findAttr("startNew")) && + !attr->getValue()->cmp("1")) { + ++curPageNum; + } + } else if (elem->isElement("contentArea")) { + curXOffset = XFAFormField::getMeasurement(elem->findAttr("x"), 0); + curYOffset = XFAFormField::getMeasurement(elem->findAttr("y"), 0); + } else { + names1 = new GHash(); + for (child = elem->getFirstChild(); child; child = child->getNextChild()) { + if (child->isElement() && + (attr = ((ZxElement *)child)->findAttr("name"))) { + childName = attr->getValue(); + names1->replace(childName, names1->lookupInt(childName) + 1); + } + } + names2 = new GHash(); + for (child = elem->getFirstChild(); child; child = child->getNextChild()) { + if (child->isElement()) { + if (!((bindElem = child->findFirstChildElement("bind")) && + (attr = bindElem->findAttr("match")) && + !attr->getValue()->cmp("none")) && + (attr = ((ZxElement *)child)->findAttr("name"))) { + childName = attr->getValue(); + if (names1->lookupInt(childName) > 1) { + i = names2->lookupInt(childName); + fullName = GString::format("{0:t}.{1:t}[{2:d}]", + name, childName, i); + fullDataName = GString::format("{0:t}.{1:t}[{2:d}]", + dataName, childName, i); + names2->replace(childName, i + 1); + } else { + fullName = GString::format("{0:t}.{1:t}", name, childName); + fullDataName = GString::format("{0:t}.{1:t}", dataName, childName); + } + } else { + fullName = name->copy(); + fullDataName = dataName->copy(); + } + scanFields((ZxElement *)child, fullName, fullDataName); + delete fullName; + delete fullDataName; + } + } + delete names1; + delete names2; + } +} + +void XFAForm::draw(int pageNum, Gfx *gfx, GBool printing) { + GfxFontDict *fontDict; + Object obj1; + int i; + + // build the font dictionary + if (resourceDict.isDict() && + resourceDict.dictLookup("Font", &obj1)->isDict()) { + fontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict()); + } else { + fontDict = NULL; + } + obj1.free(); + + for (i = 0; i < fields->getLength(); ++i) { + ((XFAFormField *)fields->get(i))->draw(pageNum, gfx, printing, fontDict); + } + + delete fontDict; +} + +int XFAForm::getNumFields() { + return fields->getLength(); +} + +FormField *XFAForm::getField(int idx) { + return (XFAFormField *)fields->get(idx); +} + +//------------------------------------------------------------------------ +// XFAFormField +//------------------------------------------------------------------------ + +XFAFormField::XFAFormField(XFAForm *xfaFormA, ZxElement *xmlA, GString *nameA, + GString *dataNameA, int pageNumA, + double xOffsetA, double yOffsetA) { + xfaForm = xfaFormA; + xml = xmlA; + name = nameA; + dataName = dataNameA; + pageNum = pageNumA; + xOffset = xOffsetA; + yOffset = yOffsetA; +} + +XFAFormField::~XFAFormField() { + delete name; + delete dataName; +} + +const char *XFAFormField::getType() { + ZxElement *uiElem; + ZxNode *node; + + if ((uiElem = xml->findFirstChildElement("ui"))) { + for (node = uiElem->getFirstChild(); node; node = node->getNextChild()) { + if (node->isElement("textEdit")) { + return "Text"; + } else if (node->isElement("barcode")) { + return "BarCode"; + } + //~ other field types go here + } + } + return NULL; +} + +Unicode *XFAFormField::getName(int *length) { + //~ assumes name is UTF-8 + return utf8ToUnicode(name, length); +} + +Unicode *XFAFormField::getValue(int *length) { + ZxElement *uiElem; + ZxNode *node; + GString *s; + + //~ assumes value is UTF-8 + s = NULL; + if ((uiElem = xml->findFirstChildElement("ui"))) { + for (node = uiElem->getFirstChild(); node; node = node->getNextChild()) { + if (node->isElement("textEdit")) { + s = getFieldValue("text"); + } else if (node->isElement("barcode")) { + s = getFieldValue("text"); + } + //~ other field types go here + } + } + if (!s) { + return NULL; + } + return utf8ToUnicode(s, length); +} + +Unicode *XFAFormField::utf8ToUnicode(GString *s, int *length) { + Unicode *u; + int n, size, c0, c1, c2, c3, c4, c5, i; + + n = size = 0; + u = NULL; + i = 0; + while (i < s->getLength()) { + if (n == size) { + size = size ? size * 2 : 16; + u = (Unicode *)greallocn(u, size, sizeof(Unicode)); + } + c0 = s->getChar(i++) & 0xff; + if (c0 <= 0x7f) { + u[n++] = c0; + } else if (c0 <= 0xdf && i < n) { + c1 = s->getChar(i++) & 0xff; + u[n++] = ((c0 & 0x1f) << 6) | (c1 & 0x3f); + } else if (c0 <= 0xef && i+1 < n) { + c1 = s->getChar(i++) & 0xff; + c2 = s->getChar(i++) & 0xff; + u[n++] = ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f); + } else if (c0 <= 0xf7 && i+2 < n) { + c1 = s->getChar(i++) & 0xff; + c2 = s->getChar(i++) & 0xff; + c3 = s->getChar(i++) & 0xff; + u[n++] = ((c0 & 0x07) << 18) | ((c1 & 0x3f) << 12) | ((c2 & 0x3f) << 6) + | (c3 & 0x3f); + } else if (c0 <= 0xfb && i+3 < n) { + c1 = s->getChar(i++) & 0xff; + c2 = s->getChar(i++) & 0xff; + c3 = s->getChar(i++) & 0xff; + c4 = s->getChar(i++) & 0xff; + u[n++] = ((c0 & 0x03) << 24) | ((c1 & 0x3f) << 18) | ((c2 & 0x3f) << 12) + | ((c3 & 0x3f) << 6) | (c4 & 0x3f); + } else if (c0 <= 0xfd && i+4 < n) { + c1 = s->getChar(i++) & 0xff; + c2 = s->getChar(i++) & 0xff; + c3 = s->getChar(i++) & 0xff; + c4 = s->getChar(i++) & 0xff; + c5 = s->getChar(i++) & 0xff; + u[n++] = ((c0 & 0x01) << 30) | ((c1 & 0x3f) << 24) | ((c2 & 0x3f) << 18) + | ((c3 & 0x3f) << 12) | ((c4 & 0x3f) << 6) | (c5 & 0x3f); + } else { + u[n++] = '?'; + } + } + *length = n; + return u; +} + +void XFAFormField::draw(int pageNumA, Gfx *gfx, GBool printing, + GfxFontDict *fontDict) { + Page *page; + PDFRectangle *pageRect; + ZxElement *uiElem; + ZxNode *node; + ZxAttr *attr; + GString *appearBuf; + MemStream *appearStream; + Object appearDict, appearance, obj1, obj2; + double mat[6]; + double x, y, w, h, x2, y2, w2, h2, x3, y3, w3, h3; + double anchorX, anchorY; + int pageRot, rot, rot3; + + if (pageNumA != pageNum) { + return; + } + + page = xfaForm->doc->getCatalog()->getPage(pageNum); + pageRect = page->getMediaBox(); + pageRot = page->getRotate(); + + anchorX = 0; + anchorY = 0; + if ((attr = xml->findAttr("anchorType"))) { + if (!attr->getValue()->cmp("topLeft")) { + anchorX = 0; + anchorY = 0; + } else if (!attr->getValue()->cmp("topCenter")) { + anchorX = 0.5; + anchorY = 0; + } else if (!attr->getValue()->cmp("topRight")) { + anchorX = 1; + anchorY = 0; + } else if (!attr->getValue()->cmp("middleLeft")) { + anchorX = 0; + anchorY = 0.5; + } else if (!attr->getValue()->cmp("middleCenter")) { + anchorX = 0.5; + anchorY = 0.5; + } else if (!attr->getValue()->cmp("middleRight")) { + anchorX = 1; + anchorY = 0.5; + } else if (!attr->getValue()->cmp("bottomLeft")) { + anchorX = 0; + anchorY = 1; + } else if (!attr->getValue()->cmp("bottomCenter")) { + anchorX = 0.5; + anchorY = 1; + } else if (!attr->getValue()->cmp("bottomRight")) { + anchorX = 1; + anchorY = 1; + } + } + x = getMeasurement(xml->findAttr("x"), 0) + xOffset; + y = getMeasurement(xml->findAttr("y"), 0) + yOffset; + w = getMeasurement(xml->findAttr("w"), 0); + h = getMeasurement(xml->findAttr("h"), 0); + if ((attr = xml->findAttr("rotate"))) { + rot = atoi(attr->getValue()->getCString()); + if ((rot %= 360) < 0) { + rot += 360; + } + } else { + rot = 0; + } + + // get annot rect (UL corner, width, height) in XFA coords + // notes: + // - XFA coordinates are top-left origin, after page rotation + // - XFA coordinates are dependent on choice of anchor point + // and field rotation + switch (rot) { + case 0: + default: + x2 = x - anchorX * w; + y2 = y - anchorY * h; + w2 = w; + h2 = h; + break; + case 90: + x2 = x - anchorY * h; + y2 = y - (1 - anchorX) * w; + w2 = h; + h2 = w; + break; + case 180: + x2 = x - (1 - anchorX) * w; + y2 = y - (1 - anchorY) * h; + w2 = w; + h2 = h; + break; + case 270: + x2 = x - (1 - anchorY) * h; + y2 = y - anchorX * w; + w2 = h; + h2 = w; + break; + } + + // convert annot rect to PDF coords (LL corner, width, height), + // taking page rotation into account + switch (pageRot) { + case 0: + default: + x3 = pageRect->x1 + x2; + y3 = pageRect->y2 - (y2 + h2); + w3 = w2; + h3 = h2; + break; + case 90: + x3 = pageRect->x1 + y2; + y3 = pageRect->y1 + x2; + w3 = h2; + h3 = w2; + break; + case 180: + x3 = pageRect->x2 - (x2 + w2); + y3 = pageRect->y1 + y2; + w3 = w2; + h3 = h2; + break; + case 270: + x3 = pageRect->x2 - (y2 + h2); + y3 = pageRect->y1 + (x2 + w2); + w3 = h2; + h3 = w2; + break; + } + rot3 = (rot + pageRot) % 360; + + // generate transform matrix + switch (rot3) { + case 0: + default: + mat[0] = 1; mat[1] = 0; + mat[2] = 0; mat[3] = 1; + mat[4] = 0; mat[5] = 0; + break; + case 90: + mat[0] = 0; mat[1] = 1; + mat[2] = -1; mat[3] = 0; + mat[4] = h; mat[5] = 0; + break; + case 180: + mat[0] = -1; mat[1] = 0; + mat[2] = 0; mat[3] = -1; + mat[4] = w; mat[5] = h; + break; + case 270: + mat[0] = 0; mat[1] = -1; + mat[2] = 1; mat[3] = 0; + mat[4] = 0; mat[5] = w; + break; + } + + // get the appearance stream data + appearBuf = new GString(); +#if 0 //~ for debugging + appearBuf->appendf("q 1 1 0 rg 0 0 {0:.4f} {1:.4f} re f Q\n", w, h); +#endif + if ((uiElem = xml->findFirstChildElement("ui"))) { + for (node = uiElem->getFirstChild(); node; node = node->getNextChild()) { + if (node->isElement("textEdit")) { + drawTextEdit(fontDict, w, h, rot3, appearBuf); + break; + } else if (node->isElement("barcode")) { + drawBarCode(fontDict, w, h, rot3, appearBuf); + break; + } + //~ other field types go here + } + } + + // create the appearance stream + appearDict.initDict(xfaForm->doc->getXRef()); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(xfaForm->doc->getXRef()); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(w)); + obj1.arrayAdd(obj2.initReal(h)); + appearDict.dictAdd(copyString("BBox"), &obj1); + obj1.initArray(xfaForm->doc->getXRef()); + obj1.arrayAdd(obj2.initReal(mat[0])); + obj1.arrayAdd(obj2.initReal(mat[1])); + obj1.arrayAdd(obj2.initReal(mat[2])); + obj1.arrayAdd(obj2.initReal(mat[3])); + obj1.arrayAdd(obj2.initReal(mat[4])); + obj1.arrayAdd(obj2.initReal(mat[5])); + appearDict.dictAdd(copyString("Matrix"), &obj1); + if (xfaForm->resourceDict.isDict()) { + appearDict.dictAdd(copyString("Resources"), + xfaForm->resourceDict.copy(&obj1)); + } + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.initStream(appearStream); + gfx->drawAnnot(&appearance, NULL, x3, y3, x3 + w3, y3 + h3); + appearance.free(); + delete appearBuf; +} + +void XFAFormField::drawTextEdit(GfxFontDict *fontDict, + double w, double h, int rot, + GString *appearBuf) { + ZxElement *valueElem, *textElem, *uiElem, *textEditElem, *combElem; + ZxElement *fontElem, *paraElem; + ZxAttr *attr; + GString *value, *fontName; + double fontSize; + int maxChars, combCells; + GBool multiLine, bold, italic; + XFAHorizAlign hAlign; + XFAVertAlign vAlign; + + if (!(value = getFieldValue("text"))) { + return; + } + + maxChars = 0; + if ((valueElem = xml->findFirstChildElement("value")) && + (textElem = valueElem->findFirstChildElement("text")) && + (attr = textElem->findAttr("maxChars"))) { + maxChars = atoi(attr->getValue()->getCString()); + } + + multiLine = gFalse; + combCells = 0; + if ((uiElem = xml->findFirstChildElement("ui")) && + (textEditElem = uiElem->findFirstChildElement("textEdit"))) { + if ((attr = textEditElem->findAttr("multiLine")) && + !attr->getValue()->cmp("1")) { + multiLine = gTrue; + } + if ((combElem = textEditElem->findFirstChildElement("comb"))) { + if ((attr = combElem->findAttr("numberOfCells"))) { + combCells = atoi(attr->getValue()->getCString()); + } else { + combCells = maxChars; + } + } + } + + fontName = NULL; + fontSize = 10; + bold = gFalse; + italic = gFalse; + if ((fontElem = xml->findFirstChildElement("font"))) { + if ((attr = fontElem->findAttr("typeface"))) { + fontName = attr->getValue()->copy(); + } + if ((attr = fontElem->findAttr("weight"))) { + if (!attr->getValue()->cmp("bold")) { + bold = gTrue; + } + } + if ((attr = fontElem->findAttr("posture"))) { + if (!attr->getValue()->cmp("italic")) { + italic = gTrue; + } + } + if ((attr = fontElem->findAttr("size"))) { + fontSize = getMeasurement(attr, fontSize); + } + } + if (!fontName) { + fontName = new GString("Courier"); + } + + hAlign = xfaHAlignLeft; + vAlign = xfaVAlignTop; + if ((paraElem = xml->findFirstChildElement("para"))) { + if ((attr = paraElem->findAttr("hAlign"))) { + if (!attr->getValue()->cmp("left")) { + hAlign = xfaHAlignLeft; + } else if (!attr->getValue()->cmp("center")) { + hAlign = xfaHAlignCenter; + } else if (!attr->getValue()->cmp("right")) { + hAlign = xfaHAlignRight; + } + //~ other hAlign values (justify, justifyAll, radix) are + //~ currently unsupported + } + if ((attr = paraElem->findAttr("vAlign"))) { + if (!attr->getValue()->cmp("top")) { + vAlign = xfaVAlignTop; + } else if (!attr->getValue()->cmp("bottom")) { + vAlign = xfaVAlignBottom; + } else if (!attr->getValue()->cmp("middle")) { + vAlign = xfaVAlignMiddle; + } + } + } + + drawText(value, multiLine, combCells, + fontName, bold, italic, fontSize, + hAlign, vAlign, 0, 0, w, h, gFalse, fontDict, appearBuf); + delete fontName; +} + +void XFAFormField::drawBarCode(GfxFontDict *fontDict, + double w, double h, int rot, + GString *appearBuf) { + ZxElement *uiElem, *barcodeElem, *fontElem; + ZxAttr *attr; + GString *value, *value2, *barcodeType, *textLocation, *fontName, *s1, *s2; + XFAVertAlign textAlign; + double wideNarrowRatio, fontSize; + double yText, wText, yBarcode, hBarcode, wNarrow, xx; + GBool doText; + int dataLength; + GBool bold, italic; + char *p; + int i, j, c; + + //--- get field value + if (!(value = getFieldValue("text"))) { + return; + } + + //--- get field attributes + barcodeType = NULL; + wideNarrowRatio = 3; + dataLength = 0; + textLocation = NULL; + if ((uiElem = xml->findFirstChildElement("ui")) && + (barcodeElem = uiElem->findFirstChildElement("barcode"))) { + if ((attr = barcodeElem->findAttr("type"))) { + barcodeType = attr->getValue(); + } + if ((attr = barcodeElem->findAttr("wideNarrowRatio"))) { + s1 = attr->getValue(); + if ((p = strchr(s1->getCString(), ':'))) { + s2 = new GString(s1, 0, p - s1->getCString()); + wideNarrowRatio = atof(p + 1); + if (wideNarrowRatio == 0) { + wideNarrowRatio = 1; + } + wideNarrowRatio = atof(s2->getCString()) / wideNarrowRatio; + delete s2; + } else { + wideNarrowRatio = atof(s1->getCString()); + } + } + if ((attr = barcodeElem->findAttr("dataLength"))) { + dataLength = atoi(attr->getValue()->getCString()); + } + if ((attr = barcodeElem->findAttr("textLocation"))) { + textLocation = attr->getValue(); + } + } + if (!barcodeType) { + error(errSyntaxError, -1, "Missing 'type' attribute in XFA barcode field"); + return; + } + if (!dataLength) { + error(errSyntaxError, -1, + "Missing 'dataLength' attribute in XFA barcode field"); + return; + } + + //--- get font + fontName = NULL; + fontSize = 0.2 * h; + bold = gFalse; + italic = gFalse; + if ((fontElem = xml->findFirstChildElement("font"))) { + if ((attr = fontElem->findAttr("typeface"))) { + fontName = attr->getValue()->copy(); + } + if ((attr = fontElem->findAttr("weight"))) { + if (!attr->getValue()->cmp("bold")) { + bold = gTrue; + } + } + if ((attr = fontElem->findAttr("posture"))) { + if (!attr->getValue()->cmp("italic")) { + italic = gTrue; + } + } + if ((attr = fontElem->findAttr("size"))) { + fontSize = getMeasurement(attr, fontSize); + } + } + if (!fontName) { + fontName = new GString("Courier"); + } + + //--- compute the embedded text type position + doText = gTrue; + yText = yBarcode = hBarcode = 0; + if (textLocation && !textLocation->cmp("above")) { + textAlign = xfaVAlignTop; + yText = h; + yBarcode = 0; + hBarcode = h - fontSize; + } else if (textLocation && !textLocation->cmp("belowEmbedded")) { + textAlign = xfaVAlignBottom; + yText = 0; + yBarcode = 0; + hBarcode = h; + } else if (textLocation && !textLocation->cmp("aboveEmbedded")) { + textAlign = xfaVAlignTop; + yText = h; + yBarcode = 0; + hBarcode = h; + } else if (textLocation && !textLocation->cmp("none")) { + textAlign = xfaVAlignBottom; // make gcc happy + doText = gFalse; + } else { // default is "below" + textAlign = xfaVAlignBottom; + yText = 0; + yBarcode = fontSize; + hBarcode = h - fontSize; + } + wText = w; + + //--- remove extraneous start/stop chars + //~ this may depend on barcode type + value2 = value->copy(); + if (value2->getLength() >= 1 && value2->getChar(0) == '*') { + value2->del(0); + } + if (value2->getLength() >= 1 && + value2->getChar(value2->getLength() - 1) == '*') { + value2->del(value2->getLength() - 1); + } + + //--- draw the bar code + if (!barcodeType->cmp("code3Of9")) { + appearBuf->append("0 g\n"); + wNarrow = w / ((7 + 3 * wideNarrowRatio) * (dataLength + 2)); + xx = 0; + for (i = -1; i <= value2->getLength(); ++i) { + if (i < 0 || i >= value2->getLength()) { + c = '*'; + } else { + c = value2->getChar(i) & 0x7f; + } + for (j = 0; j < 10; j += 2) { + appearBuf->appendf("{0:.4f} {1:.4f} {2:.4f} {3:.4f} re f\n", + xx, yBarcode, + (code3Of9Data[c][j] ? wideNarrowRatio : 1) * wNarrow, + hBarcode); + xx += ((code3Of9Data[c][j] ? wideNarrowRatio : 1) + + (code3Of9Data[c][j+1] ? wideNarrowRatio : 1)) * wNarrow; + } + } + // center the text on the drawn barcode (not the max length barcode) + wText = (value2->getLength() + 2) * (7 + 3 * wideNarrowRatio) * wNarrow; + } else { + error(errSyntaxError, -1, + "Unimplemented barcode type in XFA barcode field"); + } + //~ add other barcode types here + + //--- draw the embedded text + if (doText) { + appearBuf->append("0 g\n"); + drawText(value2, gFalse, 0, + fontName, bold, italic, fontSize, + xfaHAlignCenter, textAlign, 0, yText, wText, h, gTrue, + fontDict, appearBuf); + } + delete fontName; + delete value2; +} + +Object *XFAFormField::getResources(Object *res) { + return xfaForm->resourceDict.copy(res); +} + +double XFAFormField::getMeasurement(ZxAttr *attr, double defaultVal) { + GString *s; + double val, mul; + GBool neg; + int i; + + if (!attr) { + return defaultVal; + } + s = attr->getValue(); + i = 0; + neg = gFalse; + if (i < s->getLength() && s->getChar(i) == '+') { + ++i; + } else if (i < s->getLength() && s->getChar(i) == '-') { + neg = gTrue; + ++i; + } + val = 0; + while (i < s->getLength() && s->getChar(i) >= '0' && s->getChar(i) <= '9') { + val = val * 10 + s->getChar(i) - '0'; + ++i; + } + if (i < s->getLength() && s->getChar(i) == '.') { + ++i; + mul = 0.1; + while (i < s->getLength() && s->getChar(i) >= '0' && s->getChar(i) <= '9') { + val += mul * (s->getChar(i) - '0'); + mul *= 0.1; + ++i; + } + } + if (neg) { + val = -val; + } + if (i+1 < s->getLength()) { + if (s->getChar(i) == 'i' && s->getChar(i+1) == 'n') { + val *= 72; + } else if (s->getChar(i) == 'p' && s->getChar(i+1) == 't') { + // no change + } else if (s->getChar(i) == 'c' && s->getChar(i+1) == 'm') { + val *= 72 / 2.54; + } else if (s->getChar(i) == 'm' && s->getChar(i+1) == 'm') { + val *= 72 / 25.4; + } else { + // default to inches + val *= 72; + } + } else { + // default to inches + val *= 72; + } + return val; +} + +GString *XFAFormField::getFieldValue(const char *valueChildType) { + ZxElement *valueElem, *datasets, *data, *elem; + char *p; + + // check the <value> element within the field + if ((valueElem = xml->findFirstChildElement("value")) && + (elem = valueElem->findFirstChildElement(valueChildType))) { + if (elem->getFirstChild() && + elem->getFirstChild()->isCharData() && + ((ZxCharData *)elem->getFirstChild())->getData()->getLength() > 0) { + return ((ZxCharData *)elem->getFirstChild())->getData(); + } + } + + // check the <datasets> packet + if (!xfaForm->xml->getRoot() || + !(datasets = + xfaForm->xml->getRoot()->findFirstChildElement("xfa:datasets")) || + !(data = datasets->findFirstChildElement("xfa:data"))) { + return NULL; + } + p = name->getCString(); + if (!strncmp(p, "form.", 5)) { + p += 5; + } else { + return NULL; + } + elem = findFieldData(data, p); + if (elem && + elem->getFirstChild() && + elem->getFirstChild()->isCharData() && + ((ZxCharData *)elem->getFirstChild())->getData()->getLength() > 0) { + return ((ZxCharData *)elem->getFirstChild())->getData(); + } + + return NULL; +} + +ZxElement *XFAFormField::findFieldData(ZxElement *elem, char *partName) { + ZxNode *node; + GString *nodeName; + int curIdx, idx, n; + + curIdx = 0; + for (node = elem->getFirstChild(); node; node = node->getNextChild()) { + if (node->isElement()) { + nodeName = ((ZxElement *)node)->getType(); + n = nodeName->getLength(); + if (!strncmp(partName, nodeName->getCString(), n)) { + if (partName[n] == '[') { + idx = atoi(partName + n + 1); + if (idx == curIdx) { + for (++n; partName[n] && partName[n-1] != ']'; ++n) ; + } else { + ++curIdx; + continue; + } + } + if (!partName[n]) { + return (ZxElement *)node; + } else if (partName[n] == '.') { + return findFieldData((ZxElement *)node, partName + n + 1); + } + } + } + } + return NULL; +} + +void XFAFormField::transform(int rot, double w, double h, + double *wNew, double *hNew, GString *appearBuf) { + switch (rot) { + case 0: + default: + appearBuf->appendf("1 0 0 1 0 {0:.4f} cm\n", -h); + break; + case 90: + appearBuf->appendf("0 1 -1 0 {0:.4f} 0 cm\n", w); + *wNew = h; + *hNew = w; + break; + case 180: + appearBuf->appendf("-1 0 0 -1 {0:.4f} {1:.4f} cm\n", w, h); + *wNew = w; + *hNew = h; + break; + case 270: + appearBuf->appendf("0 -1 1 0 0 {0:.4f} cm\n", h); + *wNew = h; + *hNew = w; + break; + } +} + +void XFAFormField::drawText(GString *text, GBool multiLine, int combCells, + GString *fontName, GBool bold, + GBool italic, double fontSize, + XFAHorizAlign hAlign, XFAVertAlign vAlign, + double x, double y, double w, double h, + GBool whiteBackground, + GfxFontDict *fontDict, GString *appearBuf) { + GfxFont *font; + GString *s; + double xx, yy, tw, charWidth, lineHeight; + double rectX, rectY, rectW, rectH; + int line, i, j, k, c, rectI; + + //~ deal with Unicode text (is it UTF-8?) + + // find the font + if (!(font = findFont(fontDict, fontName, bold, italic))) { + error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', {1:s}, {2:s} used in XFA field", + fontName, bold ? "bold" : "non-bold", + italic ? "italic" : "non-italic"); + return; + } + + // setup + rectW = rectH = 0; + rectI = appearBuf->getLength(); + appearBuf->append("BT\n"); + appearBuf->appendf("/{0:t} {1:.2f} Tf\n", font->getTag(), fontSize); + + // multi-line text + if (multiLine) { + + // figure out how many lines will fit + lineHeight = 1.2 * fontSize; + + // write a series of lines of text + line = 0; + i = 0; + while (i < text->getLength()) { + + getNextLine(text, i, font, fontSize, w, &j, &tw, &k); + if (tw > rectW) { + rectW = tw; + } + + // compute text start position + switch (hAlign) { + case xfaHAlignLeft: + default: + xx = x; + break; + case xfaHAlignCenter: + xx = x + 0.5 * (w - tw); + break; + case xfaHAlignRight: + xx = x + w - tw; + break; + } + yy = y + h - fontSize * font->getAscent() - line * lineHeight; + + // draw the line + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", xx, yy); + appearBuf->append('('); + for (; i < j; ++i) { + c = text->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append(c); + } + } + appearBuf->append(") Tj\n"); + + // next line + i = k; + ++line; + } + rectH = line * lineHeight; + rectY = y + h - rectH; + + // comb formatting + } else if (combCells > 0) { + + // compute comb spacing + tw = w / combCells; + + // compute text start position + switch (hAlign) { + case xfaHAlignLeft: + default: + xx = x; + break; + case xfaHAlignCenter: + xx = x + (int)(0.5 * (combCells - text->getLength())) * tw; + break; + case xfaHAlignRight: + xx = x + w - text->getLength() * tw; + break; + } + rectW = text->getLength() * tw; + switch (vAlign) { + case xfaVAlignTop: + default: + yy = y + h - fontSize * font->getAscent(); + break; + case xfaVAlignMiddle: + yy = y + 0.5 * (h - fontSize * (font->getAscent() + + font->getDescent())); + break; + case xfaVAlignBottom: + yy = y - fontSize * font->getDescent(); + break; + } + rectY = yy + fontSize * font->getDescent(); + rectH = fontSize * (font->getAscent() - font->getDescent()); + + // write the text string + for (i = 0; i < text->getLength(); ++i) { + c = text->getChar(i) & 0xff; + if (!font->isCIDFont()) { + charWidth = fontSize * ((Gfx8BitFont *)font)->getWidth(c); + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", + xx + i * tw + 0.5 * (tw - charWidth), yy); + } else { + appearBuf->appendf("1 0 0 1 {0:.4f} {1:.4f} Tm\n", + xx + i * tw, yy); + } + appearBuf->append('('); + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("{0:.4f} 0 Td\n", w); + } else { + appearBuf->append(c); + } + appearBuf->append(") Tj\n"); + } + + // regular (non-comb) formatting + } else { + + // compute string width + if (!font->isCIDFont()) { + tw = 0; + for (i = 0; i < text->getLength(); ++i) { + tw += ((Gfx8BitFont *)font)->getWidth(text->getChar(i)); + } + } else { + // otherwise, make a crude estimate + tw = text->getLength() * 0.5; + } + tw *= fontSize; + rectW = tw; + + // compute text start position + switch (hAlign) { + case xfaHAlignLeft: + default: + xx = x; + break; + case xfaHAlignCenter: + xx = x + 0.5 * (w - tw); + break; + case xfaHAlignRight: + xx = x + w - tw; + break; + } + switch (vAlign) { + case xfaVAlignTop: + default: + yy = y + h - fontSize * font->getAscent(); + break; + case xfaVAlignMiddle: + yy = y + 0.5 * (h - fontSize * (font->getAscent() + + font->getDescent())); + break; + case xfaVAlignBottom: + yy = y - fontSize * font->getDescent(); + break; + } + rectY = yy + fontSize * font->getDescent(); + rectH = fontSize * (font->getAscent() - font->getDescent()); + appearBuf->appendf("{0:.4f} {1:.4f} Td\n", xx, yy); + + // write the text string + appearBuf->append('('); + for (i = 0; i < text->getLength(); ++i) { + c = text->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append(c); + } + } + appearBuf->append(") Tj\n"); + } + + // cleanup + appearBuf->append("ET\n"); + + // draw a white rectangle behind the text + if (whiteBackground) { + switch (hAlign) { + case xfaHAlignLeft: + default: + rectX = x; + break; + case xfaHAlignCenter: + rectX = x + 0.5 * (w - rectW); + break; + case xfaHAlignRight: + rectX = x + w - rectW; + break; + } + rectX -= 0.25 * fontSize; + rectW += 0.5 * fontSize; + s = GString::format("q 1 g {0:.4f} {1:.4f} {2:.4f} {3:.4f} re f Q\n", + rectX, rectY, rectW, rectH); + appearBuf->insert(rectI, s); + delete s; + } +} + +// Searches <fontDict> for a font matching(<fontName>, <bold>, +// <italic>). +GfxFont *XFAFormField::findFont(GfxFontDict *fontDict, GString *fontName, + GBool bold, GBool italic) { + GString *reqName, *testName; + GfxFont *font; + GBool foundName, foundBold, foundItalic; + char *p; + char c; + int i, j; + + if (!fontDict) { + return NULL; + } + + reqName = new GString(); + for (i = 0; i < fontName->getLength(); ++i) { + c = fontName->getChar(i); + if (c != ' ') { + reqName->append(c); + } + } + + for (i = 0; i < fontDict->getNumFonts(); ++i) { + font = fontDict->getFont(i); + if (!font || !font->getName()) { + continue; + } + testName = new GString(); + for (j = 0; j < font->getName()->getLength(); ++j) { + c = font->getName()->getChar(j); + if (c != ' ') { + testName->append(c); + } + } + foundName = foundBold = foundItalic = gFalse; + for (p = testName->getCString(); *p; ++p) { + if (!strncasecmp(p, reqName->getCString(), reqName->getLength())) { + foundName = gTrue; + } + if (!strncasecmp(p, "bold", 4)) { + foundBold = gTrue; + } + if (!strncasecmp(p, "italic", 6) || !strncasecmp(p, "oblique", 7)) { + foundItalic = gTrue; + } + } + delete testName; + if (foundName && foundBold == bold && foundItalic == italic) { + delete reqName; + return font; + } + } + + delete reqName; + return NULL; +} + +// Figure out how much text will fit on the next line. Returns: +// *end = one past the last character to be included +// *width = width of the characters start .. end-1 +// *next = index of first character on the following line +void XFAFormField::getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next) { + double w, dw; + int j, k, c; + + // figure out how much text will fit on the line + //~ what does Adobe do with tabs? + w = 0; + for (j = start; j < text->getLength() && w <= wMax; ++j) { + c = text->getChar(j) & 0xff; + if (c == 0x0a || c == 0x0d) { + break; + } + if (font && !font->isCIDFont()) { + dw = ((Gfx8BitFont *)font)->getWidth(c) * fontSize; + } else { + // otherwise, make a crude estimate + dw = 0.5 * fontSize; + } + w += dw; + } + if (w > wMax) { + for (k = j; k > start && text->getChar(k-1) != ' '; --k) ; + for (; k > start && text->getChar(k-1) == ' '; --k) ; + if (k > start) { + j = k; + } + if (j == start) { + // handle the pathological case where the first character is + // too wide to fit on the line all by itself + j = start + 1; + } + } + *end = j; + + // compute the width + w = 0; + for (k = start; k < j; ++k) { + if (font && !font->isCIDFont()) { + dw = ((Gfx8BitFont *)font)->getWidth(text->getChar(k)) * fontSize; + } else { + // otherwise, make a crude estimate + dw = 0.5 * fontSize; + } + w += dw; + } + *width = w; + + // next line + while (j < text->getLength() && text->getChar(j) == ' ') { + ++j; + } + if (j < text->getLength() && text->getChar(j) == 0x0d) { + ++j; + } + if (j < text->getLength() && text->getChar(j) == 0x0a) { + ++j; + } + *next = j; +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.h new file mode 100644 index 00000000000..95bf14cd4c8 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XFAForm.h @@ -0,0 +1,126 @@ +//======================================================================== +// +// XFAForm.h +// +// Copyright 2012 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XFAFORM_H +#define XFAFORM_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Form.h" + +class ZxDoc; +class ZxElement; +class ZxAttr; + +//------------------------------------------------------------------------ + +enum XFAHorizAlign { + xfaHAlignLeft, + xfaHAlignCenter, + xfaHAlignRight +}; + +enum XFAVertAlign { + xfaVAlignTop, + xfaVAlignBottom, + xfaVAlignMiddle +}; + +//------------------------------------------------------------------------ + +class XFAForm: public Form { +public: + + static XFAForm *load(PDFDoc *docA, Object *acroFormObj, Object *xfaObj); + + virtual ~XFAForm(); + + virtual const char *getType() { return "XFA"; } + + virtual void draw(int pageNum, Gfx *gfx, GBool printing); + + virtual int getNumFields(); + virtual FormField *getField(int idx); + +private: + + XFAForm(PDFDoc *docA, ZxDoc *xmlA, Object *resourceDictA, GBool fullXFAA); + void scanFields(ZxElement *elem, GString *name, GString *dataName); + + ZxDoc *xml; + GList *fields; // [XFAFormField] + Object resourceDict; + GBool fullXFA; // true for "Full XFA", false for + // "XFA Foreground" + int curPageNum; // current page number - used by scanFields() + double curXOffset, // current x,y offset - used by scanFields() + curYOffset; + + friend class XFAFormField; +}; + +//------------------------------------------------------------------------ + +class XFAFormField: public FormField { +public: + + XFAFormField(XFAForm *xfaFormA, ZxElement *xmlA, GString *nameA, + GString *dataNameA, int pageNumA, + double xOffsetA, double yOffsetA); + + virtual ~XFAFormField(); + + virtual const char *getType(); + virtual Unicode *getName(int *length); + virtual Unicode *getValue(int *length); + + virtual Object *getResources(Object *res); + +private: + + Unicode *utf8ToUnicode(GString *s, int *length); + void draw(int pageNumA, Gfx *gfx, GBool printing, GfxFontDict *fontDict); + void drawTextEdit(GfxFontDict *fontDict, + double w, double h, int rot, + GString *appearBuf); + void drawBarCode(GfxFontDict *fontDict, + double w, double h, int rot, + GString *appearBuf); + static double getMeasurement(ZxAttr *attr, double defaultVal); + GString *getFieldValue(const char *valueChildType); + ZxElement *findFieldData(ZxElement *elem, char *partName); + void transform(int rot, double w, double h, + double *wNew, double *hNew, GString *appearBuf); + void drawText(GString *text, GBool multiLine, int combCells, + GString *fontName, GBool bold, + GBool italic, double fontSize, + XFAHorizAlign hAlign, XFAVertAlign vAlign, + double x, double y, double w, double h, + GBool whiteBackground, + GfxFontDict *fontDict, GString *appearBuf); + GfxFont *findFont(GfxFontDict *fontDict, GString *fontName, + GBool bold, GBool italic); + void getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next); + + XFAForm *xfaForm; + ZxElement *xml; + GString *name; + GString *dataName; + int pageNum; + double xOffset, yOffset; + + friend class XFAForm; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFApp.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFApp.cc index 4f5af03a826..4f5af03a826 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFApp.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFApp.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFApp.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFApp.h index 9d4060ac97a..9d4060ac97a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFApp.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFApp.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFCore.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFCore.cc index b98bc3776fa..9a3725f53fc 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFCore.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFCore.cc @@ -493,7 +493,7 @@ void XPDFCore::doAction(LinkAction *action) { } s = ((LinkGoToR *)action)->getFileName()->getCString(); //~ translate path name for VMS (deal with '/') - if (isAbsolutePath(s)) { + if (isAbsolutePath(s) || !doc->getFileName()) { fileName = new GString(s); } else { fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s); @@ -531,7 +531,7 @@ void XPDFCore::doAction(LinkAction *action) { if (!strcmp(s + fileName->getLength() - 4, ".pdf") || !strcmp(s + fileName->getLength() - 4, ".PDF")) { //~ translate path name for VMS (deal with '/') - if (isAbsolutePath(s)) { + if (isAbsolutePath(s) || !doc->getFileName()) { fileName = fileName->copy(); } else { fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s); @@ -640,7 +640,8 @@ void XPDFCore::doAction(LinkAction *action) { if (movieAnnot.dictLookup("Movie", &obj1)->isDict()) { if (obj1.dictLookup("F", &obj2)) { if ((fileName = LinkAction::getFileSpecName(&obj2))) { - if (!isAbsolutePath(fileName->getCString())) { + if (!isAbsolutePath(fileName->getCString()) && + doc->getFileName()) { fileName2 = appendToPath( grabPath(doc->getFileName()->getCString()), fileName->getCString()); @@ -658,6 +659,13 @@ void XPDFCore::doAction(LinkAction *action) { movieAnnot.free(); break; + // unsupported action types + case actionJavaScript: + case actionSubmitForm: + case actionHide: + error(errSyntaxError, -1, "Unsupported link action type"); + break; + // unknown action type case actionUnknown: error(errSyntaxError, -1, "Unknown link action type: '{0:t}'", @@ -1124,6 +1132,9 @@ void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) { case actionMovie: s = "[movie]"; break; + case actionJavaScript: + case actionSubmitForm: + case actionHide: case actionUnknown: s = "[unknown link]"; break; @@ -1356,6 +1367,8 @@ void XPDFCore::redrawRect(PDFCoreTile *tileA, int xSrc, int ySrc, XFillRectangle(display, drawAreaWin, drawAreaGC, xDest, yDest, width, height); } + + XFlush(display); } void XPDFCore::updateScrollbars() { diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFCore.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFCore.h index be1dcfab288..be1dcfab288 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFCore.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFCore.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTree.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTree.cc index bae9cb000a9..bae9cb000a9 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTree.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTree.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTree.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTree.h index be7293a3c2e..be7293a3c2e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTree.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTree.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTreeP.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTreeP.h index 85cb12e5118..85cb12e5118 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFTreeP.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFTreeP.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFViewer.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFViewer.cc index 2de349da788..4292a0e4a7f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFViewer.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFViewer.cc @@ -165,6 +165,7 @@ XPDFViewerCmd XPDFViewer::cmdTab[] = { { "about", 0, gFalse, gFalse, &XPDFViewer::cmdAbout }, { "closeOutline", 0, gFalse, gFalse, &XPDFViewer::cmdCloseOutline }, { "closeWindow", 0, gFalse, gFalse, &XPDFViewer::cmdCloseWindow }, + { "closeWindowOrQuit", 0, gFalse, gFalse, &XPDFViewer::cmdCloseWindowOrQuit }, { "continuousMode", 0, gFalse, gFalse, &XPDFViewer::cmdContinuousMode }, { "endPan", 0, gTrue, gTrue, &XPDFViewer::cmdEndPan }, { "endSelection", 0, gTrue, gTrue, &XPDFViewer::cmdEndSelection }, @@ -384,7 +385,9 @@ void XPDFViewer::open(GString *fileName, int pageA, GString *destName) { int pg; double z; - if (!core->getDoc() || fileName->cmp(core->getDoc()->getFileName())) { + if (!core->getDoc() || + !core->getDoc()->getFileName() || + fileName->cmp(core->getDoc()->getFileName())) { if (!loadFile(fileName, NULL, NULL)) { return; } @@ -445,7 +448,7 @@ GBool XPDFViewer::loadFile(GString *fileName, GString *ownerPassword, void XPDFViewer::reloadFile() { int pg; - if (!core->getDoc()) { + if (!core->getDoc() || !core->getDoc()->getFileName()) { return; } pg = core->getPageNum(); @@ -808,6 +811,11 @@ void XPDFViewer::cmdCloseWindow(GString *args[], int nArgs, app->close(this, gFalse); } +void XPDFViewer::cmdCloseWindowOrQuit(GString *args[], int nArgs, + XEvent *event) { + app->close(this, gTrue); +} + void XPDFViewer::cmdContinuousMode(GString *args[], int nArgs, XEvent *event) { Widget btn; @@ -1803,7 +1811,7 @@ void XPDFViewer::initToolbar(Widget parent) { menuPane = XmCreatePulldownMenu(toolBar, "zoomMenuPane", args, n); for (i = 0; i < nZoomMenuItems; ++i) { n = 0; - s = XmStringCreateLocalized(zoomMenuInfo[i].label); + s = XmStringCreateLocalized((char *)zoomMenuInfo[i].label); XtSetArg(args[n], XmNlabelString, s); ++n; XtSetArg(args[n], XmNuserData, (XtPointer)i); ++n; sprintf(buf, "zoom%d", i); @@ -3422,17 +3430,18 @@ void XPDFViewer::setupPrintDialog() { doc = core->getDoc(); psFileName = globalParams->getPSFile(); if (!psFileName || psFileName->getChar(0) == '|') { - pdfFileName = doc->getFileName(); - p = pdfFileName->getCString() + pdfFileName->getLength() - 4; - if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) { - psFileName2 = new GString(pdfFileName->getCString(), - pdfFileName->getLength() - 4); - } else { - psFileName2 = pdfFileName->copy(); + if ((pdfFileName = doc->getFileName())) { + p = pdfFileName->getCString() + pdfFileName->getLength() - 4; + if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) { + psFileName2 = new GString(pdfFileName->getCString(), + pdfFileName->getLength() - 4); + } else { + psFileName2 = pdfFileName->copy(); + } + psFileName2->append(".ps"); + XmTextFieldSetString(printFileText, psFileName2->getCString()); + delete psFileName2; } - psFileName2->append(".ps"); - XmTextFieldSetString(printFileText, psFileName2->getCString()); - delete psFileName2; } if (psFileName && psFileName->getChar(0) == '|') { XmToggleButtonSetState(printWithCmdBtn, True, False); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFViewer.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFViewer.h index 8a345e841d3..8b03e7fc4fe 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XPDFViewer.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XPDFViewer.h @@ -103,6 +103,7 @@ private: void cmdAbout(GString *args[], int nArgs, XEvent *event); void cmdCloseOutline(GString *args[], int nArgs, XEvent *event); void cmdCloseWindow(GString *args[], int nArgs, XEvent *event); + void cmdCloseWindowOrQuit(GString *args[], int nArgs, XEvent *event); void cmdContinuousMode(GString *args[], int nArgs, XEvent *event); void cmdEndPan(GString *args[], int nArgs, XEvent *event); void cmdEndSelection(GString *args[], int nArgs, XEvent *event); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XRef.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XRef.cc index 83322c3b4dc..71540a9717a 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XRef.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XRef.cc @@ -18,6 +18,7 @@ #include <ctype.h> #include <limits.h> #include "gmem.h" +#include "gfile.h" #include "Object.h" #include "Stream.h" #include "Lexer.h" @@ -43,6 +44,84 @@ #define defPermFlags 0xfffc //------------------------------------------------------------------------ +// XRefPosSet +//------------------------------------------------------------------------ + +class XRefPosSet { +public: + + XRefPosSet(); + ~XRefPosSet(); + void add(GFileOffset pos); + GBool check(GFileOffset pos); + +private: + + int find(GFileOffset pos); + + GFileOffset *tab; + int size; + int len; +}; + +XRefPosSet::XRefPosSet() { + size = 16; + len = 0; + tab = (GFileOffset *)gmallocn(size, sizeof(GFileOffset)); +} + +XRefPosSet::~XRefPosSet() { + gfree(tab); +} + +void XRefPosSet::add(GFileOffset pos) { + int i; + + i = find(pos); + if (i < len && tab[i] == pos) { + return; + } + if (len == size) { + if (size > INT_MAX / 2) { + gMemError("Integer overflow in XRefPosSet::add()"); + } + size *= 2; + tab = (GFileOffset *)greallocn(tab, size, sizeof(GFileOffset)); + } + if (i < len) { + memmove(&tab[i + 1], &tab[i], (len - i) * sizeof(GFileOffset)); + } + tab[i] = pos; + ++len; +} + +GBool XRefPosSet::check(GFileOffset pos) { + int i; + + i = find(pos); + return i < len && tab[i] == pos; +} + +int XRefPosSet::find(GFileOffset pos) { + int a, b, m; + + a = - 1; + b = len; + // invariant: tab[a] < pos < tab[b] + while (b - a > 1) { + m = (a + b) / 2; + if (tab[m] < pos) { + a = m; + } else if (tab[m] > pos) { + b = m; + } else { + return m; + } + } + return b; +} + +//------------------------------------------------------------------------ // ObjectStream //------------------------------------------------------------------------ @@ -134,7 +213,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { obj2.free(); delete parser; gfree(offsets); - goto err1; + goto err2; } objNums[i] = obj1.getInt(); offsets[i] = obj2.getInt(); @@ -144,7 +223,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { (i > 0 && offsets[i] < offsets[i-1])) { delete parser; gfree(offsets); - goto err1; + goto err2; } } while (str->getChar() != EOF) ; @@ -153,8 +232,8 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { // skip to the first object - this shouldn't be necessary because // the First key is supposed to be equal to offsets[0], but just in // case... - for (i = first; i < offsets[0]; ++i) { - objStr.getStream()->getChar(); + if (i < offsets[0]) { + objStr.getStream()->discardChars(offsets[0] - i); } // parse the objects @@ -175,6 +254,8 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { gfree(offsets); ok = gTrue; + err2: + objStr.streamClose(); err1: objStr.free(); } @@ -203,8 +284,10 @@ Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) { //------------------------------------------------------------------------ XRef::XRef(BaseStream *strA, GBool repair) { - Guint pos; + GFileOffset pos; Object obj; + XRefPosSet *posSet; + int i; ok = gTrue; errCode = errNone; @@ -213,12 +296,18 @@ XRef::XRef(BaseStream *strA, GBool repair) { entries = NULL; streamEnds = NULL; streamEndsLen = 0; - objStr = NULL; + for (i = 0; i < objStrCacheSize; ++i) { + objStrs[i] = NULL; + } encrypted = gFalse; permFlags = defPermFlags; ownerPasswordOk = gFalse; + for (i = 0; i < xrefCacheSize; ++i) { + cache[i].num = -1; + } + str = strA; start = str->getStart(); @@ -241,7 +330,9 @@ XRef::XRef(BaseStream *strA, GBool repair) { } // read the xref table - while (readXRef(&pos)) ; + posSet = new XRefPosSet(); + while (readXRef(&pos, posSet)) ; + delete posSet; if (!ok) { errCode = errDamaged; return; @@ -268,30 +359,34 @@ XRef::XRef(BaseStream *strA, GBool repair) { } XRef::~XRef() { + int i; + + for (i = 0; i < xrefCacheSize; ++i) { + if (cache[i].num >= 0) { + cache[i].obj.free(); + } + } gfree(entries); trailerDict.free(); if (streamEnds) { gfree(streamEnds); } - if (objStr) { - delete objStr; + for (i = 0; i < objStrCacheSize; ++i) { + if (objStrs[i]) { + delete objStrs[i]; + } } } // Read the 'startxref' position. -Guint XRef::getStartXref() { +GFileOffset XRef::getStartXref() { char buf[xrefSearchSize+1]; char *p; - int c, n, i; + int n, i; // read last xrefSearchSize bytes str->setPos(xrefSearchSize, -1); - for (n = 0; n < xrefSearchSize; ++n) { - if ((c = str->getChar()) == EOF) { - break; - } - buf[n] = c; - } + n = str->getBlock(buf, xrefSearchSize); buf[n] = '\0'; // find startxref @@ -304,86 +399,123 @@ Guint XRef::getStartXref() { return 0; } for (p = &buf[i+9]; isspace(*p & 0xff); ++p) ; - lastXRefPos = strToUnsigned(p); + lastXRefPos = strToFileOffset(p); return lastXRefPos; } // Read one xref table section. Also reads the associated trailer // dictionary, and returns the prev pointer (if any). -GBool XRef::readXRef(Guint *pos) { +GBool XRef::readXRef(GFileOffset *pos, XRefPosSet *posSet) { Parser *parser; Object obj; GBool more; + char buf[100]; + int n, i; - // start up a parser, parse one token - obj.initNull(); - parser = new Parser(NULL, - new Lexer(NULL, - str->makeSubStream(start + *pos, gFalse, 0, &obj)), - gTrue); - parser->getObj(&obj, gTrue); + // the xref data should either be "xref ..." (for an xref table) or + // "nn gg obj << ... >> stream ..." (for an xref stream); possibly + // preceded by whitespace + str->setPos(start + *pos); + n = str->getBlock(buf, 100); + for (i = 0; i < n && Lexer::isSpace(buf[i]); ++i) ; // parse an old-style xref table - if (obj.isCmd("xref")) { - obj.free(); - more = readXRefTable(parser, pos); + if (i + 4 < n && + buf[i] == 'x' && buf[i+1] == 'r' && buf[i+2] == 'e' && buf[i+3] == 'f' && + Lexer::isSpace(buf[i+4])) { + more = readXRefTable(pos, i + 5, posSet); // parse an xref stream - } else if (obj.isInt()) { + } else if (i < n && buf[i] >= '0' && buf[i] <= '9') { + obj.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(start + *pos, gFalse, 0, &obj)), + gTrue); + if (!parser->getObj(&obj, gTrue)->isInt()) { + goto err2; + } obj.free(); if (!parser->getObj(&obj, gTrue)->isInt()) { - goto err1; + goto err2; } obj.free(); if (!parser->getObj(&obj, gTrue)->isCmd("obj")) { - goto err1; + goto err2; } obj.free(); if (!parser->getObj(&obj)->isStream()) { - goto err1; + goto err2; } more = readXRefStream(obj.getStream(), pos); obj.free(); + delete parser; } else { goto err1; } - delete parser; return more; - err1: + err2: obj.free(); delete parser; + err1: ok = gFalse; return gFalse; } -GBool XRef::readXRefTable(Parser *parser, Guint *pos) { +GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { XRefEntry entry; - GBool more; + Parser *parser; Object obj, obj2; - Guint pos2; - int first, n, newSize, i; + char buf[6]; + GFileOffset off, pos2; + GBool more; + int first, n, newSize, gen, i, c; + + if (posSet->check(*pos)) { + error(errSyntaxWarning, -1, "Infinite loop in xref table"); + return gFalse; + } + posSet->add(*pos); + + str->setPos(start + *pos + offset); while (1) { - parser->getObj(&obj, gTrue); - if (obj.isCmd("trailer")) { - obj.free(); + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + if (c == 't') { + if (str->getBlock(buf, 6) != 6 || memcmp(buf, "railer", 6)) { + goto err1; + } break; } - if (!obj.isInt()) { + if (c < '0' || c > '9') { goto err1; } - first = obj.getInt(); - obj.free(); - if (!parser->getObj(&obj, gTrue)->isInt()) { + first = 0; + do { + first = (first * 10) + (c - '0'); + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { goto err1; } - n = obj.getInt(); - obj.free(); - if (first < 0 || n < 0 || first + n < 0) { + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + n = 0; + do { + n = (n * 10) + (c - '0'); + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { + goto err1; + } + if (first < 0 || n < 0 || first > INT_MAX - n) { goto err1; } if (first + n > size) { @@ -395,32 +527,51 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) { } entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; + entries[i].offset = (GFileOffset)-1; entries[i].type = xrefEntryFree; } size = newSize; } for (i = first; i < first + n; ++i) { - if (!parser->getObj(&obj, gTrue)->isInt()) { + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + off = 0; + do { + off = (off * 10) + (c - '0'); + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { goto err1; } - entry.offset = (Guint)obj.getInt(); - obj.free(); - if (!parser->getObj(&obj, gTrue)->isInt()) { + entry.offset = off; + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + gen = 0; + do { + gen = (gen * 10) + (c - '0'); + c = str->getChar(); + } while (c >= '0' && c <= '9'); + if (!Lexer::isSpace(c)) { goto err1; } - entry.gen = obj.getInt(); - obj.free(); - parser->getObj(&obj, gTrue); - if (obj.isCmd("n")) { + entry.gen = gen; + do { + c = str->getChar(); + } while (Lexer::isSpace(c)); + if (c == 'n') { entry.type = xrefEntryUncompressed; - } else if (obj.isCmd("f")) { + } else if (c == 'f') { entry.type = xrefEntryFree; } else { goto err1; } - obj.free(); - if (entries[i].offset == 0xffffffff) { + c = str->getChar(); + if (!Lexer::isSpace(c)) { + goto err1; + } + if (entries[i].offset == (GFileOffset)-1) { entries[i] = entry; // PDF files of patents from the IBM Intellectual Property // Network have a bug: the xref table claims to start at 1 @@ -430,7 +581,7 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) { entries[1].type == xrefEntryFree) { i = first = 0; entries[0] = entries[1]; - entries[1].offset = 0xffffffff; + entries[1].offset = (GFileOffset)-1; } if (i > last) { last = i; @@ -440,32 +591,29 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) { } // read the trailer dictionary - if (!parser->getObj(&obj)->isDict()) { + obj.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(str->getPos(), gFalse, 0, &obj)), + gTrue); + parser->getObj(&obj); + delete parser; + if (!obj.isDict()) { + obj.free(); goto err1; } // get the 'Prev' pointer + //~ this can be a 64-bit int (?) obj.getDict()->lookupNF("Prev", &obj2); if (obj2.isInt()) { - pos2 = (Guint)obj2.getInt(); - if (pos2 != *pos) { - *pos = pos2; - more = gTrue; - } else { - error(errSyntaxWarning, -1, "Infinite loop in xref table"); - more = gFalse; - } + *pos = (GFileOffset)(Guint)obj2.getInt(); + more = gTrue; } else if (obj2.isRef()) { // certain buggy PDF generators generate "/Prev NNN 0 R" instead // of "/Prev NNN" - pos2 = (Guint)obj2.getRefNum(); - if (pos2 != *pos) { - *pos = pos2; - more = gTrue; - } else { - error(errSyntaxWarning, -1, "Infinite loop in xref table"); - more = gFalse; - } + *pos = (GFileOffset)(Guint)obj2.getRefNum(); + more = gTrue; } else { more = gFalse; } @@ -477,9 +625,10 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) { } // check for an 'XRefStm' key + //~ this can be a 64-bit int (?) if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) { - pos2 = (Guint)obj2.getInt(); - readXRef(&pos2); + pos2 = (GFileOffset)(Guint)obj2.getInt(); + readXRef(&pos2, posSet); if (!ok) { obj2.free(); goto err1; @@ -491,12 +640,11 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) { return more; err1: - obj.free(); ok = gFalse; return gFalse; } -GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { +GBool XRef::readXRefStream(Stream *xrefStr, GFileOffset *pos) { Dict *dict; int w[3]; GBool more; @@ -516,7 +664,7 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { if (newSize > size) { entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; + entries[i].offset = (GFileOffset)-1; entries[i].type = xrefEntryFree; } size = newSize; @@ -533,11 +681,13 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { } w[i] = obj2.getInt(); obj2.free(); - if (w[i] < 0 || w[i] > 4) { - goto err1; - } } obj.free(); + if (w[0] < 0 || w[0] > 4 || + w[1] < 0 || w[1] > (int)sizeof(GFileOffset) || + w[2] < 0 || w[2] > 4) { + goto err0; + } xrefStr->reset(); dict->lookupNF("Index", &idx); @@ -569,9 +719,10 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { } idx.free(); + //~ this can be a 64-bit int (?) dict->lookupNF("Prev", &obj); if (obj.isInt()) { - *pos = (Guint)obj.getInt(); + *pos = (GFileOffset)(Guint)obj.getInt(); more = gTrue; } else { more = gFalse; @@ -591,7 +742,7 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { } GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { - Guint offset; + GFileOffset offset; int type, gen, c, newSize, i, j; if (first + n < 0) { @@ -606,7 +757,7 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { } entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; + entries[i].offset = (GFileOffset)-1; entries[i].type = xrefEntryFree; } size = newSize; @@ -634,7 +785,7 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { } gen = (gen << 8) + c; } - if (entries[i].offset == 0xffffffff) { + if (entries[i].offset == (GFileOffset)-1) { switch (type) { case 0: entries[i].offset = offset; @@ -668,7 +819,7 @@ GBool XRef::constructXRef() { Parser *parser; Object newTrailerDict, obj; char buf[256]; - Guint pos; + GFileOffset pos; int num, gen; int newSize; int streamEndsSize; @@ -748,7 +899,7 @@ GBool XRef::constructXRef() { entries = (XRefEntry *) greallocn(entries, newSize, sizeof(XRefEntry)); for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; + entries[i].offset = (GFileOffset)-1; entries[i].type = xrefEntryFree; } size = newSize; @@ -771,15 +922,16 @@ GBool XRef::constructXRef() { } else if (!strncmp(p, "endstream", 9)) { if (streamEndsLen == streamEndsSize) { streamEndsSize += 64; - streamEnds = (Guint *)greallocn(streamEnds, - streamEndsSize, sizeof(Guint)); + streamEnds = (GFileOffset *)greallocn(streamEnds, streamEndsSize, + sizeof(GFileOffset)); } streamEnds[streamEndsLen++] = pos; } } - if (gotRoot) + if (gotRoot) { return gTrue; + } error(errSyntaxError, -1, "Couldn't find trailer dictionary"); return gFalse; @@ -824,13 +976,31 @@ GBool XRef::okToAddNotes(GBool ignoreOwnerPW) { Object *XRef::fetch(int num, int gen, Object *obj, int recursion) { XRefEntry *e; Parser *parser; + ObjectStream *objStr; Object obj1, obj2, obj3; + XRefCacheEntry tmp; + int i, j; // check for bogus ref - this can happen in corrupted PDF files if (num < 0 || num >= size) { goto err; } + // check the cache + if (cache[0].num == num && cache[0].gen == gen) { + return cache[0].obj.copy(obj); + } + for (i = 1; i < xrefCacheSize; ++i) { + if (cache[i].num == num && cache[i].gen == gen) { + tmp = cache[i]; + for (j = i; j > 0; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = tmp; + return cache[0].obj.copy(obj); + } + } + e = &entries[num]; switch (e->type) { @@ -869,21 +1039,13 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) { goto err; } #endif - if (e->offset >= (Guint)size || + if (e->offset >= (GFileOffset)size || entries[e->offset].type != xrefEntryUncompressed) { error(errSyntaxError, -1, "Invalid object stream"); goto err; } - if (!objStr || objStr->getObjStrNum() != (int)e->offset) { - if (objStr) { - delete objStr; - } - objStr = new ObjectStream(this, e->offset); - if (!objStr->isOk()) { - delete objStr; - objStr = NULL; - goto err; - } + if (!(objStr = getObjectStream((int)e->offset))) { + goto err; } objStr->getObject(e->gen, num, obj); break; @@ -892,12 +1054,61 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) { goto err; } + // put the new object in the cache, throwing away the oldest object + // currently in the cache + if (cache[xrefCacheSize - 1].num >= 0) { + cache[xrefCacheSize - 1].obj.free(); + } + for (i = xrefCacheSize - 1; i > 0; --i) { + cache[i] = cache[i - 1]; + } + cache[0].num = num; + cache[0].gen = gen; + obj->copy(&cache[0].obj); + return obj; err: return obj->initNull(); } +ObjectStream *XRef::getObjectStream(int objStrNum) { + ObjectStream *objStr; + int i, j; + + // check the MRU entry in the cache + if (objStrs[0] && objStrs[0]->getObjStrNum() == objStrNum) { + return objStrs[0]; + } + + // check the rest of the cache + for (i = 1; i < objStrCacheSize; ++i) { + if (objStrs[i] && objStrs[i]->getObjStrNum() == objStrNum) { + objStr = objStrs[i]; + for (j = i; j > 0; --j) { + objStrs[j] = objStrs[j - 1]; + } + objStrs[0] = objStr; + return objStr; + } + } + + // load a new ObjectStream + objStr = new ObjectStream(this, objStrNum); + if (!objStr->isOk()) { + delete objStr; + return NULL; + } + if (objStrs[objStrCacheSize - 1]) { + delete objStrs[objStrCacheSize - 1]; + } + for (j = objStrCacheSize - 1; j > 0; --j) { + objStrs[j] = objStrs[j - 1]; + } + objStrs[0] = objStr; + return objStr; +} + Object *XRef::getDocInfo(Object *obj) { return trailerDict.dictLookup("Info", obj); } @@ -907,7 +1118,7 @@ Object *XRef::getDocInfoNF(Object *obj) { return trailerDict.dictLookupNF("Info", obj); } -GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { +GBool XRef::getStreamEnd(GFileOffset streamStart, GFileOffset *streamEnd) { int a, b, m; if (streamEndsLen == 0 || @@ -930,14 +1141,14 @@ GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { return gTrue; } -Guint XRef::strToUnsigned(char *s) { - Guint x, d; +GFileOffset XRef::strToFileOffset(char *s) { + GFileOffset x, d; char *p; x = 0; for (p = s; *p && isdigit(*p & 0xff); ++p) { d = *p - '0'; - if (x > (UINT_MAX - d) / 10) { + if (x > (GFILEOFFSET_MAX - d) / 10) { break; } x = 10 * x + d; diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XRef.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XRef.h index f2c4ac300a6..0b74dcb8806 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XRef.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XRef.h @@ -16,12 +16,14 @@ #endif #include "gtypes.h" +#include "gfile.h" #include "Object.h" class Dict; class Stream; class Parser; class ObjectStream; +class XRefPosSet; //------------------------------------------------------------------------ // XRef @@ -34,11 +36,21 @@ enum XRefEntryType { }; struct XRefEntry { - Guint offset; + GFileOffset offset; int gen; XRefEntryType type; }; +struct XRefCacheEntry { + int num; + int gen; + Object obj; +}; + +#define xrefCacheSize 16 + +#define objStrCacheSize 4 + class XRef { public: @@ -83,7 +95,7 @@ public: int getNumObjects() { return last + 1; } // Return the offset of the last xref table. - Guint getLastXRefPos() { return lastXRefPos; } + GFileOffset getLastXRefPos() { return lastXRefPos; } // Return the catalog object reference. int getRootNum() { return rootNum; } @@ -91,7 +103,7 @@ public: // Get end position for a stream in a damaged file. // Returns false if unknown or file is not damaged. - GBool getStreamEnd(Guint streamStart, Guint *streamEnd); + GBool getStreamEnd(GFileOffset streamStart, GFileOffset *streamEnd); // Direct access. int getSize() { return size; } @@ -101,7 +113,7 @@ public: private: BaseStream *str; // input stream - Guint start; // offset in file (to allow for garbage + GFileOffset start; // offset in file (to allow for garbage // at beginning of file) XRefEntry *entries; // xref entries int size; // size of <entries> array @@ -110,11 +122,12 @@ private: GBool ok; // true if xref table is valid int errCode; // error code (if <ok> is false) Object trailerDict; // trailer dictionary - Guint lastXRefPos; // offset of last xref table - Guint *streamEnds; // 'endstream' positions - only used in + GFileOffset lastXRefPos; // offset of last xref table + GFileOffset *streamEnds; // 'endstream' positions - only used in // damaged files int streamEndsLen; // number of valid entries in streamEnds - ObjectStream *objStr; // cached object stream + ObjectStream * // cached object streams + objStrs[objStrCacheSize]; GBool encrypted; // true if file is encrypted int permFlags; // permission bits GBool ownerPasswordOk; // true if owner password is correct @@ -122,14 +135,17 @@ private: int keyLength; // length of key, in bytes int encVersion; // encryption version CryptAlgorithm encAlgorithm; // encryption algorithm + XRefCacheEntry // cache of recently accessed objects + cache[xrefCacheSize]; - Guint getStartXref(); - GBool readXRef(Guint *pos); - GBool readXRefTable(Parser *parser, Guint *pos); + GFileOffset getStartXref(); + GBool readXRef(GFileOffset *pos, XRefPosSet *posSet); + GBool readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet); GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n); - GBool readXRefStream(Stream *xrefStr, Guint *pos); + GBool readXRefStream(Stream *xrefStr, GFileOffset *pos); GBool constructXRef(); - Guint strToUnsigned(char *s); + ObjectStream *getObjectStream(int objStrNum); + GFileOffset strToFileOffset(char *s); }; #endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XpdfPluginAPI.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XpdfPluginAPI.cc index 4c51537299f..d513bec9154 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XpdfPluginAPI.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XpdfPluginAPI.cc @@ -14,7 +14,7 @@ #include "GlobalParams.h" #include "Object.h" #include "PDFDoc.h" -#ifdef WIN32 +#ifdef _WIN32 #include "WinPDFCore.h" #else #include "XPDFCore.h" diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XpdfPluginAPI.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XpdfPluginAPI.h index 22540f728bd..22540f728bd 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/XpdfPluginAPI.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/XpdfPluginAPI.h diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.cc new file mode 100644 index 00000000000..95242674eb3 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.cc @@ -0,0 +1,839 @@ +//======================================================================== +// +// Zoox.cc +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "Zoox.h" + +//~ all of this code assumes the encoding is UTF-8 or ASCII or something +//~ similar (ISO-8859-*) + +//------------------------------------------------------------------------ + +static char nameStartChar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // 30 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 70 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f0 +}; + +static char nameChar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, // 20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 30 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 70 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f0 +}; + +//------------------------------------------------------------------------ + +ZxNode::ZxNode() { + next = NULL; + parent = NULL; + firstChild = lastChild = NULL; +} + +ZxNode::~ZxNode() { + ZxNode *child; + + while (firstChild) { + child = firstChild; + firstChild = firstChild->next; + delete child; + } +} + +ZxElement *ZxNode::findFirstElement(const char *type) { + ZxNode *child; + ZxElement *result; + + if (isElement(type)) { + return (ZxElement *)this; + } + for (child = firstChild; child; child = child->next) { + if ((result = child->findFirstElement(type))) { + return result; + } + } + return NULL; +} + +ZxElement *ZxNode::findFirstChildElement(const char *type) { + ZxNode *child; + + for (child = firstChild; child; child = child->next) { + if (child->isElement(type)) { + return (ZxElement *)child; + } + } + return NULL; +} + +GList *ZxNode::findAllElements(const char *type) { + GList *results; + + results = new GList(); + findAllElements(type, results); + return results; +} + +void ZxNode::findAllElements(const char *type, GList *results) { + ZxNode *child; + + if (isElement(type)) { + results->append(this); + } + for (child = firstChild; child; child = child->next) { + child->findAllElements(type, results); + } +} + +GList *ZxNode::findAllChildElements(const char *type) { + GList *results; + ZxNode *child; + + results = new GList(); + for (child = firstChild; child; child = child->next) { + if (child->isElement(type)) { + results->append(child); + } + } + return results; +} + +void ZxNode::addChild(ZxNode *child) { + if (lastChild) { + lastChild->next = child; + lastChild = child; + } else { + firstChild = lastChild = child; + } + child->parent = this; + child->next = NULL; +} + +//------------------------------------------------------------------------ + +ZxDoc::ZxDoc() { + xmlDecl = NULL; + docTypeDecl = NULL; + root = NULL; +} + +ZxDoc *ZxDoc::loadMem(const char *data, Guint dataLen) { + ZxDoc *doc; + + doc = new ZxDoc(); + if (!doc->parse(data, dataLen)) { + delete doc; + return NULL; + } + return doc; +} + +ZxDoc *ZxDoc::loadFile(const char *fileName) { + ZxDoc *doc; + FILE *f; + char *data; + Guint dataLen; + + if (!(f = fopen(fileName, "rb"))) { + return NULL; + } + fseek(f, 0, SEEK_END); + dataLen = (Guint)ftell(f); + if (!dataLen) { + fclose(f); + return NULL; + } + fseek(f, 0, SEEK_SET); + data = (char *)gmalloc(dataLen); + if (fread(data, 1, dataLen, f) != dataLen) { + fclose(f); + gfree(data); + return NULL; + } + fclose(f); + doc = loadMem(data, dataLen); + gfree(data); + return doc; +} + +ZxDoc::~ZxDoc() { +} + +void ZxDoc::addChild(ZxNode *node) { + if (node->isXMLDecl() && !xmlDecl) { + xmlDecl = (ZxXMLDecl *)node; + } else if (node->isDocTypeDecl() && !docTypeDecl) { + docTypeDecl = (ZxDocTypeDecl *)node; + } else if (node->isElement() && !root) { + root = (ZxElement *)node; + } + ZxNode::addChild(node); +} + +bool ZxDoc::parse(const char *data, Guint dataLen) { + parsePtr = data; + parseEnd = data + dataLen; + + parseSpace(); + parseXMLDecl(this); + parseMisc(this); + parseDocTypeDecl(this); + parseMisc(this); + if (match("<")) { + parseElement(this); + } + parseMisc(this); + return root != NULL; +} + +void ZxDoc::parseXMLDecl(ZxNode *par) { + GString *version, *encoding, *s; + bool standalone; + + if (!match("<?xml")) { + return; + } + parsePtr += 5; + parseSpace(); + + // version + version = NULL; + if (match("version")) { + parsePtr += 7; + parseSpace(); + if (match("=")) { + ++parsePtr; + parseSpace(); + version = parseQuotedString(); + } + } + if (!version) { + version = new GString("1.0"); + } + parseSpace(); + + // encoding + encoding = NULL; + if (match("encoding")) { + parsePtr += 8; + parseSpace(); + if (match("=")) { + ++parsePtr; + parseSpace(); + encoding = parseQuotedString(); + } + } + parseSpace(); + + // standalone + standalone = false; + if (match("standalone")) { + parsePtr += 10; + parseSpace(); + if (match("=")) { + ++parsePtr; + parseSpace(); + s = parseQuotedString(); + standalone = !s->cmp("yes"); + delete s; + } + } + parseSpace(); + + if (match("?>")) { + parsePtr += 2; + } + + par->addChild(new ZxXMLDecl(version, encoding, standalone)); +} + +//~ this just skips everything after the name +void ZxDoc::parseDocTypeDecl(ZxNode *par) { + GString *name; + int state; + char c, quote; + + if (!match("<!DOCTYPE")) { + return; + } + parsePtr += 9; + parseSpace(); + + name = parseName(); + parseSpace(); + + state = 0; + quote = '\0'; + while (parsePtr < parseEnd && state < 4) { + c = *parsePtr++; + switch (state) { + case 0: // not in square brackets; not in quotes + if (c == '>') { + state = 4; + } else if (c == '"' || c == '\'') { + state = 1; + } else if (c == '[') { + state = 2; + } + break; + case 1: // not in square brackets; in quotes + if (c == quote) { + state = 0; + } + break; + case 2: // in square brackets; not in quotes + if (c == ']') { + state = 0; + } else if (c == '"' || c == '\'') { + state = 3; + } + break; + case 3: // in square brackets; in quotes + if (c == quote) { + state = 2; + } + break; + } + } + + par->addChild(new ZxDocTypeDecl(name)); +} + +// assumes match("<") +void ZxDoc::parseElement(ZxNode *par) { + GString *type; + ZxElement *elem; + ZxAttr *attr; + + ++parsePtr; + type = parseName(); + elem = new ZxElement(type); + parseSpace(); + while ((attr = parseAttr())) { + elem->addAttr(attr); + parseSpace(); + } + if (match("/>")) { + parsePtr += 2; + } else if (match(">")) { + ++parsePtr; + parseContent(elem); + } + par->addChild(elem); +} + +ZxAttr *ZxDoc::parseAttr() { + GString *name, *value; + const char *start; + char quote, c; + int x, n; + + name = parseName(); + parseSpace(); + if (!match("=")) { + delete name; + return NULL; + } + ++parsePtr; + parseSpace(); + if (!(parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\''))) { + delete name; + return NULL; + } + quote = *parsePtr++; + value = new GString(); + while (parsePtr < parseEnd && *parsePtr != quote) { + if (*parsePtr == '&') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == '#') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == 'x') { + ++parsePtr; + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = (x << 4) + (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) + (10 + c - 'a'); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) + (10 + c - 'A'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(value, x); + } else { + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = x * 10 + (c - '0'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(value, x); + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != ';' && + *parsePtr != quote && *parsePtr != '&'; + ++parsePtr) ; + n = (int)(parsePtr - start); + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + if (n == 2 && !strncmp(start, "lt", 2)) { + value->append('<'); + } else if (n == 2 && !strncmp(start, "gt", 2)) { + value->append('>'); + } else if (n == 3 && !strncmp(start, "amp", 3)) { + value->append('&'); + } else if (n == 4 && !strncmp(start, "apos", 4)) { + value->append('\''); + } else if (n == 4 && !strncmp(start, "quot", 4)) { + value->append('"'); + } else { + value->append(start - 1, (int)(parsePtr - start) + 1); + } + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != quote && *parsePtr != '&'; + ++parsePtr) ; + value->append(start, (int)(parsePtr - start)); + } + } + if (parsePtr < parseEnd && *parsePtr == quote) { + ++parsePtr; + } + return new ZxAttr(name, value); +} + +// this consumes the end tag +void ZxDoc::parseContent(ZxElement *par) { + GString *endType; + + endType = (new GString("</"))->append(par->getType()); + + while (parsePtr < parseEnd) { + if (match(endType->getCString())) { + parsePtr += endType->getLength(); + parseSpace(); + if (match(">")) { + ++parsePtr; + } + break; + } else if (match("<?")) { + parsePI(par); + } else if (match("<![CDATA[")) { + parseCDSect(par); + } else if (match("<!--")) { + parseComment(par); + } else if (match("<")) { + parseElement(par); + } else { + parseCharData(par); + } + } + + delete endType; +} + +void ZxDoc::parseCharData(ZxElement *par) { + GString *data; + const char *start; + char c; + int x, n; + + data = new GString(); + while (parsePtr < parseEnd && *parsePtr != '<') { + if (*parsePtr == '&') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == '#') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == 'x') { + ++parsePtr; + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = (x << 4) + (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) + (10 + c - 'a'); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) + (10 + c - 'A'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(data, x); + } else { + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = x * 10 + (c - '0'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(data, x); + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != ';' && + *parsePtr != '<' && *parsePtr != '&'; + ++parsePtr) ; + n = (int)(parsePtr - start); + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + if (n == 2 && !strncmp(start, "lt", 2)) { + data->append('<'); + } else if (n == 2 && !strncmp(start, "gt", 2)) { + data->append('>'); + } else if (n == 3 && !strncmp(start, "amp", 3)) { + data->append('&'); + } else if (n == 4 && !strncmp(start, "apos", 4)) { + data->append('\''); + } else if (n == 4 && !strncmp(start, "quot", 4)) { + data->append('"'); + } else { + data->append(start - 1, (int)(parsePtr - start) + 1); + } + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != '<' && *parsePtr != '&'; + ++parsePtr) ; + data->append(start, (int)(parsePtr - start)); + } + } + par->addChild(new ZxCharData(data, true)); +} + +void ZxDoc::appendUTF8(GString *s, int c) { + if (c <= 0x7f) { + s->append((char)c); + } else if (c <= 0x7ff) { + s->append((char)(0xc0 + (c >> 6))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0xffff) { + s->append((char)(0xe0 + (c >> 12))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x1fffff) { + s->append((char)(0xf0 + (c >> 18))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x3ffffff) { + s->append((char)(0xf8 + (c >> 24))); + s->append((char)(0x80 + ((c >> 18) & 0x3f))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x7fffffff) { + s->append((char)(0xfc + (c >> 30))); + s->append((char)(0x80 + ((c >> 24) & 0x3f))); + s->append((char)(0x80 + ((c >> 18) & 0x3f))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } +} + +// assumes match("<![CDATA[") +void ZxDoc::parseCDSect(ZxNode *par) { + const char *start; + + parsePtr += 9; + start = parsePtr; + while (parsePtr < parseEnd - 3) { + if (!strncmp(parsePtr, "]]>", 3)) { + par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)), + false)); + parsePtr += 3; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; + par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)), + false)); +} + +void ZxDoc::parseMisc(ZxNode *par) { + while (1) { + if (match("<!--")) { + parseComment(par); + } else if (match("<?")) { + parsePI(par); + } else if (parsePtr < parseEnd && (*parsePtr == '\x20' || + *parsePtr == '\x09' || + *parsePtr == '\x0d' || + *parsePtr == '\x0a')) { + ++parsePtr; + } else { + break; + } + } +} + +// assumes match("<!--") +void ZxDoc::parseComment(ZxNode *par) { + const char *start; + + parsePtr += 4; + start = parsePtr; + while (parsePtr <= parseEnd - 3) { + if (!strncmp(parsePtr, "-->", 3)) { + par->addChild(new ZxComment(new GString(start, (int)(parsePtr - start)))); + parsePtr += 3; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; +} + +// assumes match("<?") +void ZxDoc::parsePI(ZxNode *par) { + GString *target; + const char *start; + + parsePtr += 2; + target = parseName(); + parseSpace(); + start = parsePtr; + while (parsePtr <= parseEnd - 2) { + if (!strncmp(parsePtr, "?>", 2)) { + par->addChild(new ZxPI(target, new GString(start, + (int)(parsePtr - start)))); + parsePtr += 2; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; + par->addChild(new ZxPI(target, new GString(start, (int)(parsePtr - start)))); +} + +//~ this accepts all chars >= 0x80 +//~ this doesn't check for properly-formed UTF-8 +GString *ZxDoc::parseName() { + GString *name; + + name = new GString(); + if (parsePtr < parseEnd && nameStartChar[*parsePtr & 0xff]) { + name->append(*parsePtr++); + while (parsePtr < parseEnd && nameChar[*parsePtr & 0xff]) { + name->append(*parsePtr++); + } + } + return name; +} + +GString *ZxDoc::parseQuotedString() { + GString *s; + const char *start; + char quote; + + if (parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\'')) { + quote = *parsePtr++; + start = parsePtr; + while (parsePtr < parseEnd && *parsePtr != quote) { + ++parsePtr; + } + s = new GString(start, (int)(parsePtr - start)); + if (parsePtr < parseEnd && *parsePtr == quote) { + ++parsePtr; + } + } else { + s = new GString(); + } + return s; +} + +void ZxDoc::parseSpace() { + while (parsePtr < parseEnd && (*parsePtr == '\x20' || + *parsePtr == '\x09' || + *parsePtr == '\x0d' || + *parsePtr == '\x0a')) { + ++parsePtr; + } +} + +bool ZxDoc::match(const char *s) { + int n; + + n = (int)strlen(s); + return parseEnd - parsePtr >= n && !strncmp(parsePtr, s, n); +} + +//------------------------------------------------------------------------ + +ZxXMLDecl::ZxXMLDecl(GString *versionA, GString *encodingA, bool standaloneA) { + version = versionA; + encoding = encodingA; + standalone = standaloneA; +} + +ZxXMLDecl::~ZxXMLDecl() { + delete version; + if (encoding) { + delete encoding; + } +} + +//------------------------------------------------------------------------ + +ZxDocTypeDecl::ZxDocTypeDecl(GString *nameA) { + name = nameA; +} + +ZxDocTypeDecl::~ZxDocTypeDecl() { + delete name; +} + +//------------------------------------------------------------------------ + +ZxComment::ZxComment(GString *textA) { + text = textA; +} + +ZxComment::~ZxComment() { + delete text; +} + +//------------------------------------------------------------------------ + +ZxPI::ZxPI(GString *targetA, GString *textA) { + target = targetA; + text = textA; +} + +ZxPI::~ZxPI() { + delete target; + delete text; +} + +//------------------------------------------------------------------------ + +ZxElement::ZxElement(GString *typeA) { + type = typeA; + attrs = new GHash(); + firstAttr = lastAttr = NULL; +} + +ZxElement::~ZxElement() { + delete type; + deleteGHash(attrs, ZxAttr); +} + +bool ZxElement::isElement(const char *typeA) { + return !type->cmp(typeA); +} + +ZxAttr *ZxElement::findAttr(const char *attrName) { + return (ZxAttr *)attrs->lookup(attrName); +} + +void ZxElement::addAttr(ZxAttr *attr) { + attrs->add(attr->getName(), attr); + if (lastAttr) { + lastAttr->next = attr; + lastAttr= attr; + } else { + firstAttr = lastAttr = attr; + } + attr->parent = this; + attr->next = NULL; +} + +//------------------------------------------------------------------------ + +ZxAttr::ZxAttr(GString *nameA, GString *valueA) { + name = nameA; + value = valueA; + parent = NULL; + next = NULL; +} + +ZxAttr::~ZxAttr() { + delete name; + delete value; +} + +//------------------------------------------------------------------------ + +ZxCharData::ZxCharData(GString *dataA, bool parsedA) { + data = dataA; + parsed = parsedA; +} + +ZxCharData::~ZxCharData() { + delete data; +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.h new file mode 100644 index 00000000000..091f72e10a9 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/Zoox.h @@ -0,0 +1,241 @@ +//======================================================================== +// +// Zoox.h +// +//======================================================================== + +#ifndef ZOOX_H +#define ZOOX_H + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class GString; +class GList; +class GHash; + +class ZxAttr; +class ZxDocTypeDecl; +class ZxElement; +class ZxXMLDecl; + +//------------------------------------------------------------------------ + +class ZxNode { +public: + + ZxNode(); + virtual ~ZxNode(); + + virtual bool isDoc() { return false; } + virtual bool isXMLDecl() { return false; } + virtual bool isDocTypeDecl() { return false; } + virtual bool isComment() { return false; } + virtual bool isPI() { return false; } + virtual bool isElement() { return false; } + virtual bool isElement(const char *type) { return false; } + virtual bool isCharData() { return false; } + virtual ZxNode *getFirstChild() { return firstChild; } + virtual ZxNode *getNextChild() { return next; } + ZxElement *findFirstElement(const char *type); + ZxElement *findFirstChildElement(const char *type); + GList *findAllElements(const char *type); + GList *findAllChildElements(const char *type); + virtual void addChild(ZxNode *child); + +protected: + + void findAllElements(const char *type, GList *results); + + ZxNode *next; + ZxNode *parent; + ZxNode *firstChild, + *lastChild; +}; + +//------------------------------------------------------------------------ + +class ZxDoc: public ZxNode { +public: + + ZxDoc(); + + // Parse from memory. Returns NULL on error. + static ZxDoc *loadMem(const char *data, Guint dataLen); + + // Parse from disk. Returns NULL on error. + static ZxDoc *loadFile(const char *fileName); + + virtual ~ZxDoc(); + + virtual bool isDoc() { return true; } + ZxXMLDecl *getXMLDecl() { return xmlDecl; } + ZxDocTypeDecl *getDocTypeDecl() { return docTypeDecl; } + ZxElement *getRoot() { return root; } + virtual void addChild(ZxNode *node); + +private: + + bool parse(const char *data, Guint dataLen); + void parseXMLDecl(ZxNode *par); + void parseDocTypeDecl(ZxNode *par); + void parseElement(ZxNode *par); + ZxAttr *parseAttr(); + void parseContent(ZxElement *par); + void parseCharData(ZxElement *par); + void appendUTF8(GString *s, int c); + void parseCDSect(ZxNode *par); + void parseMisc(ZxNode *par); + void parseComment(ZxNode *par); + void parsePI(ZxNode *par); + GString *parseName(); + GString *parseQuotedString(); + void parseSpace(); + bool match(const char *s); + + ZxXMLDecl *xmlDecl; // may be NULL + ZxDocTypeDecl *docTypeDecl; // may be NULL + ZxElement *root; // may be NULL + + const char *parsePtr; + const char *parseEnd; +}; + +//------------------------------------------------------------------------ + +class ZxXMLDecl: public ZxNode { +public: + + ZxXMLDecl(GString *versionA, GString *encodingA, bool standaloneA); + virtual ~ZxXMLDecl(); + + virtual bool isXMLDecl() { return true; } + GString *getVersion() { return version; } + GString *getEncoding() { return encoding; } + bool getStandalone() { return standalone; } + +private: + + GString *version; + GString *encoding; // may be NULL + bool standalone; +}; + +//------------------------------------------------------------------------ + +class ZxDocTypeDecl: public ZxNode { +public: + + ZxDocTypeDecl(GString *nameA); + virtual ~ZxDocTypeDecl(); + + virtual bool isDocTypeDecl() { return true; } + GString *getName() { return name; } + +private: + + GString *name; +}; + +//------------------------------------------------------------------------ + +class ZxComment: public ZxNode { +public: + + ZxComment(GString *textA); + virtual ~ZxComment(); + + virtual bool isComment() { return true; } + GString *getText() { return text; } + +private: + + GString *text; +}; + +//------------------------------------------------------------------------ + +class ZxPI: public ZxNode { +public: + + ZxPI(GString *targetA, GString *textA); + virtual ~ZxPI(); + + virtual bool isPI() { return true; } + GString *getTarget() { return target; } + GString *getText() { return text; } + +private: + + GString *target; + GString *text; +}; + +//------------------------------------------------------------------------ + +class ZxElement: public ZxNode { +public: + + ZxElement(GString *typeA); + virtual ~ZxElement(); + + virtual bool isElement() { return true; } + virtual bool isElement(const char *typeA); + GString *getType() { return type; } + ZxAttr *findAttr(const char *attrName); + ZxAttr *getFirstAttr() { return firstAttr; } + void addAttr(ZxAttr *attr); + +private: + + GString *type; + GHash *attrs; // [ZxAttr] + ZxAttr *firstAttr, *lastAttr; +}; + +//------------------------------------------------------------------------ + +class ZxAttr { +public: + + ZxAttr(GString *nameA, GString *valueA); + ~ZxAttr(); + + GString *getName() { return name; } + GString *getValue() { return value; } + ZxAttr *getNextAttr() { return next; } + +private: + + GString *name; + GString *value; + ZxElement *parent; + ZxAttr *next; + + friend class ZxElement; +}; + +//------------------------------------------------------------------------ + +class ZxCharData: public ZxNode { +public: + + ZxCharData(GString *dataA, bool parsedA); + virtual ~ZxCharData(); + + virtual bool isCharData() { return true; } + GString *getData() { return data; } + bool isParsed() { return parsed; } + +private: + + GString *data; // in UTF-8 format + bool parsed; +}; + +#endif diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/about-text.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/about-text.h index 2ea7588a368..2ea7588a368 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/about-text.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/about-text.h diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/about.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/about.xbm index 86f84720c9b..86f84720c9b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/about.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/about.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/backArrow.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/backArrow.xbm index 47f49e19073..47f49e19073 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/backArrow.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/backArrow.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/backArrowDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/backArrowDis.xbm index 752963963a7..752963963a7 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/backArrowDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/backArrowDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/config.h b/Build/source/libs/xpdf/xpdf-3.04/xpdf/config.h index 39a62cfba25..6bf406860bf 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/config.h +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/config.h @@ -2,7 +2,7 @@ // // config.h // -// Copyright 1996-2011 Glyph & Cog, LLC +// Copyright 1996-2014 Glyph & Cog, LLC // //======================================================================== @@ -14,13 +14,13 @@ //------------------------------------------------------------------------ // xpdf version -#define xpdfVersion "3.03" -#define xpdfVersionNum 3.03 +#define xpdfVersion "3.04" +#define xpdfVersionNum 3.04 #define xpdfMajorVersion 3 -#define xpdfMinorVersion 3 +#define xpdfMinorVersion 4 #define xpdfUpdateVersion 0 #define xpdfMajorVersionStr "3" -#define xpdfMinorVersionStr "3" +#define xpdfMinorVersionStr "4" #define xpdfUpdateVersionStr "0" // supported PDF version @@ -28,11 +28,11 @@ #define supportedPDFVersionNum 1.7 // copyright notice -#define xpdfCopyright "Copyright 1996-2011 Glyph & Cog, LLC" +#define xpdfCopyright "Copyright 1996-2014 Glyph & Cog, LLC" // Windows resource file stuff -#define winxpdfVersion "WinXpdf 3.03" -#define xpdfCopyrightAmp "Copyright 1996-2011 Glyph && Cog, LLC" +#define winxpdfVersion "WinXpdf 3.04" +#define xpdfCopyrightAmp "Copyright 1996-2014 Glyph && Cog, LLC" //------------------------------------------------------------------------ // paper size @@ -52,7 +52,7 @@ //------------------------------------------------------------------------ // user config file name, relative to the user's home directory -#if defined(VMS) || defined(WIN32) +#if defined(VMS) || defined(_WIN32) #define xpdfUserConfigFile "xpdfrc" #else #define xpdfUserConfigFile ".xpdfrc" @@ -78,7 +78,7 @@ // popen //------------------------------------------------------------------------ -#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS) +#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(_WIN32) || defined(__DJGPP__) || defined(MACOS) #define POPEN_READ_MODE "rb" #else #define POPEN_READ_MODE "r" diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblLeftArrow.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblLeftArrow.xbm index 616d2bd37fc..616d2bd37fc 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblLeftArrow.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblLeftArrow.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblLeftArrowDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblLeftArrowDis.xbm index 3fb78d80c8d..3fb78d80c8d 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblLeftArrowDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblLeftArrowDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblRightArrow.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblRightArrow.xbm index 0072810ebca..0072810ebca 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblRightArrow.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblRightArrow.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblRightArrowDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblRightArrowDis.xbm index a6c1e3708cd..a6c1e3708cd 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/dblRightArrowDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/dblRightArrowDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/find.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/find.xbm index 206da875fbd..206da875fbd 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/find.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/find.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/findDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/findDis.xbm index cf666f2493c..cf666f2493c 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/findDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/findDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/forwardArrow.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/forwardArrow.xbm index e3875352b8e..e3875352b8e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/forwardArrow.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/forwardArrow.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/forwardArrowDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/forwardArrowDis.xbm index 58d0cc0f00b..58d0cc0f00b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/forwardArrowDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/forwardArrowDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/leftArrow.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/leftArrow.xbm index 367e4e604ce..367e4e604ce 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/leftArrow.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/leftArrow.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/leftArrowDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/leftArrowDis.xbm index 953092a6e24..953092a6e24 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/leftArrowDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/leftArrowDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfdetach.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfdetach.cc index 4be3a48ce93..6d29ff3f774 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfdetach.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfdetach.cc @@ -147,7 +147,7 @@ int main(int argc, char *argv[]) { } else if (saveAll) { for (i = 0; i < nFiles; ++i) { if (savePath[0]) { - n = strlen(savePath); + n = (int)strlen(savePath); if (n > (int)sizeof(path) - 2) { n = sizeof(path) - 2; } diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdffonts.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdffonts.cc index 80403a1e318..e1a0b4303be 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdffonts.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdffonts.cc @@ -22,6 +22,7 @@ #include "Dict.h" #include "GfxFont.h" #include "Annot.h" +#include "Form.h" #include "PDFDoc.h" #include "config.h" @@ -41,11 +42,14 @@ static const char *fontTypeNames[] = { "CID TrueType (OT)" }; +static void scanFonts(Object *obj, PDFDoc *doc); static void scanFonts(Dict *resDict, PDFDoc *doc); static void scanFont(GfxFont *font, PDFDoc *doc); static int firstPage = 1; static int lastPage = 0; +static GBool showFontLoc = gFalse; +static GBool showFontLocPS = gFalse; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; static char cfgFileName[256] = ""; @@ -57,6 +61,10 @@ static ArgDesc argDesc[] = { "first page to examine"}, {"-l", argInt, &lastPage, 0, "last page to examine"}, + {"-loc", argFlag, &showFontLoc, 0, + "print extended info on font location"}, + {"-locPS", argFlag, &showFontLocPS, 0, + "print extended info on font location for PostScript conversion"}, {"-opw", argString, ownerPassword, sizeof(ownerPassword), "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), @@ -80,6 +88,10 @@ static Ref *fonts; static int fontsLen; static int fontsSize; +static Ref *seenObjs; +static int seenObjsLen; +static int seenObjsSize; + int main(int argc, char *argv[]) { PDFDoc *doc; GString *fileName; @@ -88,8 +100,9 @@ int main(int argc, char *argv[]) { Page *page; Dict *resDict; Annots *annots; + Form *form; Object obj1, obj2; - int pg, i; + int pg, i, j; int exitCode; exitCode = 99; @@ -108,6 +121,7 @@ int main(int argc, char *argv[]) { // read config file globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); // open PDF file if (ownerPassword[0] != '\001') { @@ -141,10 +155,17 @@ int main(int argc, char *argv[]) { } // scan the fonts - printf("name type emb sub uni object ID\n"); - printf("------------------------------------ ----------------- --- --- --- ---------\n"); + if (showFontLoc || showFontLocPS) { + printf("name type emb sub uni object ID location\n"); + printf("------------------------------------ ----------------- --- --- --- --------- --------\n"); + } else { + printf("name type emb sub uni object ID\n"); + printf("------------------------------------ ----------------- --- --- --- ---------\n"); + } fonts = NULL; fontsLen = fontsSize = 0; + seenObjs = NULL; + seenObjsLen = seenObjsSize = 0; for (pg = firstPage; pg <= lastPage; ++pg) { page = doc->getCatalog()->getPage(pg); if ((resDict = page->getResourceDict())) { @@ -154,21 +175,35 @@ int main(int argc, char *argv[]) { obj1.free(); for (i = 0; i < annots->getNumAnnots(); ++i) { if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { - obj1.streamGetDict()->lookup("Resources", &obj2); - if (obj2.isDict()) { - scanFonts(obj2.getDict(), doc); - } + obj1.streamGetDict()->lookupNF("Resources", &obj2); + scanFonts(&obj2, doc); obj2.free(); } obj1.free(); } delete annots; } + if ((form = doc->getCatalog()->getForm())) { + for (i = 0; i < form->getNumFields(); ++i) { + form->getField(i)->getResources(&obj1); + if (obj1.isArray()) { + for (j = 0; j < obj1.arrayGetLength(); ++j) { + obj1.arrayGetNF(j, &obj2); + scanFonts(&obj2, doc); + obj2.free(); + } + } else if (obj1.isDict()) { + scanFonts(obj1.getDict(), doc); + } + obj1.free(); + } + } exitCode = 0; // clean up gfree(fonts); + gfree(seenObjs); err1: delete doc; delete globalParams; @@ -181,8 +216,37 @@ int main(int argc, char *argv[]) { return exitCode; } +static void scanFonts(Object *obj, PDFDoc *doc) { + Object obj2; + int i; + + if (obj->isRef()) { + for (i = 0; i < seenObjsLen; ++i) { + if (obj->getRefNum() == seenObjs[i].num && + obj->getRefGen() == seenObjs[i].gen) { + return; + } + } + if (seenObjsLen == seenObjsSize) { + if (seenObjsSize <= INT_MAX - 32) { + seenObjsSize += 32; + } else { + // let greallocn throw an exception + seenObjsSize = -1; + } + seenObjs = (Ref *)greallocn(seenObjs, seenObjsSize, sizeof(Ref)); + } + seenObjs[seenObjsLen++] = obj->getRef(); + } + if (obj->fetch(doc->getXRef(), &obj2)->isDict()) { + scanFonts(obj2.getDict(), doc); + } + obj2.free(); +} + static void scanFonts(Dict *resDict, PDFDoc *doc) { - Object obj1, obj2, xObjDict, xObj, resObj; + Object obj1, obj2, xObjDict, xObj; + Object patternDict, pattern, gsDict, gs, smask, smaskGroup, resObj; Ref r; GfxFontDict *gfxFontDict; GfxFont *font; @@ -211,23 +275,58 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) { } obj1.free(); - // recursively scan any resource dictionaries in objects in this + // recursively scan any resource dictionaries in XObjects in this // resource dictionary resDict->lookup("XObject", &xObjDict); if (xObjDict.isDict()) { for (i = 0; i < xObjDict.dictGetLength(); ++i) { xObjDict.dictGetVal(i, &xObj); if (xObj.isStream()) { - xObj.streamGetDict()->lookup("Resources", &resObj); - if (resObj.isDict()) { - scanFonts(resObj.getDict(), doc); - } + xObj.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); resObj.free(); } xObj.free(); } } xObjDict.free(); + + // recursively scan any resource dictionaries in Patterns in this + // resource dictionary + resDict->lookup("Pattern", &patternDict); + if (patternDict.isDict()) { + for (i = 0; i < patternDict.dictGetLength(); ++i) { + patternDict.dictGetVal(i, &pattern); + if (pattern.isStream()) { + pattern.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + pattern.free(); + } + } + patternDict.free(); + + // recursively scan any resource dictionaries in ExtGStates in this + // resource dictionary + resDict->lookup("ExtGState", &gsDict); + if (gsDict.isDict()) { + for (i = 0; i < gsDict.dictGetLength(); ++i) { + if (gsDict.dictGetVal(i, &gs)->isDict()) { + if (gs.dictLookup("SMask", &smask)->isDict()) { + if (smask.dictLookup("G", &smaskGroup)->isStream()) { + smaskGroup.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + smaskGroup.free(); + } + smask.free(); + } + gs.free(); + } + } + gsDict.free(); } static void scanFont(GfxFont *font, PDFDoc *doc) { @@ -235,6 +334,7 @@ static void scanFont(GfxFont *font, PDFDoc *doc) { Object fontObj, toUnicodeObj; GString *name; GBool emb, subset, hasToUnicode; + GfxFontLoc *loc; int i; fontRef = *font->getID(); @@ -284,10 +384,38 @@ static void scanFont(GfxFont *font, PDFDoc *doc) { subset ? "yes" : "no", hasToUnicode ? "yes" : "no"); if (fontRef.gen >= 100000) { - printf(" [none]\n"); + printf(" [none]"); } else { - printf(" %6d %2d\n", fontRef.num, fontRef.gen); + printf(" %6d %2d", fontRef.num, fontRef.gen); + } + if (showFontLoc || showFontLocPS) { + if (font->getType() == fontType3) { + printf(" embedded"); + } else { + loc = font->locateFont(doc->getXRef(), showFontLocPS); + if (loc) { + if (loc->locType == gfxFontLocEmbedded) { + printf(" embedded"); + } else if (loc->locType == gfxFontLocExternal) { + if (loc->path) { + printf(" external: %s", loc->path->getCString()); + } else { + printf(" unavailable"); + } + } else if (loc->locType == gfxFontLocResident) { + if (loc->path) { + printf(" resident: %s", loc->path->getCString()); + } else { + printf(" unavailable"); + } + } + } else { + printf(" unknown"); + } + delete loc; + } } + printf("\n"); // add this font to the list if (fontsLen == fontsSize) { diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfimages.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfimages.cc index dc794433e69..dc794433e69 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfimages.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfimages.cc diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfinfo.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfinfo.cc index ad482acdb4e..9c0493d7df6 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdfinfo.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdfinfo.cc @@ -2,7 +2,7 @@ // // pdfinfo.cc // -// Copyright 1998-2003 Glyph & Cog, LLC +// Copyright 1998-2013 Glyph & Cog, LLC // //======================================================================== @@ -16,6 +16,7 @@ #include "parseargs.h" #include "GString.h" #include "gmem.h" +#include "gfile.h" #include "GlobalParams.h" #include "Object.h" #include "Stream.h" @@ -27,7 +28,7 @@ #include "PDFDoc.h" #include "CharTypes.h" #include "UnicodeMap.h" -#include "PDFDocEncoding.h" +#include "TextString.h" #include "Error.h" #include "config.h" @@ -239,6 +240,7 @@ int main(int argc, char *argv[]) { wISO /= sqrt(2.0); } } + printf(" (rotated %d degrees)", doc->getPageRotate(pg)); printf("\n"); } @@ -275,16 +277,8 @@ int main(int argc, char *argv[]) { f = fopen(fileName->getCString(), "rb"); #endif if (f) { -#if HAVE_FSEEKO - fseeko(f, 0, SEEK_END); - printf("File size: %u bytes\n", (Guint)ftello(f)); -#elif HAVE_FSEEK64 - fseek64(f, 0, SEEK_END); - printf("File size: %u bytes\n", (Guint)ftell64(f)); -#else - fseek(f, 0, SEEK_END); - printf("File size: %d bytes\n", (int)ftell(f)); -#endif + gfseek(f, 0, SEEK_END); + printf("File size: %u bytes\n", (Guint)gftell(f)); fclose(f); } @@ -322,36 +316,21 @@ int main(int argc, char *argv[]) { static void printInfoString(Dict *infoDict, const char *key, const char *text, UnicodeMap *uMap) { Object obj; - GString *s1; - GBool isUnicode; - Unicode u; + TextString *s; + Unicode *u; char buf[8]; int i, n; if (infoDict->lookup(key, &obj)->isString()) { fputs(text, stdout); - s1 = obj.getString(); - if ((s1->getChar(0) & 0xff) == 0xfe && - (s1->getChar(1) & 0xff) == 0xff) { - isUnicode = gTrue; - i = 2; - } else { - isUnicode = gFalse; - i = 0; - } - while (i < obj.getString()->getLength()) { - if (isUnicode) { - u = ((s1->getChar(i) & 0xff) << 8) | - (s1->getChar(i+1) & 0xff); - i += 2; - } else { - u = pdfDocEncoding[s1->getChar(i) & 0xff]; - ++i; - } - n = uMap->mapUnicode(u, buf, sizeof(buf)); + s = new TextString(obj.getString()); + u = s->getUnicode(); + for (i = 0; i < s->getLength(); ++i) { + n = uMap->mapUnicode(u[i], buf, sizeof(buf)); fwrite(buf, 1, n, stdout); } fputc('\n', stdout); + delete s; } obj.free(); } diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftohtml.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftohtml.cc new file mode 100644 index 00000000000..f1fe691eb37 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftohtml.cc @@ -0,0 +1,246 @@ +//======================================================================== +// +// pdftohtml.cc +// +// Copyright 2005 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> +#include <stdio.h> +#include <stdlib.h> +#include "parseargs.h" +#include "gmem.h" +#include "gfile.h" +#include "GString.h" +#include "GlobalParams.h" +#include "PDFDoc.h" +#include "HTMLGen.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "config.h" + +//------------------------------------------------------------------------ + +static GBool createIndex(char *htmlDir); + +//------------------------------------------------------------------------ + +static int firstPage = 1; +static int lastPage = 0; +static int resolution = 150; +static GBool skipInvisible = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-r", argInt, &resolution, 0, + "resolution, in DPI (default is 150)"}, + {"-skipinvisible", argFlag, &skipInvisible, 0, + "do not draw invisible text"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +//------------------------------------------------------------------------ + +static int writeToFile(void *file, const char *data, int size) { + return (int)fwrite(data, 1, size, (FILE *)file); +} + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + char *htmlDir; + GString *ownerPW, *userPW; + HTMLGen *htmlGen; + GString *htmlFileName, *pngFileName, *pngURL; + FILE *htmlFile, *pngFile; + int pg, err, exitCode; + GBool ok; + + exitCode = 99; + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdftohtml version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftohtml", "<PDF-file> <html-dir>", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + htmlDir = argv[2]; + + // read config file + globalParams = new GlobalParams(cfgFileName); + if (quiet) { + globalParams->setErrQuiet(quiet); + } + globalParams->setupBaseFonts(NULL); + globalParams->setTextEncoding("UTF-8"); + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // check for copy permission + if (!doc->okToCopy()) { + error(errNotAllowed, -1, + "Copying of text from this document is not allowed."); + exitCode = 3; + goto err1; + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // create HTML directory + if (!createDir(htmlDir, 0755)) { + error(errIO, -1, "Couldn't create HTML output directory '{0:s}'", + htmlDir); + exitCode = 2; + goto err1; + } + + // set up the HTMLGen object + htmlGen = new HTMLGen(resolution); + if (!htmlGen->isOk()) { + exitCode = 99; + goto err1; + } + htmlGen->setDrawInvisibleText(!skipInvisible); + htmlGen->startDoc(doc); + + // convert the pages + for (pg = firstPage; pg <= lastPage; ++pg) { + htmlFileName = GString::format("{0:s}/page{1:d}.html", htmlDir, pg); + pngFileName = GString::format("{0:s}/page{1:d}.png", htmlDir, pg); + if (!(htmlFile = fopen(htmlFileName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open HTML file '{0:t}'", htmlFileName); + delete htmlFileName; + delete pngFileName; + goto err2; + } + if (!(pngFile = fopen(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(), + &writeToFile, htmlFile, + &writeToFile, pngFile); + delete pngURL; + fclose(htmlFile); + fclose(pngFile); + delete htmlFileName; + delete pngFileName; + if (err != errNone) { + error(errIO, -1, "Error converting page {0:d}", pg); + exitCode = 2; + goto err2; + } + } + + // create the master index + if (!createIndex(htmlDir)) { + exitCode = 2; + goto err2; + } + + exitCode = 0; + + // clean up + err2: + delete htmlGen; + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static GBool createIndex(char *htmlDir) { + GString *htmlFileName; + FILE *html; + int pg; + + htmlFileName = GString::format("{0:s}/index.html", htmlDir); + html = fopen(htmlFileName->getCString(), "w"); + delete htmlFileName; + if (!html) { + error(errIO, -1, "Couldn't open HTML file '{0:t}'", htmlFileName); + return gFalse; + } + + fprintf(html, "<html>\n"); + fprintf(html, "<body>\n"); + for (pg = firstPage; pg <= lastPage; ++pg) { + fprintf(html, "<a href=\"page%d.html\">page %d</a><br>\n", pg, pg); + } + fprintf(html, "</body>\n"); + fprintf(html, "</html>\n"); + + fclose(html); + + return gTrue; +} diff --git a/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftopng.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftopng.cc new file mode 100644 index 00000000000..bb91ebac8b0 --- /dev/null +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftopng.cc @@ -0,0 +1,289 @@ +//======================================================================== +// +// pdftopng.cc +// +// Copyright 2009 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> +#include <stdlib.h> +#include <stdio.h> +#include <png.h> +#include "parseargs.h" +#include "gmem.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Object.h" +#include "PDFDoc.h" +#include "SplashBitmap.h" +#include "Splash.h" +#include "SplashOutputDev.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static int resolution = 150; +static GBool mono = gFalse; +static GBool gray = gFalse; +static char enableFreeTypeStr[16] = ""; +static char antialiasStr[16] = ""; +static char vectorAntialiasStr[16] = ""; +static char ownerPassword[33] = ""; +static char userPassword[33] = ""; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to print"}, + {"-l", argInt, &lastPage, 0, + "last page to print"}, + {"-r", argInt, &resolution, 0, + "resolution, in DPI (default is 150)"}, + {"-mono", argFlag, &mono, 0, + "generate a monochrome PBM file"}, + {"-gray", argFlag, &gray, 0, + "generate a grayscale PGM file"}, +#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H + {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), + "enable FreeType font rasterizer: yes, no"}, +#endif + {"-aa", argString, antialiasStr, sizeof(antialiasStr), + "enable font anti-aliasing: yes, no"}, + {"-aaVector", argString, vectorAntialiasStr, sizeof(vectorAntialiasStr), + "enable vector anti-aliasing: yes, no"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +static void setupPNG(png_structp *png, png_infop *pngInfo, FILE *f, + int bitDepth, int colorType, + SplashBitmap *bitmap); +static void writePNGData(png_structp png, SplashBitmap *bitmap); +static void finishPNG(png_structp *png, png_infop *pngInfo); + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + char *pngRoot; + GString *pngFile; + GString *ownerPW, *userPW; + SplashColor paperColor; + SplashOutputDev *splashOut; + GBool ok; + int exitCode; + int pg; + png_structp png; + png_infop pngInfo; + FILE *f; + + exitCode = 99; + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (mono && gray) { + ok = gFalse; + } + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdftopng version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftopng", "<PDF-file> <PNG-root>", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + pngRoot = argv[2]; + + // read config file + globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); + if (enableFreeTypeStr[0]) { + if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { + fprintf(stderr, "Bad '-freetype' value on command line\n"); + } + } + if (antialiasStr[0]) { + if (!globalParams->setAntialias(antialiasStr)) { + fprintf(stderr, "Bad '-aa' value on command line\n"); + } + } + if (vectorAntialiasStr[0]) { + if (!globalParams->setVectorAntialias(vectorAntialiasStr)) { + fprintf(stderr, "Bad '-aaVector' value on command line\n"); + } + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0]) { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0]) { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // get page range + if (firstPage < 1) + firstPage = 1; + if (lastPage < 1 || lastPage > doc->getNumPages()) + lastPage = doc->getNumPages(); + + + // write PNG files + if (mono) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono1, 1, gFalse, paperColor); + } else if (gray) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse, paperColor); + } else { + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + } + splashOut->startDoc(doc->getXRef()); + for (pg = firstPage; pg <= lastPage; ++pg) { + doc->displayPage(splashOut, pg, resolution, resolution, 0, + gFalse, gTrue, gFalse); + if (mono) { + if (!strcmp(pngRoot, "-")) { + f = stdout; + } else { + pngFile = GString::format("{0:s}-{1:06d}.png", pngRoot, pg); + if (!(f = fopen(pngFile->getCString(), "wb"))) { + exit(2); + } + delete pngFile; + } + setupPNG(&png, &pngInfo, f, + 1, PNG_COLOR_TYPE_GRAY, splashOut->getBitmap()); + writePNGData(png, splashOut->getBitmap()); + finishPNG(&png, &pngInfo); + fclose(f); + } else if (gray) { + if (!strcmp(pngRoot, "-")) { + f = stdout; + } else { + pngFile = GString::format("{0:s}-{1:06d}.png", pngRoot, pg); + if (!(f = fopen(pngFile->getCString(), "wb"))) { + exit(2); + } + delete pngFile; + } + setupPNG(&png, &pngInfo, f, + 8, PNG_COLOR_TYPE_GRAY, splashOut->getBitmap()); + writePNGData(png, splashOut->getBitmap()); + finishPNG(&png, &pngInfo); + fclose(f); + } else { // RGB + if (!strcmp(pngRoot, "-")) { + f = stdout; + } else { + pngFile = GString::format("{0:s}-{1:06d}.png", pngRoot, pg); + if (!(f = fopen(pngFile->getCString(), "wb"))) { + exit(2); + } + delete pngFile; + } + setupPNG(&png, &pngInfo, f, + 8, PNG_COLOR_TYPE_RGB, splashOut->getBitmap()); + writePNGData(png, splashOut->getBitmap()); + finishPNG(&png, &pngInfo); + fclose(f); + } + } + delete splashOut; + + exitCode = 0; + + // clean up + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void setupPNG(png_structp *png, png_infop *pngInfo, FILE *f, + int bitDepth, int colorType, + SplashBitmap *bitmap) { + if (!(*png = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) || + !(*pngInfo = png_create_info_struct(*png))) { + exit(2); + } + if (setjmp(png_jmpbuf(*png))) { + exit(2); + } + png_init_io(*png, f); + png_set_IHDR(*png, *pngInfo, bitmap->getWidth(), bitmap->getHeight(), + bitDepth, colorType, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(*png, *pngInfo); +} + +static void writePNGData(png_structp png, SplashBitmap *bitmap) { + Guchar *p; + int y; + + if (setjmp(png_jmpbuf(png))) { + exit(2); + } + p = bitmap->getDataPtr(); + for (y = 0; y < bitmap->getHeight(); ++y) { + png_write_row(png, (png_bytep)p); + p += bitmap->getRowSize(); + } +} + + + +static void finishPNG(png_structp *png, png_infop *pngInfo) { + if (setjmp(png_jmpbuf(*png))) { + exit(2); + } + png_write_end(*png, *pngInfo); + png_destroy_write_struct(png, pngInfo); +} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftoppm.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftoppm.cc index cfc72368076..17c0bbf276e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftoppm.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftoppm.cc @@ -8,6 +8,14 @@ #include <aconf.h> #include <stdio.h> +#ifdef _WIN32 +# include <io.h> +# include <fcntl.h> +#endif +#ifdef DEBUG_FP_LINUX +# include <fenv.h> +# include <fpu_control.h> +#endif #include "parseargs.h" #include "gmem.h" #include "GString.h" @@ -24,7 +32,6 @@ static int lastPage = 0; static int resolution = 150; static GBool mono = gFalse; static GBool gray = gFalse; -static char enableT1libStr[16] = ""; static char enableFreeTypeStr[16] = ""; static char antialiasStr[16] = ""; static char vectorAntialiasStr[16] = ""; @@ -46,10 +53,6 @@ static ArgDesc argDesc[] = { "generate a monochrome PBM file"}, {"-gray", argFlag, &gray, 0, "generate a grayscale PGM file"}, -#if HAVE_T1LIB_H - {"-t1lib", argString, enableT1libStr, sizeof(enableT1libStr), - "enable t1lib font rasterizer: yes, no"}, -#endif #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), "enable FreeType font rasterizer: yes, no"}, @@ -91,6 +94,21 @@ int main(int argc, char *argv[]) { int exitCode; int pg; +#ifdef DEBUG_FP_LINUX + // enable exceptions on floating point div-by-zero + feenableexcept(FE_DIVBYZERO); + // force 64-bit rounding: this avoids changes in output when minor + // code changes result in spills of x87 registers; it also avoids + // differences in output with valgrind's 64-bit floating point + // emulation (yes, this is a kludge; but it's pretty much + // unavoidable given the x87 instruction set; see gcc bug 323 for + // more info) + fpu_control_t cw; + _FPU_GETCW(cw); + cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE; + _FPU_SETCW(cw); +#endif + exitCode = 99; // parse args @@ -112,11 +130,6 @@ int main(int argc, char *argv[]) { // read config file globalParams = new GlobalParams(cfgFileName); globalParams->setupBaseFonts(NULL); - if (enableT1libStr[0]) { - if (!globalParams->setEnableT1lib(enableT1libStr)) { - fprintf(stderr, "Bad '-t1lib' value on command line\n"); - } - } if (enableFreeTypeStr[0]) { if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { fprintf(stderr, "Bad '-freetype' value on command line\n"); @@ -182,6 +195,9 @@ int main(int argc, char *argv[]) { doc->displayPage(splashOut, pg, resolution, resolution, 0, gFalse, gTrue, gFalse); if (!strcmp(ppmRoot, "-")) { +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif splashOut->getBitmap()->writePNMFile(stdout); } else { ppmFile = GString::format("{0:s}-{1:06d}.{2:s}", diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftops.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftops.cc index eae441f15ea..a6f478da4ed 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftops.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftops.cc @@ -11,6 +11,10 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> +#ifdef DEBUG_FP_LINUX +# include <fenv.h> +# include <fpu_control.h> +#endif #include "parseargs.h" #include "GString.h" #include "gmem.h" @@ -147,6 +151,21 @@ int main(int argc, char *argv[]) { char *p; int exitCode; +#ifdef DEBUG_FP_LINUX + // enable exceptions on floating point div-by-zero + feenableexcept(FE_DIVBYZERO); + // force 64-bit rounding: this avoids changes in output when minor + // code changes result in spills of x87 registers; it also avoids + // differences in output with valgrind's 64-bit floating point + // emulation (yes, this is a kludge; but it's pretty much + // unavoidable given the x87 instruction set; see gcc bug 323 for + // more info) + fpu_control_t cw; + _FPU_GETCW(cw); + cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE; + _FPU_SETCW(cw); +#endif + exitCode = 99; // parse args @@ -216,6 +235,9 @@ int main(int argc, char *argv[]) { if (noCrop) { globalParams->setPSCrop(gFalse); } + if (pageCrop) { + globalParams->setPSUseCropBoxAsPage(gTrue); + } if (expand) { globalParams->setPSExpandSmaller(gTrue); } @@ -318,15 +340,18 @@ int main(int argc, char *argv[]) { firstPage, lastPage, mode); if (psOut->isOk()) { doc->displayPages(psOut, firstPage, lastPage, 72, 72, - 0, !pageCrop, globalParams->getPSCrop(), gTrue); + 0, !globalParams->getPSUseCropBoxAsPage(), + globalParams->getPSCrop(), gTrue); } else { delete psOut; exitCode = 2; goto err2; } - delete psOut; - exitCode = 0; + if (!psOut->checkIO()) { + exitCode = 2; + } + delete psOut; // clean up err2: diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftotext.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftotext.cc index 5296ac4646c..758413edd3b 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/pdftotext.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/pdftotext.cc @@ -2,7 +2,7 @@ // // pdftotext.cc // -// Copyright 1997-2003 Glyph & Cog, LLC +// Copyright 1997-2013 Glyph & Cog, LLC // //======================================================================== @@ -11,6 +11,10 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> +#ifdef DEBUG_FP_LINUX +# include <fenv.h> +# include <fpu_control.h> +#endif #include "parseargs.h" #include "GString.h" #include "gmem.h" @@ -26,21 +30,19 @@ #include "TextOutputDev.h" #include "CharTypes.h" #include "UnicodeMap.h" +#include "TextString.h" #include "Error.h" #include "config.h" -static void printInfoString(FILE *f, Dict *infoDict, const char *key, - const char *text1, const char *text2, - UnicodeMap *uMap); -static void printInfoDate(FILE *f, Dict *infoDict, const char *key, - const char *fmt); - static int firstPage = 1; static int lastPage = 0; static GBool physLayout = gFalse; -static double fixedPitch = 0; +static GBool tableLayout = gFalse; +static GBool linePrinter = gFalse; static GBool rawOrder = gFalse; -static GBool htmlMeta = gFalse; +static double fixedPitch = 0; +static double fixedLineSpacing = 0; +static GBool clipText = gFalse; static char textEncName[128] = ""; static char textEOL[16] = ""; static GBool noPageBreaks = gFalse; @@ -58,12 +60,18 @@ static ArgDesc argDesc[] = { "last page to convert"}, {"-layout", argFlag, &physLayout, 0, "maintain original physical layout"}, - {"-fixed", argFP, &fixedPitch, 0, - "assume fixed-pitch (or tabular) text"}, + {"-table", argFlag, &tableLayout, 0, + "similar to -layout, but optimized for tables"}, + {"-lineprinter", argFlag, &linePrinter, 0, + "use strict fixed-pitch/height layout"}, {"-raw", argFlag, &rawOrder, 0, "keep strings in content stream order"}, - {"-htmlmeta", argFlag, &htmlMeta, 0, - "generate a simple HTML file, including the meta information"}, + {"-fixed", argFP, &fixedPitch, 0, + "assume fixed-pitch (or tabular) text"}, + {"-linespacing", argFP, &fixedLineSpacing, 0, + "fixed line spacing for LinePrinter mode"}, + {"-clip", argFlag, &clipText, 0, + "separate clipped text"}, {"-enc", argString, textEncName, sizeof(textEncName), "output text encoding name"}, {"-eol", argString, textEOL, sizeof(textEOL), @@ -96,14 +104,29 @@ int main(int argc, char *argv[]) { GString *fileName; GString *textFileName; GString *ownerPW, *userPW; + TextOutputControl textOutControl; TextOutputDev *textOut; - FILE *f; UnicodeMap *uMap; Object info; GBool ok; char *p; int exitCode; +#ifdef DEBUG_FP_LINUX + // enable exceptions on floating point div-by-zero + feenableexcept(FE_DIVBYZERO); + // force 64-bit rounding: this avoids changes in output when minor + // code changes result in spills of x87 registers; it also avoids + // differences in output with valgrind's 64-bit floating point + // emulation (yes, this is a kludge; but it's pretty much + // unavoidable given the x87 instruction set; see gcc bug 323 for + // more info) + fpu_control_t cw; + _FPU_GETCW(cw); + cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE; + _FPU_SETCW(cw); +#endif + exitCode = 99; // parse args @@ -117,9 +140,6 @@ int main(int argc, char *argv[]) { goto err0; } fileName = new GString(argv[1]); - if (fixedPitch) { - physLayout = gTrue; - } // read config file globalParams = new GlobalParams(cfgFileName); @@ -187,7 +207,7 @@ int main(int argc, char *argv[]) { } else { textFileName = fileName->copy(); } - textFileName->append(htmlMeta ? ".html" : ".txt"); + textFileName->append(".txt"); } // get page range @@ -198,50 +218,25 @@ int main(int argc, char *argv[]) { lastPage = doc->getNumPages(); } - // write HTML header - if (htmlMeta) { - if (!textFileName->cmp("-")) { - f = stdout; - } else { - if (!(f = fopen(textFileName->getCString(), "wb"))) { - error(errIO, -1, "Couldn't open text file '{0:t}'", textFileName); - exitCode = 2; - goto err3; - } - } - fputs("<html>\n", f); - fputs("<head>\n", f); - doc->getDocInfo(&info); - if (info.isDict()) { - printInfoString(f, info.getDict(), "Title", "<title>", "</title>\n", - uMap); - printInfoString(f, info.getDict(), "Subject", - "<meta name=\"Subject\" content=\"", "\">\n", uMap); - printInfoString(f, info.getDict(), "Keywords", - "<meta name=\"Keywords\" content=\"", "\">\n", uMap); - printInfoString(f, info.getDict(), "Author", - "<meta name=\"Author\" content=\"", "\">\n", uMap); - printInfoString(f, info.getDict(), "Creator", - "<meta name=\"Creator\" content=\"", "\">\n", uMap); - printInfoString(f, info.getDict(), "Producer", - "<meta name=\"Producer\" content=\"", "\">\n", uMap); - printInfoDate(f, info.getDict(), "CreationDate", - "<meta name=\"CreationDate\" content=\"%s\">\n"); - printInfoDate(f, info.getDict(), "LastModifiedDate", - "<meta name=\"ModDate\" content=\"%s\">\n"); - } - info.free(); - fputs("</head>\n", f); - fputs("<body>\n", f); - fputs("<pre>\n", f); - if (f != stdout) { - fclose(f); - } - } - // write text file - textOut = new TextOutputDev(textFileName->getCString(), - physLayout, fixedPitch, rawOrder, htmlMeta); + if (tableLayout) { + textOutControl.mode = textOutTableLayout; + textOutControl.fixedPitch = fixedPitch; + } else if (physLayout) { + textOutControl.mode = textOutPhysLayout; + textOutControl.fixedPitch = fixedPitch; + } else if (linePrinter) { + textOutControl.mode = textOutLinePrinter; + textOutControl.fixedPitch = fixedPitch; + textOutControl.fixedLineSpacing = fixedLineSpacing; + } else if (rawOrder) { + textOutControl.mode = textOutRawOrder; + } else { + textOutControl.mode = textOutReadingOrder; + } + textOutControl.clipText = clipText; + textOut = new TextOutputDev(textFileName->getCString(), &textOutControl, + gFalse); if (textOut->isOk()) { doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, gFalse, gTrue, gFalse); @@ -252,25 +247,6 @@ int main(int argc, char *argv[]) { } delete textOut; - // write end of HTML file - if (htmlMeta) { - if (!textFileName->cmp("-")) { - f = stdout; - } else { - if (!(f = fopen(textFileName->getCString(), "ab"))) { - error(errIO, -1, "Couldn't open text file '{0:t}'", textFileName); - exitCode = 2; - goto err3; - } - } - fputs("</pre>\n", f); - fputs("</body>\n", f); - fputs("</html>\n", f); - if (f != stdout) { - fclose(f); - } - } - exitCode = 0; // clean up @@ -289,56 +265,3 @@ int main(int argc, char *argv[]) { return exitCode; } - -static void printInfoString(FILE *f, Dict *infoDict, const char *key, - const char *text1, const char *text2, - UnicodeMap *uMap) { - Object obj; - GString *s1; - GBool isUnicode; - Unicode u; - char buf[8]; - int i, n; - - if (infoDict->lookup(key, &obj)->isString()) { - fputs(text1, f); - s1 = obj.getString(); - if ((s1->getChar(0) & 0xff) == 0xfe && - (s1->getChar(1) & 0xff) == 0xff) { - isUnicode = gTrue; - i = 2; - } else { - isUnicode = gFalse; - i = 0; - } - while (i < obj.getString()->getLength()) { - if (isUnicode) { - u = ((s1->getChar(i) & 0xff) << 8) | - (s1->getChar(i+1) & 0xff); - i += 2; - } else { - u = s1->getChar(i) & 0xff; - ++i; - } - n = uMap->mapUnicode(u, buf, sizeof(buf)); - fwrite(buf, 1, n, f); - } - fputs(text2, f); - } - obj.free(); -} - -static void printInfoDate(FILE *f, Dict *infoDict, const char *key, - const char *fmt) { - Object obj; - char *s; - - if (infoDict->lookup(key, &obj)->isString()) { - s = obj.getString()->getCString(); - if (s[0] == 'D' && s[1] == ':') { - s += 2; - } - fprintf(f, fmt, s); - } - obj.free(); -} diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/print.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/print.xbm index 209eb43583f..209eb43583f 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/print.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/print.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/printDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/printDis.xbm index 19e962d5fbe..19e962d5fbe 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/printDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/printDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/rightArrow.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/rightArrow.xbm index 4ccb16b1e32..4ccb16b1e32 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/rightArrow.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/rightArrow.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/rightArrowDis.xbm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/rightArrowDis.xbm index 1216c47f10e..1216c47f10e 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/rightArrowDis.xbm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/rightArrowDis.xbm diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/vms_make.com b/Build/source/libs/xpdf/xpdf-3.04/xpdf/vms_make.com index f4fb74aff88..f4fb74aff88 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/vms_make.com +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/vms_make.com diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/xpdf.cc b/Build/source/libs/xpdf/xpdf-3.04/xpdf/xpdf.cc index e5d91ca9365..1041265a3f1 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/xpdf.cc +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/xpdf.cc @@ -22,7 +22,6 @@ //------------------------------------------------------------------------ static GBool contView = gFalse; -static char enableT1libStr[16] = ""; static char enableFreeTypeStr[16] = ""; static char antialiasStr[16] = ""; static char vectorAntialiasStr[16] = ""; @@ -66,10 +65,6 @@ static ArgDesc argDesc[] = { "initial zoom level (percent, 'page', 'width')"}, {"-cont", argFlag, &contView, 0, "start in continuous view mode" }, -#if HAVE_T1LIB_H - {"-t1lib", argString, enableT1libStr, sizeof(enableT1libStr), - "enable t1lib font rasterizer: yes, no"}, -#endif #if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), "enable FreeType font rasterizer: yes, no"}, @@ -185,11 +180,6 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Bad '-eol' value on command line\n"); } } - if (enableT1libStr[0]) { - if (!globalParams->setEnableT1lib(enableT1libStr)) { - fprintf(stderr, "Bad '-t1lib' value on command line\n"); - } - } if (enableFreeTypeStr[0]) { if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { fprintf(stderr, "Bad '-freetype' value on command line\n"); diff --git a/Build/source/libs/xpdf/xpdf-3.03/xpdf/xpdfIcon.xpm b/Build/source/libs/xpdf/xpdf-3.04/xpdf/xpdfIcon.xpm index 5e05d20e2c0..5e05d20e2c0 100644 --- a/Build/source/libs/xpdf/xpdf-3.03/xpdf/xpdfIcon.xpm +++ b/Build/source/libs/xpdf/xpdf-3.04/xpdf/xpdfIcon.xpm diff --git a/Build/source/texk/web2c/pdftexdir/ChangeLog b/Build/source/texk/web2c/pdftexdir/ChangeLog index 5eadcf82124..ac596ca5337 100644 --- a/Build/source/texk/web2c/pdftexdir/ChangeLog +++ b/Build/source/texk/web2c/pdftexdir/ChangeLog @@ -1,3 +1,11 @@ +2014-06-18 Peter Breitenlohner <peb@mppmu.mpg.de> + + * ttf2afm.c: Avoid undefined behaviour when char is signed. + +2014-06-16 Peter Breitenlohner <peb@mppmu.mpg.de> + + * pdftosrc.cc: Adapt to xpdf-3.04. + 2012-05-20 Thanh Han The <thanh@river-valley.org> * pdftex.web: do not try to avoid printing 0 0 Td. diff --git a/Build/source/texk/web2c/pdftexdir/pdftosrc.cc b/Build/source/texk/web2c/pdftexdir/pdftosrc.cc index 642e12feec1..ef59b1fddb1 100644 --- a/Build/source/texk/web2c/pdftexdir/pdftosrc.cc +++ b/Build/source/texk/web2c/pdftexdir/pdftosrc.cc @@ -135,11 +135,7 @@ int main(int argc, char *argv[]) exit(1); } if (extract_xref_table) { -#ifdef POPPLER_VERSION int size = xref->getNumObjects(); -#else - int size = xref->getSize(); -#endif int i; for (i = 0; i < size; i++) { if (xref->getEntry(i)->offset == 0xffffffff) |