summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf')
-rw-r--r--Build/source/libs/xpdf/ANNOUNCE13
-rw-r--r--Build/source/libs/xpdf/CHANGES136
-rw-r--r--Build/source/libs/xpdf/INSTALL6
-rw-r--r--Build/source/libs/xpdf/README54
-rw-r--r--Build/source/libs/xpdf/aconf-win32.h38
-rw-r--r--Build/source/libs/xpdf/aconf.h.in25
-rw-r--r--Build/source/libs/xpdf/dj_make.bat17
-rw-r--r--Build/source/libs/xpdf/fofi/FoFiTrueType.cc434
-rw-r--r--Build/source/libs/xpdf/fofi/FoFiTrueType.h40
-rw-r--r--Build/source/libs/xpdf/fofi/FoFiType1.cc65
-rw-r--r--Build/source/libs/xpdf/fofi/FoFiType1C.cc590
-rw-r--r--Build/source/libs/xpdf/fofi/FoFiType1C.h5
-rw-r--r--Build/source/libs/xpdf/goo/FixedPoint.cc29
-rw-r--r--Build/source/libs/xpdf/goo/FixedPoint.h5
-rw-r--r--Build/source/libs/xpdf/goo/GString.cc449
-rw-r--r--Build/source/libs/xpdf/goo/GString.h39
-rw-r--r--Build/source/libs/xpdf/goo/Makefile.in7
-rw-r--r--Build/source/libs/xpdf/goo/depend.mk2
-rw-r--r--Build/source/libs/xpdf/goo/gfile.cc58
-rw-r--r--Build/source/libs/xpdf/goo/gfile.h5
-rw-r--r--Build/source/libs/xpdf/goo/gmem.cc (renamed from Build/source/libs/xpdf/goo/gmem.c)119
-rw-r--r--Build/source/libs/xpdf/goo/gmem.h25
-rw-r--r--Build/source/libs/xpdf/xpdf/Catalog.cc35
-rw-r--r--Build/source/libs/xpdf/xpdf/Catalog.h9
-rw-r--r--Build/source/libs/xpdf/xpdf/Decrypt.cc427
-rw-r--r--Build/source/libs/xpdf/xpdf/Decrypt.h54
-rw-r--r--Build/source/libs/xpdf/xpdf/Function.cc64
-rw-r--r--Build/source/libs/xpdf/xpdf/Function.h8
-rw-r--r--Build/source/libs/xpdf/xpdf/GfxFont.cc28
-rw-r--r--Build/source/libs/xpdf/xpdf/GfxFont.h7
-rw-r--r--Build/source/libs/xpdf/xpdf/GfxState.cc205
-rw-r--r--Build/source/libs/xpdf/xpdf/GfxState.h40
-rw-r--r--Build/source/libs/xpdf/xpdf/GlobalParams.cc1249
-rw-r--r--Build/source/libs/xpdf/xpdf/GlobalParams.h143
-rw-r--r--Build/source/libs/xpdf/xpdf/JBIG2Stream.cc74
-rw-r--r--Build/source/libs/xpdf/xpdf/JBIG2Stream.h4
-rw-r--r--Build/source/libs/xpdf/xpdf/JPXStream.cc235
-rw-r--r--Build/source/libs/xpdf/xpdf/JPXStream.h8
-rw-r--r--Build/source/libs/xpdf/xpdf/Link.cc141
-rw-r--r--Build/source/libs/xpdf/xpdf/Link.h40
-rw-r--r--Build/source/libs/xpdf/xpdf/OutputDev.cc2
-rw-r--r--Build/source/libs/xpdf/xpdf/OutputDev.h59
-rw-r--r--Build/source/libs/xpdf/xpdf/PDFDoc.cc85
-rw-r--r--Build/source/libs/xpdf/xpdf/PDFDoc.h17
-rw-r--r--Build/source/libs/xpdf/xpdf/PSTokenizer.cc2
-rw-r--r--Build/source/libs/xpdf/xpdf/Page.cc226
-rw-r--r--Build/source/libs/xpdf/xpdf/Page.h20
-rw-r--r--Build/source/libs/xpdf/xpdf/Parser.cc61
-rw-r--r--Build/source/libs/xpdf/xpdf/Parser.h11
-rw-r--r--Build/source/libs/xpdf/xpdf/SecurityHandler.cc14
-rw-r--r--Build/source/libs/xpdf/xpdf/SecurityHandler.h5
-rw-r--r--Build/source/libs/xpdf/xpdf/Stream.cc280
-rw-r--r--Build/source/libs/xpdf/xpdf/Stream.h40
-rw-r--r--Build/source/libs/xpdf/xpdf/XRef.cc26
-rw-r--r--Build/source/libs/xpdf/xpdf/XRef.h6
-rw-r--r--Build/source/libs/xpdf/xpdf/config.h17
56 files changed, 4527 insertions, 1276 deletions
diff --git a/Build/source/libs/xpdf/ANNOUNCE b/Build/source/libs/xpdf/ANNOUNCE
index 3f12a2602f8..1184040894f 100644
--- a/Build/source/libs/xpdf/ANNOUNCE
+++ b/Build/source/libs/xpdf/ANNOUNCE
@@ -1,4 +1,4 @@
-Subject: ANNOUNCE: Xpdf 3.01 - a PDF viewer for X
+Subject: ANNOUNCE: Xpdf 3.02 - a PDF viewer for X
Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the
@@ -11,12 +11,11 @@ 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 continuous view mode, including the '-cont' switch and the
- 'continuousView' config file option.
-* At high zoom levels, don't rasterize the entire page - this avoids
- problems running out of memory.
-* Added "search backward" and "match case" options to the find dialog.
-* Support explicitly masked images and soft masked images.
+* Anti-aliased vector graphics, including stroke adjustment.
+* Support for PDF 1.6 and PDF 1.7, including AES decryption and
+ OpenType fonts.
+* User-configurable key/mouse bindings.
+* Improved full-screen mode, with the ability to toggle on the fly.
See the `CHANGES' file for a complete list of changes.
diff --git a/Build/source/libs/xpdf/CHANGES b/Build/source/libs/xpdf/CHANGES
index 360dd25a105..0378f0da537 100644
--- a/Build/source/libs/xpdf/CHANGES
+++ b/Build/source/libs/xpdf/CHANGES
@@ -1577,7 +1577,8 @@ Minor changes to GlobalParams.h and JPXStream.h because some compilers
Xpdf now complains about a negative page number.
Changed GString::cmp and GString::cmpN to correctly handle '\0' chars
in the middle of strings.
-Corrected the handling of the 'extend' parameters in radial shadings.
+Fixed the radial shading code; corrected the handling of the 'extend'
+ parameters.
Added the gmallocn and greallocn functions.
Fixed a bug in the TIFF image component predictor which shows up with
components that are not 1 or 8 bits wide.
@@ -1626,3 +1627,136 @@ When converting a Type 1C glyph to a Type 1 glyph, insert closepath
Check for a sane 'loca' table in TrueType fonts (FoFiTrueType::parse).
Fix PSOutputDev to correctly handle the case of an empty name in a
font encoding.
+
+3.02 (2007-feb-27)
+------------------
+Added anti-aliasing for vector graphics; added the vectorAntialias
+ xpdfrc option; added the "-aaVector" switch to xpdf and pdftoppm.
+Implemented stroke adjustment (always enabled by default, ignoring the
+ SA parameter, to match Adobe's behavior), and added the strokeAdjust
+ xpdfrc command.
+Support PDF 1.6 and PDF 1.7.
+Added support for AES decryption.
+Added support for OpenType fonts (only tested with 8-bit CFF data so
+ far).
+Added user-configurable key/mouse bindings - the bind/unbind xpdfrc
+ commands.
+Cleaned up the full-screen mode code and added the ability to toggle
+ it on the fly (the default key binding is alt-f).
+Pdfimages with the -j option now writes JPEG files for 1-component
+ (grayscale) DCT images, in addition to 3-component (RGB) images.
+Fixed bugs in handling sampled (type 0) functions with 32-bit
+ samples.
+Fixed some things to support DeviceN color spaces with up to 32
+ colorants.
+Pdftops now constructs the %%Creator and %%Title DSC comments from the
+ relevant information in the PDF Info dictionary.
+Tweak the TrueType font encoding deciphering algorithm.
+Added the "mapUnkownCharNames" xpdfrc option.
+Fix a bug (that only showed up with certain window managers) in the
+ intermediate resize event optimization. [Thanks to Michael Rogers.]
+Check for a broken/missing embedded font (this was causing xpdf to
+ crash).
+Added support for transfer functions in PostScript output.
+Be a bit more tolerant of Link destinations that contain null values
+ for positioning parameters.
+Use ordered dot dithering instead of clustered dot dithering at
+ resolutions below 300 dpi (for monochrome output).
+Fixed security holes (bounds checking issues) in several places.
+Don't bother creating a SplashFont (allocating memory) for fonts that
+ are only used for hidden text - this avoids problems with fonts of
+ unreasonably large sizes.
+Clipping in TextOutputDev was off for characters on the left edge of
+ the page.
+The scn and SCN operators weren't correctly handling colors with more
+ than four components.
+FoFiType1::writeEncoded wasn't always correctly finding the end of the
+ encoding.
+Use the ColorTransform parameter in the DCTDecode stream dictionary.
+Type 3 fonts are allowed to have a bbox of [0 0 0 0], which means
+ "unspecified" -- don't issue error messages in that case.
+Perform the transform (to device space) in Splash instead of in
+ SplashOutputDev -- this is needed to correctly handle round joins
+ and caps on stroked paths.
+PSOutputDev now rasterizes any pages that use transparency.
+Limit the crop, bleed, trim, and art boxes to the edges of the media
+ box (per the PDF spec).
+Change GString to increase the allocation increment by powers of two.
+Handle whitespace in hex strings in CMap files/streams.
+Use strings instead of names for separation colorant names in
+ PSOutputDev.
+For explicitly masked images where the mask is higher resolution than
+ the image, use the soft mask code.
+Avoid problems with very large x-steps in the PostScript output for
+ tiling pattern fills.
+Avoid a divide-by-zero in stitching functions which have a subfunction
+ with empty bounds.
+Honor the "Hidden", "NoView", and "Print" flags on annotations.
+Rewrote the pixel rendering code in Splash to use a single set of
+ pixel pipeline functions.
+Added support for transparency groups and soft masks.
+Fixed the transparency blend functions to match the addendum published
+ by Adobe.
+Changed Splash/SplashBitmap to store alpha in a separate plane.
+Setting the color space now selects the correct default color for that
+ color space.
+Remove the mutex lock from GlobalParams::getErrQuiet() to avoid a
+ deadlock when parseCIDToUnicode() or parseUnicodeToUnicode() calls
+ it from inside a locked section.
+Added error checking (on the argument count) in the sc/SC/scn/SCN
+ operators.
+Skip over notdef glyphs in TrueType fonts (which sometimes get drawn
+ as little boxes), to match Adobe's behavior.
+Painting operations in a Separation color space with the "None"
+ colorant or a DeviceN color space with all colorants set to "None"
+ never mark the page.
+Fixed an obscure bug in the JPX decoder - it wasn't reading the extra
+ stuffing byte in the case where the last byte of a packet header was
+ 0xff.
+Change the TrueType font parser (FoFiTrueType) to change the glyph
+ count rather than report an error if the 'loca' table is too small.
+Fixed a couple of bugs in the JBIG2 decoder.
+Added stochastic clustered dot dithering.
+Added the screenType, screenSize, screenDotRadius, screenGamma,
+ screenBlackThreshold, and screenWhiteThreshold xpdfrc settings.
+PSOutputDev now correctly handles invalid Type 3 charprocs which don't
+ start with a d0 or d1 operator
+FreeType 2.2.x support - get rid of the FT_INTERNAL_OBJECTS_H include,
+ and add some 'const' declarations.
+Handle PDFDocEncoding in Info dictionary strings.
+Tweak the xref repair code - ignore whitespace at the start of lines
+ when looking for objects.
+Added the "-exec" switch to xpdf.
+Removed the xpdf.viKeys X resource.
+Changed the color key / explicit masked image code in PSOutputDev to
+ generate better PS code, including a Level 3 option.
+Tweaked the DEBUG_MEM code for performance.
+Move the JBIG2 global stream reading code into reset() instead of the
+ constructor - this way, pdftotext doesn't end up reading the global
+ stream.
+Added the "-preload" option to pdftops and the psPreload xpdfrc
+ command.
+Added the "zoom to selection" command (on the popup menu).
+Fix a bug (in xpdf/pdftoppm/pdftops) with tiling patterns whose bbox
+ size is different from their xStep/yStep.
+Implemented stroke with pattern color spaces.
+Following a link to a page whose CropBox was different from the
+ MediaBox was resulting in an incorrect scroll position.
+Parse truncated date strings from the Info dictionary correctly.
+Change FoFiType1 to handle Type 1 fonts with two /Encoding keys.
+Extend the PSOutputDev shaded fill code to handle DeviceCMYK shaded
+ fills in level2sep and level3sep modes.
+Detect infinite loops in the Page tree.
+Optimized the ASCII85Encoder code.
+Tweaked the text extractor to do a better job of lining up rows of
+ text.
+Leave images compressed (or re-compress them with RLE) in PostScript
+ output when setting up images for forms and Type 3 fonts (or with
+ -preload).
+Extend FoFiType1 to handle Type 1 fonts with octal character codes in
+ their encodings.
+Use a custom string formatter to avoid problems with locale-based decimal
+ formatting (commas instead of periods) in PS output.
+Allow comments in PostScript-type functions.
+Change the TrueType font parser (FoFiTrueType) to delete glyf table
+ entries that are too short.
diff --git a/Build/source/libs/xpdf/INSTALL b/Build/source/libs/xpdf/INSTALL
index 10036518c6f..6c6db871129 100644
--- a/Build/source/libs/xpdf/INSTALL
+++ b/Build/source/libs/xpdf/INSTALL
@@ -1,11 +1,11 @@
Xpdf
====
-version 3.01
-2005-aug-17
+version 3.02
+2007-feb-27
The Xpdf software and documentation are
-copyright 1996-2005 Glyph & Cog, LLC.
+copyright 1996-2007 Glyph & Cog, LLC.
Email: derekn@foolabs.com
WWW: http://www.foolabs.com/xpdf/
diff --git a/Build/source/libs/xpdf/README b/Build/source/libs/xpdf/README
index 5fb5b104c31..71fd62e319d 100644
--- a/Build/source/libs/xpdf/README
+++ b/Build/source/libs/xpdf/README
@@ -1,17 +1,17 @@
Xpdf
====
-version 3.01
-2005-aug-17
+version 3.02
+2007-feb-27
The Xpdf software and documentation are
-copyright 1996-2005 Glyph & Cog, LLC.
+copyright 1996-2007 Glyph & Cog, LLC.
Email: derekn@foolabs.com
WWW: http://www.foolabs.com/xpdf/
The PDF data structures, operators, and specification are
-copyright 1985-2004 Adobe Systems Inc.
+copyright 1985-2006 Adobe Systems Inc.
What is Xpdf?
@@ -204,10 +204,15 @@ pdftex project:
References
----------
-Adobe Systems Inc., _PDF Reference: Adobe Portable Document Format
-Version 1.6_.
-http://partners.adobe.com/public/developer/pdf/index_reference.html
-[The manual for PDF version 1.6.]
+Adobe Systems Inc., _PDF Reference, sixth edition: Adobe Portable
+Document Format version 1.7_.
+http://www.adobe.com/devnet/pdf/pdf_reference.html
+[The manual for PDF version 1.7.]
+
+Adobe Systems Inc., "Errata for the PDF Reference, sixth edition,
+version 1.7", October 16, 2006.
+http://www.adobe.com/devnet/pdf/pdf_reference.html
+[The errata for the PDF 1.7 spec.]
Adobe Systems Inc., _PostScript Language Reference_, 3rd ed.
Addison-Wesley, 1999, ISBN 0-201-37922-8.
@@ -262,6 +267,10 @@ http://partners.adobe.com/asn/developer/type/corporateuse.txt
http://partners.adobe.com/asn/developer/type/zapfdingbats.txt
[Mappings between character names to Unicode.]
+Adobe Systems Inc., OpenType Specification v. 1.4.
+http://partners.adobe.com/public/developer/opentype/index_spec.html
+[The OpenType font format spec.]
+
Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_. 1993.
http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf
@@ -271,7 +280,7 @@ ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz
[This is the algorithm used to encrypt PDF files.]
T. Boutell, et al., "PNG (Portable Network Graphics) Specification,
-Version 1.0. RFC 2083.
+Version 1.0". RFC 2083.
[PDF uses the PNG filter algorithms.]
CCITT, "Information Technology - Digital Compression and Coding of
@@ -296,6 +305,15 @@ version 1.3". RFC 1951.
[The definition of the compression algorithm used in FlateDecode
streams.]
+Morris Dworkin, "Recommendation for Block Cipher Modes of Operation",
+National Institute of Standards, NIST Special Publication 800-38A,
+2001.
+[The cipher block chaining (CBC) mode used with AES in PDF files.]
+
+Federal Information Processing Standards Publication 197 (FIPS PUBS
+197), "Advanced Encryption Standard (AES)", November 26, 2001.
+[AES encryption, used in PDF 1.6.]
+
Jim Flowers, "X Logical Font Description Conventions", Version 1.5, X
Consortium Standard, X Version 11, Release 6.1.
ftp://ftp.x.org/pub/R6.1/xc/doc/hardcopy/XLFD/xlfd.PS.Z
@@ -333,6 +351,10 @@ http://www.itu.int/
[The official Group 3 and 4 fax standards - used by the CCITTFaxDecode
stream, as well as the JBIG2Decode stream.]
+B. Kaliski, "PKCS #5: Password-Based Cryptography Specification,
+Version 2.0". RFC 2898.
+[Defines the padding scheme used with AES encryption in PDF files.]
+
Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, "Practical
Fast 1-D DCT Algorithms with 11 Multiplications". IEEE Intl. Conf. on
Acoustics, Speech & Signal Processing, 1989, 988-991.
@@ -342,10 +364,11 @@ Microsoft, _TrueType 1.0 Font Files_, rev. 1.66. 1995.
http://www.microsoft.com/typography/tt/tt.htm
[The TrueType font spec (in MS Word format, naturally).]
-Thai Industrial Standard, "Standard for Thai Character Codes for
-Computers", TIS-620-2533 (1990).
-http://www.nectec.or.th/it-standards/std620/std620.htm
-[The TIS-620 Thai encoding.]
+V. Ostromoukhov, R.D. Hersch, "Stochastic Clustered-Dot Dithering",
+Conf. Color Imaging: Device-Independent Color, Color Hardcopy, and
+Graphic Arts IV, 1999, SPIE Vol. 3648, 496-505.
+http://diwww.epfl.ch/w3lsp/publications/colour/scd.html
+[The stochastic dithering algorithm used in Xpdf.]
P. Peterlin, "ISO 8859-2 (Latin 2) Resources".
http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html
@@ -359,6 +382,11 @@ http://www.inforamp.net/~poynton/ColorFAQ.html
R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321.
[MD5 is used in PDF document encryption.]
+Thai Industrial Standard, "Standard for Thai Character Codes for
+Computers", TIS-620-2533 (1990).
+http://www.nectec.or.th/it-standards/std620/std620.htm
+[The TIS-620 Thai encoding.]
+
Unicode Consortium, "Unicode Home Page".
http://www.unicode.org/
[Online copy of the Unicode spec.]
diff --git a/Build/source/libs/xpdf/aconf-win32.h b/Build/source/libs/xpdf/aconf-win32.h
index 60509334391..0bdc7636623 100644
--- a/Build/source/libs/xpdf/aconf-win32.h
+++ b/Build/source/libs/xpdf/aconf-win32.h
@@ -7,6 +7,8 @@
#ifndef ACONF_H
#define ACONF_H
+#include <aconf2.h>
+
/*
* Use A4 paper size instead of Letter for PostScript output.
*/
@@ -28,6 +30,21 @@
#define MULTITHREADED 1
/*
+ * Enable C++ exceptions.
+ */
+#define USE_EXCEPTIONS 1
+
+/*
+ * Enable word list support.
+ */
+#undef TEXTOUT_WORD_LIST
+
+/*
+ * Use fixed point (instead of floating point) arithmetic.
+ */
+#undef USE_FIXEDPOINT
+
+/*
* Directory with the Xpdf app-defaults file.
*/
#undef APPDEFDIR
@@ -50,8 +67,14 @@
#undef HAVE_BSTRING_H
#undef HAVE_POPEN
#undef HAVE_MKSTEMP
+#undef HAVE_MKSTEMPS
#undef SELECT_TAKES_INT
+#undef HAVE_FSEEKO
#undef HAVE_FSEEK64
+#undef _FILE_OFFSET_BITS
+#undef _LARGE_FILES
+#undef _LARGEFILE_SOURCE
+#undef HAVE_XTAPPSETEXITFLAG
/*
* This is defined if using libXpm.
@@ -79,4 +102,19 @@
*/
#undef HAVE_PAPER_H
+/*
+ * Enable support for loading plugins.
+ */
+#undef ENABLE_PLUGINS
+
+/*
+ * Defined if the Splash library is avaiable.
+ */
+#undef HAVE_SPLASH
+
+/*
+ * Enable support for CMYK output.
+ */
+#undef SPLASH_CMYK
+
#endif
diff --git a/Build/source/libs/xpdf/aconf.h.in b/Build/source/libs/xpdf/aconf.h.in
index b7928fb3fc2..b6c63518f53 100644
--- a/Build/source/libs/xpdf/aconf.h.in
+++ b/Build/source/libs/xpdf/aconf.h.in
@@ -30,11 +30,21 @@
#undef MULTITHREADED
/*
+ * Enable C++ exceptions.
+ */
+#undef USE_EXCEPTIONS
+
+/*
* Enable word list support.
*/
#undef TEXTOUT_WORD_LIST
/*
+ * Use fixed point (instead of floating point) arithmetic.
+ */
+#undef USE_FIXEDPOINT
+
+/*
* Directory with the Xpdf app-defaults file.
*/
#undef APPDEFDIR
@@ -87,4 +97,19 @@
*/
#undef HAVE_PAPER_H
+/*
+ * Enable support for loading plugins.
+ */
+#undef ENABLE_PLUGINS
+
+/*
+ * Defined if the Splash library is avaiable.
+ */
+#undef HAVE_SPLASH
+
+/*
+ * Enable support for CMYK output.
+ */
+#undef SPLASH_CMYK
+
#endif
diff --git a/Build/source/libs/xpdf/dj_make.bat b/Build/source/libs/xpdf/dj_make.bat
index 37f360359df..d01b7928c63 100644
--- a/Build/source/libs/xpdf/dj_make.bat
+++ b/Build/source/libs/xpdf/dj_make.bat
@@ -1,5 +1,5 @@
set CC=gcc
-set CFLAGS=-g -O2 -I.. -I..\goo
+set CFLAGS=-g -O2 -I.. -I..\fofi -I..\goo
set CXX=gpp
set CXXFLAGS=%CFLAGS%
set LIBPROG=ar
@@ -10,9 +10,9 @@ 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 gmem.c
%CC% %CFLAGS% -c parseargs.c
del libGoo.a
%LIBPROG% -rc libGoo.a GHash.o GList.o GString.o gmempp.o gfile.o gmem.o parseargs.o
@@ -59,6 +59,7 @@ del *.o
%CXX% %CXXFLAGS% -c PSTokenizer.cc
%CXX% %CXXFLAGS% -c Page.cc
%CXX% %CXXFLAGS% -c Parser.cc
+%CXX% %CXXFLAGS% -c SecurityHandler.cc
%CXX% %CXXFLAGS% -c Stream.cc
%CXX% %CXXFLAGS% -c TextOutputDev.cc
%CXX% %CXXFLAGS% -c UnicodeMap.cc
@@ -67,16 +68,14 @@ del *.o
del libxpdf.a
%LIBPROG% -rc libxpdf.a *.o
-%CXX% %CXXFLAGS% -o pdftops.exe pdftops.cc libxpdf.a ..\goo\libGoo.a
+%CXX% %CXXFLAGS% -o pdftops.exe pdftops.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
-%CXX% %CXXFLAGS% -o pdftotext.exe pdftotext.cc libxpdf.a ..\goo\libGoo.a
+%CXX% %CXXFLAGS% -o pdftotext.exe pdftotext.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
-%CXX% %CXXFLAGS% -o pdfinfo.exe pdfinfo.cc libxpdf.a ..\goo\libGoo.a
+%CXX% %CXXFLAGS% -o pdfinfo.exe pdfinfo.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
-%CXX% %CXXFLAGS% -o pdffonts.exe pdffonts.cc libxpdf.a ..\goo\libGoo.a
+%CXX% %CXXFLAGS% -o pdffonts.exe pdffonts.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
-%CXX% %CXXFLAGS% -o pdfimages.exe pdfimages.cc libxpdf.a ..\goo\libGoo.a
-
-%CXX% %CXXFLAGS% -o pdftoppm.exe pdftoppm.cc libxpdf.a ..\goo\libGoo.a
+%CXX% %CXXFLAGS% -o pdfimages.exe pdfimages.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a
cd ..
diff --git a/Build/source/libs/xpdf/fofi/FoFiTrueType.cc b/Build/source/libs/xpdf/fofi/FoFiTrueType.cc
index 46b61ec3979..f8a1aa3478e 100644
--- a/Build/source/libs/xpdf/fofi/FoFiTrueType.cc
+++ b/Build/source/libs/xpdf/fofi/FoFiTrueType.cc
@@ -18,6 +18,7 @@
#include "gmem.h"
#include "GString.h"
#include "GHash.h"
+#include "FoFiType1C.h"
#include "FoFiTrueType.h"
//
@@ -108,8 +109,11 @@ struct TrueTypeLoca {
#define cmapTag 0x636d6170
#define glyfTag 0x676c7966
#define headTag 0x68656164
+#define hheaTag 0x68686561
+#define hmtxTag 0x686d7478
#define locaTag 0x6c6f6361
#define nameTag 0x6e616d65
+#define os2Tag 0x4f532f32
#define postTag 0x706f7374
static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
@@ -391,6 +395,28 @@ int FoFiTrueType::mapNameToGID(char *name) {
return nameToGID->lookupInt(name);
}
+Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
+ FoFiType1C *ff;
+ Gushort *map;
+ int i;
+
+ *nCIDs = 0;
+ if (!openTypeCFF) {
+ return NULL;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return NULL;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return NULL;
+ }
+ map = ff->getCIDToGIDMap(nCIDs);
+ delete ff;
+ return map;
+}
+
int FoFiTrueType::getEmbeddingRights() {
int i, fsType;
GBool ok;
@@ -419,13 +445,19 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding,
Gushort *codeToGID,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[512];
+ GString *buf;
GBool ok;
+ if (openTypeCFF) {
+ return;
+ }
+
// write the header
ok = gTrue;
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("%!PS-TrueTypeFont-{0:2g}\n",
+ (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
// begin the font dictionary
(*outputFunc)(outputStream, "10 dict begin\n", 14);
@@ -434,9 +466,10 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding,
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
// write the guts of the dictionary
@@ -448,20 +481,47 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding,
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}
+void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
+ GBool ascii, FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ FoFiType1C *ff;
+ int i;
+
+ if (!openTypeCFF) {
+ return;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return;
+ }
+ ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
+ delete ff;
+}
+
void FoFiTrueType::convertToCIDType2(char *psName,
Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[512];
+ GString *buf;
Gushort cid;
GBool ok;
int i, j, k;
+ if (openTypeCFF) {
+ return;
+ }
+
// write the header
ok = gTrue;
- sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("%!PS-TrueTypeFont-{0:2g}\n",
+ (double)getS32BE(0, &ok) / 65536.0);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
// begin the font dictionary
(*outputFunc)(outputStream, "20 dict begin\n", 14);
@@ -477,8 +537,9 @@ void FoFiTrueType::convertToCIDType2(char *psName,
(*outputFunc)(outputStream, " end def\n", 10);
(*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
if (cidMap) {
- sprintf(buf, "/CIDCount %d def\n", nCIDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/CIDCount {0:d} def\n", nCIDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
if (nCIDs > 32767) {
(*outputFunc)(outputStream, "/CIDMap [", 9);
for (i = 0; i < nCIDs; i += 32768 - 16) {
@@ -487,8 +548,10 @@ void FoFiTrueType::convertToCIDType2(char *psName,
(*outputFunc)(outputStream, " ", 2);
for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
cid = cidMap[i+j+k];
- sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:02x}{1:02x}",
+ (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "\n", 1);
}
@@ -502,8 +565,10 @@ void FoFiTrueType::convertToCIDType2(char *psName,
(*outputFunc)(outputStream, " ", 2);
for (j = 0; j < 16 && i+j < nCIDs; ++j) {
cid = cidMap[i+j];
- sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:02x}{1:02x}",
+ (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "\n", 1);
}
@@ -511,27 +576,34 @@ void FoFiTrueType::convertToCIDType2(char *psName,
}
} else {
// direct mapping - just fill the string(s) with s[i]=i
- sprintf(buf, "/CIDCount %d def\n", nGlyphs);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/CIDCount {0:d} def\n", nGlyphs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
if (nGlyphs > 32767) {
(*outputFunc)(outputStream, "/CIDMap [\n", 10);
for (i = 0; i < nGlyphs; i += 32767) {
j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
- sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
- " 255 and put\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format(" {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format(" 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
+ i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format(" 1 index exch dup 2 mul 1 add exch {0:d} add"
+ " 255 and put\n", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, " } for\n", 8);
}
(*outputFunc)(outputStream, "] def\n", 6);
} else {
- sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/CIDMap {0:d} string\n", 2 * nGlyphs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format(" 0 1 {0:d} {{\n", nGlyphs - 1);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream,
" 2 copy dup 2 mul exch -8 bitshift put\n", 42);
(*outputFunc)(outputStream,
@@ -541,9 +613,10 @@ void FoFiTrueType::convertToCIDType2(char *psName,
}
}
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
(*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
(*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
@@ -559,14 +632,39 @@ void FoFiTrueType::convertToCIDType2(char *psName,
56);
}
+void FoFiTrueType::convertToCIDType0(char *psName,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ FoFiType1C *ff;
+ int i;
+
+ if (!openTypeCFF) {
+ return;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return;
+ }
+ ff->convertToCIDType0(psName, outputFunc, outputStream);
+ delete ff;
+}
+
void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[512];
+ GString *buf;
GString *sfntsName;
int n, i, j;
+ if (openTypeCFF) {
+ return;
+ }
+
// write the Type 42 sfnts array
sfntsName = (new GString(psName))->append("_sfnts");
cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
@@ -578,28 +676,33 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
(*outputFunc)(outputStream, "10 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
(*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x def\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("_{0:02x} def\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
- sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
- bbox[0], bbox[1], bbox[2], bbox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
(*outputFunc)(outputStream, "/sfnts ", 7);
(*outputFunc)(outputStream, psName, strlen(psName));
(*outputFunc)(outputStream, "_sfnts def\n", 11);
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
for (j = 0; j < 256 && i+j < n; ++j) {
- sprintf(buf, "dup %d /c%02x put\n", j, j);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "readonly def\n", 13);
(*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
(*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
for (j = 0; j < 256 && i+j < n; ++j) {
- sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/c{0:02x} {1:d} def\n",
+ j, cidMap ? cidMap[i+j] : i+j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "end readonly def\n", 17);
(*outputFunc)(outputStream,
@@ -616,21 +719,44 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
(*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
(*outputFunc)(outputStream, "/Encoding [\n", 12);
for (i = 0; i < n; i += 256) {
- sprintf(buf, "%d\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:d}\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
(*outputFunc)(outputStream, "/FDepVector [\n", 14);
for (i = 0; i < n; i += 256) {
(*outputFunc)(outputStream, "/", 1);
(*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x findfont\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("_{0:02x} findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}
+void FoFiTrueType::convertToType0(char *psName,
+ FoFiOutputFunc outputFunc,
+ void *outputStream) {
+ FoFiType1C *ff;
+ int i;
+
+ if (!openTypeCFF) {
+ return;
+ }
+ i = seekTable("CFF ");
+ if (!checkRegion(tables[i].offset, tables[i].len)) {
+ return;
+ }
+ if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
+ tables[i].len))) {
+ return;
+ }
+ ff->convertToType0(psName, outputFunc, outputStream);
+ delete ff;
+}
+
void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
void *outputStream, char *name,
Gushort *codeToGID) {
@@ -672,12 +798,50 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
0, 0, 0, 0, // min Type 1 memory
0, 0, 0, 0 // max Type 1 memory
};
- GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
+ static char os2Tab[86] = {
+ 0, 1, // version
+ 0, 1, // xAvgCharWidth
+ 0, 0, // usWeightClass
+ 0, 0, // usWidthClass
+ 0, 0, // fsType
+ 0, 0, // ySubscriptXSize
+ 0, 0, // ySubscriptYSize
+ 0, 0, // ySubscriptXOffset
+ 0, 0, // ySubscriptYOffset
+ 0, 0, // ySuperscriptXSize
+ 0, 0, // ySuperscriptYSize
+ 0, 0, // ySuperscriptXOffset
+ 0, 0, // ySuperscriptYOffset
+ 0, 0, // yStrikeoutSize
+ 0, 0, // yStrikeoutPosition
+ 0, 0, // sFamilyClass
+ 0, 0, 0, 0, 0, // panose
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, // ulUnicodeRange1
+ 0, 0, 0, 0, // ulUnicodeRange2
+ 0, 0, 0, 0, // ulUnicodeRange3
+ 0, 0, 0, 0, // ulUnicodeRange4
+ 0, 0, 0, 0, // achVendID
+ 0, 0, // fsSelection
+ 0, 0, // usFirstCharIndex
+ 0, 0, // usLastCharIndex
+ 0, 0, // sTypoAscender
+ 0, 0, // sTypoDescender
+ 0, 0, // sTypoLineGap
+ 0, 0, // usWinAscent
+ 0, 0, // usWinDescent
+ 0, 0, 0, 0, // ulCodePageRange1
+ 0, 0, 0, 0 // ulCodePageRange2
+ };
+ GBool missingCmap, missingName, missingPost, missingOS2;
+ GBool unsortedLoca, badCmapLen, abbrevHMTX;
int nZeroLengthTables;
+ int nHMetrics, advWidth, lsb;
TrueTypeLoca *locaTable;
TrueTypeTable *newTables;
- char *newNameTab, *newCmapTab;
+ char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab;
int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
+ int newHHEALen, newHMTXLen;
Guint locaChecksum, glyfChecksum, fileChecksum;
char *tableDir;
char locaBuf[4], checksumBuf[4];
@@ -685,10 +849,20 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
Guint t;
int pos, i, j, k, n;
+ if (openTypeCFF) {
+ return;
+ }
+
// check for missing tables
+ // (Note: if the OS/2 table is missing, the Microsoft PCL5 driver
+ // will embed a PCL TrueType font with the pitch field set to zero,
+ // which apparently causes divide-by-zero errors. As far as I can
+ // tell, the only important field in the OS/2 table is
+ // xAvgCharWidth.)
missingCmap = (cmapIdx = seekTable("cmap")) < 0;
missingName = seekTable("name") < 0;
missingPost = seekTable("post") < 0;
+ missingOS2 = seekTable("OS/2") < 0;
// read the loca table, check to see if it's sorted
locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
@@ -705,6 +879,19 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
unsortedLoca = gTrue;
}
+ // glyph descriptions must be at least 12 bytes long (nContours,
+ // xMin, yMin, xMax, yMax, instructionLength - two bytes each);
+ // invalid glyph descriptions (even if they're never used) make
+ // Windows choke, so we work around that problem here (ideally,
+ // this would parse the glyph descriptions in the glyf table and
+ // remove any that were invalid, but this quick test is a decent
+ // start)
+ if (i > 0 &&
+ locaTable[i].origOffset - locaTable[i-1].origOffset > 0 &&
+ locaTable[i].origOffset - locaTable[i-1].origOffset < 12) {
+ locaTable[i-1].origOffset = locaTable[i].origOffset;
+ unsortedLoca = gTrue;
+ }
locaTable[i].idx = i;
}
@@ -732,9 +919,17 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
}
}
+ // check for an abbreviated hmtx table (this is completely legal,
+ // but confuses the Microsoft PCL5 printer driver, which generates
+ // embedded fonts with the pitch field set to zero)
+ i = seekTable("hhea");
+ nHMetrics = getU16BE(tables[i].offset + 34, &ok);
+ abbrevHMTX = nHMetrics < nGlyphs;
+
// if nothing is broken, just write the TTF file as is
- if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
- !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) {
+ if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
+ !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
+ !name && !codeToGID) {
(*outputFunc)(outputStream, (char *)file, len);
goto done1;
}
@@ -892,6 +1087,44 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
newCmapTab = NULL;
}
+ // generate the new hmtx table and the updated hhea table
+ if (abbrevHMTX) {
+ i = seekTable("hhea");
+ pos = tables[i].offset;
+ newHHEALen = 36;
+ newHHEATab = (char *)gmalloc(newHHEALen);
+ for (i = 0; i < newHHEALen; ++i) {
+ newHHEATab[i] = getU8(pos++, &ok);
+ }
+ newHHEATab[34] = nGlyphs >> 8;
+ newHHEATab[35] = nGlyphs & 0xff;
+ i = seekTable("hmtx");
+ pos = tables[i].offset;
+ newHMTXLen = 4 * nGlyphs;
+ newHMTXTab = (char *)gmalloc(newHMTXLen);
+ advWidth = 0;
+ for (i = 0; i < nHMetrics; ++i) {
+ advWidth = getU16BE(pos, &ok);
+ lsb = getU16BE(pos + 2, &ok);
+ pos += 4;
+ newHMTXTab[4*i ] = advWidth >> 8;
+ newHMTXTab[4*i + 1] = advWidth & 0xff;
+ newHMTXTab[4*i + 2] = lsb >> 8;
+ newHMTXTab[4*i + 3] = lsb & 0xff;
+ }
+ for (; i < nGlyphs; ++i) {
+ lsb = getU16BE(pos, &ok);
+ pos += 2;
+ newHMTXTab[4*i ] = advWidth >> 8;
+ newHMTXTab[4*i + 1] = advWidth & 0xff;
+ newHMTXTab[4*i + 2] = lsb >> 8;
+ newHMTXTab[4*i + 3] = lsb & 0xff;
+ }
+ } else {
+ newHHEATab = newHMTXTab = NULL;
+ newHHEALen = newHMTXLen = 0; // make gcc happy
+ }
+
// construct the new table directory:
// - keep all original tables with non-zero length
// - fix the cmap table's length, if necessary
@@ -901,7 +1134,7 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
// - (re)compute table checksums
nNewTables = nTables - nZeroLengthTables +
(missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
- (missingPost ? 1 : 0);
+ (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
j = 0;
for (i = 0; i < nTables; ++i) {
@@ -932,6 +1165,14 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
newTables[j].len = newNameLen;
newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
newNameLen);
+ } else if (newTables[j].tag == hheaTag && abbrevHMTX) {
+ newTables[j].len = newHHEALen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab,
+ newHHEALen);
+ } else if (newTables[j].tag == hmtxTag && abbrevHMTX) {
+ newTables[j].len = newHMTXLen;
+ newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab,
+ newHMTXLen);
}
++j;
}
@@ -969,6 +1210,13 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
newTables[j].len = sizeof(postTab);
++j;
}
+ if (missingOS2) {
+ newTables[j].tag = os2Tag;
+ newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab,
+ sizeof(os2Tab));
+ newTables[j].len = sizeof(os2Tab);
+ ++j;
+ }
qsort(newTables, nNewTables, sizeof(TrueTypeTable),
&cmpTrueTypeTableTag);
pos = 12 + nNewTables * 16;
@@ -1055,6 +1303,12 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
(*outputFunc)(outputStream, nameTab, newTables[i].len);
} else if (newTables[i].tag == postTag && missingPost) {
(*outputFunc)(outputStream, postTab, newTables[i].len);
+ } else if (newTables[i].tag == os2Tag && missingOS2) {
+ (*outputFunc)(outputStream, os2Tab, newTables[i].len);
+ } else if (newTables[i].tag == hheaTag && abbrevHMTX) {
+ (*outputFunc)(outputStream, newHHEATab, newTables[i].len);
+ } else if (newTables[i].tag == hmtxTag && abbrevHMTX) {
+ (*outputFunc)(outputStream, newHMTXTab, newTables[i].len);
} else if (newTables[i].tag == locaTag && unsortedLoca) {
for (j = 0; j <= nGlyphs; ++j) {
if (locaFmt) {
@@ -1102,6 +1356,8 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
}
}
+ gfree(newHMTXTab);
+ gfree(newHHEATab);
gfree(newCmapTab);
gfree(newNameTab);
gfree(tableDir);
@@ -1114,7 +1370,7 @@ void FoFiTrueType::cvtEncoding(char **encoding,
FoFiOutputFunc outputFunc,
void *outputStream) {
char *name;
- char buf[64];
+ GString *buf;
int i;
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
@@ -1123,15 +1379,17 @@ void FoFiTrueType::cvtEncoding(char **encoding,
if (!(name = encoding[i])) {
name = ".notdef";
}
- sprintf(buf, "dup %d /", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("dup {0:d} /", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, name, strlen(name));
(*outputFunc)(outputStream, " put\n", 5);
}
} else {
for (i = 0; i < 256; ++i) {
- sprintf(buf, "dup %d /c%02x put\n", i, i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("dup {0:d} /c{1:02x} put\n", i, i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
}
(*outputFunc)(outputStream, "readonly def\n", 13);
@@ -1142,7 +1400,8 @@ void FoFiTrueType::cvtCharStrings(char **encoding,
FoFiOutputFunc outputFunc,
void *outputStream) {
char *name;
- char buf[64], buf2[16];
+ GString *buf;
+ char buf2[16];
int i, k;
// always define '.notdef'
@@ -1177,8 +1436,9 @@ void FoFiTrueType::cvtCharStrings(char **encoding,
if (k > 0 && k < nGlyphs) {
(*outputFunc)(outputStream, "/", 1);
(*outputFunc)(outputStream, name, strlen(name));
- sprintf(buf, " %d def\n", k);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format(" {0:d} def\n", k);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
}
}
@@ -1481,14 +1741,15 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
void FoFiTrueType::dumpString(Guchar *s, int length,
FoFiOutputFunc outputFunc,
void *outputStream) {
- char buf[64];
+ GString *buf;
int pad, i, j;
(*outputFunc)(outputStream, "<", 1);
for (i = 0; i < length; i += 32) {
for (j = 0; j < 32 && i+j < length; ++j) {
- sprintf(buf, "%02X", s[i+j] & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:02x}", s[i+j] & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (i % (65536 - 32) == 65536 - 64) {
(*outputFunc)(outputStream, ">\n<", 3);
@@ -1537,7 +1798,7 @@ Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
void FoFiTrueType::parse() {
Guint topTag;
- int pos, i, j;
+ int pos, ver, i, j;
parsedOk = gTrue;
@@ -1555,6 +1816,13 @@ void FoFiTrueType::parse() {
pos = 0;
}
+ // check the sfnt version
+ ver = getU32BE(pos, &parsedOk);
+ if (!parsedOk) {
+ return;
+ }
+ openTypeCFF = ver == 0x4f54544f; // 'OTTO'
+
// read the table directory
nTables = getU16BE(pos + 4, &parsedOk);
if (!parsedOk) {
@@ -1581,10 +1849,11 @@ void FoFiTrueType::parse() {
// the Type 42 spec
if (seekTable("head") < 0 ||
seekTable("hhea") < 0 ||
- seekTable("loca") < 0 ||
seekTable("maxp") < 0 ||
- seekTable("glyf") < 0 ||
- seekTable("hmtx") < 0) {
+ seekTable("hmtx") < 0 ||
+ (!openTypeCFF && seekTable("loca") < 0) ||
+ (!openTypeCFF && seekTable("glyf") < 0) ||
+ (openTypeCFF && seekTable("CFF ") < 0)) {
parsedOk = gFalse;
return;
}
@@ -1633,23 +1902,28 @@ void FoFiTrueType::parse() {
// make sure the loca table is sane (correct length and entries are
// in bounds)
- i = seekTable("loca");
- if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
- parsedOk = gFalse;
- return;
- }
- for (j = 0; j <= nGlyphs; ++j) {
- if (locaFmt) {
- pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
- } else {
- pos = getU16BE(tables[i].offset + j*2, &parsedOk);
- }
- if (pos < 0 || pos > len) {
+ if (!openTypeCFF) {
+ i = seekTable("loca");
+ if (tables[i].len < 0) {
parsedOk = gFalse;
+ return;
+ }
+ if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
+ nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1;
+ }
+ for (j = 0; j <= nGlyphs; ++j) {
+ if (locaFmt) {
+ pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
+ } else {
+ pos = getU16BE(tables[i].offset + j*2, &parsedOk);
+ }
+ if (pos < 0 || pos > len) {
+ parsedOk = gFalse;
+ }
+ }
+ if (!parsedOk) {
+ return;
}
- }
- if (!parsedOk) {
- return;
}
// read the post table
diff --git a/Build/source/libs/xpdf/fofi/FoFiTrueType.h b/Build/source/libs/xpdf/fofi/FoFiTrueType.h
index f7b09d6c0ab..cf06ae78a9e 100644
--- a/Build/source/libs/xpdf/fofi/FoFiTrueType.h
+++ b/Build/source/libs/xpdf/fofi/FoFiTrueType.h
@@ -38,6 +38,10 @@ public:
virtual ~FoFiTrueType();
+ // Returns true if this an OpenType font containing CFF data, false
+ // if it's a TrueType font (or OpenType font with TrueType data).
+ GBool isOpenTypeCFF() { return openTypeCFF; }
+
// Return the number of cmaps defined by this font.
int getNumCmaps();
@@ -59,6 +63,11 @@ public:
// font does not have a post table.
int mapNameToGID(char *name);
+ // Return the mapping from CIDs to GIDs, and return the number of
+ // CIDs in *<nCIDs>. This is only useful for CID fonts. (Only
+ // useful for OpenType CFF fonts.)
+ Gushort *getCIDToGIDMap(int *nCIDs);
+
// Returns the least restrictive embedding licensing right (as
// defined by the TrueType spec):
// * 4: OS/2 table is missing or invalid
@@ -74,33 +83,57 @@ public:
// <encoding> array specifies the mapping from char codes to names.
// If <encoding> is NULL, the encoding is unknown or undefined. The
// <codeToGID> array specifies the mapping from char codes to GIDs.
+ // (Not useful for OpenType CFF fonts.)
void convertToType42(char *psName, char **encoding,
Gushort *codeToGID,
FoFiOutputFunc outputFunc, void *outputStream);
+ // Convert to a Type 1 font, suitable for embedding in a PostScript
+ // file. This is only useful with 8-bit fonts. If <newEncoding> is
+ // not NULL, it will be used in place of the encoding in the Type 1C
+ // font. If <ascii> is true the eexec section will be hex-encoded,
+ // otherwise it will be left as binary data. If <psName> is
+ // non-NULL, it will be used as the PostScript font name. (Only
+ // useful for OpenType CFF fonts.)
+ void convertToType1(char *psName, char **newEncoding, GBool ascii,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
// Convert to a Type 2 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name (so we don't need to depend on the 'name' table in the
// font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
- // entries.
+ // entries. (Not useful for OpenType CFF fonts.)
void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
+ // Convert to a Type 0 CIDFont, suitable for embedding in a
+ // PostScript file. <psName> will be used as the PostScript font
+ // name. (Only useful for OpenType CFF fonts.)
+ void convertToCIDType0(char *psName,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name (so we don't need to depend on the 'name'
// table in the font). The <cidMap> array maps CIDs to GIDs; it has
- // <nCIDs> entries.
+ // <nCIDs> entries. (Not useful for OpenType CFF fonts.)
void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. <psName> will be used as the
+ // PostScript font name. (Only useful for OpenType CFF fonts.)
+ void convertToType0(char *psName,
+ FoFiOutputFunc outputFunc, void *outputStream);
+
// Write a clean TTF file, filling in missing tables and correcting
// various other errors. If <name> is non-NULL, the font is renamed
// to <name>. If <codeToGID> is non-NULL, the font is re-encoded,
// using a Windows Unicode cmap. If <name> is NULL and the font is
- // complete and correct, it will be written unmodified.
+ // complete and correct, it will be written unmodified. (Not useful
+ // for OpenType CFF fonts.)
void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
char *name = NULL, Gushort *codeToGID = NULL);
@@ -133,6 +166,7 @@ private:
int locaFmt;
int bbox[4];
GHash *nameToGID;
+ GBool openTypeCFF;
GBool parsedOk;
};
diff --git a/Build/source/libs/xpdf/fofi/FoFiType1.cc b/Build/source/libs/xpdf/fofi/FoFiType1.cc
index 256639c1203..efad5ee4eb7 100644
--- a/Build/source/libs/xpdf/fofi/FoFiType1.cc
+++ b/Build/source/libs/xpdf/fofi/FoFiType1.cc
@@ -75,7 +75,7 @@ char **FoFiType1::getEncoding() {
void FoFiType1::writeEncoded(char **newEncoding,
FoFiOutputFunc outputFunc, void *outputStream) {
char buf[512];
- char *line;
+ char *line, *line2, *p;
int i;
// copy everything up to the encoding
@@ -101,19 +101,57 @@ void FoFiType1::writeEncoded(char **newEncoding,
}
(*outputFunc)(outputStream, "readonly def\n", 13);
- // copy everything after the encoding
+ // find the end of the encoding data
+ //~ this ought to parse PostScript tokens
if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line);
} else {
- for (line = getNextLine(line);
- line && strncmp(line, "readonly def", 12);
- line = getNextLine(line)) ;
- if (line) {
- line = getNextLine(line);
+ // skip "/Encoding" + one whitespace char,
+ // then look for 'def' preceded by PostScript whitespace
+ p = line + 10;
+ line = NULL;
+ for (; p < (char *)file + len; ++p) {
+ if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
+ *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
+ p + 4 <= (char *)file + len &&
+ !strncmp(p + 1, "def", 3)) {
+ line = p + 4;
+ break;
+ }
}
}
+
+ // some fonts have two /Encoding entries in their dictionary, so we
+ // check for a second one here
if (line) {
- (*outputFunc)(outputStream, line, ((char *)file + len) - line);
+ for (line2 = line, i = 0;
+ i < 20 && line2 && strncmp(line2, "/Encoding", 9);
+ line2 = getNextLine(line2), ++i) ;
+ if (i < 20 && line2) {
+ (*outputFunc)(outputStream, line, line2 - line);
+ if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
+ line = getNextLine(line2);
+ } else {
+ // skip "/Encoding" + one whitespace char,
+ // then look for 'def' preceded by PostScript whitespace
+ p = line2 + 10;
+ line = NULL;
+ for (; p < (char *)file + len; ++p) {
+ if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
+ *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
+ p + 4 <= (char *)file + len &&
+ !strncmp(p + 1, "def", 3)) {
+ line = p + 4;
+ break;
+ }
+ }
+ }
+ }
+
+ // copy everything after the encoding
+ if (line) {
+ (*outputFunc)(outputStream, line, ((char *)file + len) - line);
+ }
}
}
@@ -178,8 +216,15 @@ void FoFiType1::parse() {
if (*p2) {
c = *p2;
*p2 = '\0';
- if ((code = atoi(p)) < 256) {
- *p2 = c;
+ code = atoi(p);
+ *p2 = c;
+ if (code == 8 && *p2 == '#') {
+ code = 0;
+ for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
+ code = code * 8 + (*p2 - '0');
+ }
+ }
+ if (code < 256) {
for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
if (*p == '/') {
++p;
diff --git a/Build/source/libs/xpdf/fofi/FoFiType1C.cc b/Build/source/libs/xpdf/fofi/FoFiType1C.cc
index 499414bea2a..3b28f3210c8 100644
--- a/Build/source/libs/xpdf/fofi/FoFiType1C.cc
+++ b/Build/source/libs/xpdf/fofi/FoFiType1C.cc
@@ -129,24 +129,33 @@ Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
return map;
}
-void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
+void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc,
void *outputStream) {
+ int psNameLen;
Type1CEexecBuf eb;
Type1CIndex subrIdx;
Type1CIndexVal val;
- char buf[512];
+ GString *buf;
+ char buf2[256];
char **enc;
GBool ok;
int i;
+ if (psName) {
+ psNameLen = strlen(psName);
+ } else {
+ psName = name->getCString();
+ psNameLen = name->getLength();
+ }
+
// write header and font dictionary, up to encoding
ok = gTrue;
(*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
- (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, psName, psNameLen);
if (topDict.versionSID != 0) {
- getString(topDict.versionSID, buf, &ok);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ getString(topDict.versionSID, buf2, &ok);
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
}
(*outputFunc)(outputStream, "\n", 1);
// the dictionary needs room for 12 entries: the following 9, plus
@@ -156,37 +165,37 @@ void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
(*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
if (topDict.versionSID != 0) {
(*outputFunc)(outputStream, "/version (", 10);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") readonly def\n", 15);
}
if (topDict.noticeSID != 0) {
- getString(topDict.noticeSID, buf, &ok);
+ getString(topDict.noticeSID, buf2, &ok);
(*outputFunc)(outputStream, "/Notice (", 9);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") readonly def\n", 15);
}
if (topDict.copyrightSID != 0) {
- getString(topDict.copyrightSID, buf, &ok);
+ getString(topDict.copyrightSID, buf2, &ok);
(*outputFunc)(outputStream, "/Copyright (", 12);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") readonly def\n", 15);
}
if (topDict.fullNameSID != 0) {
- getString(topDict.fullNameSID, buf, &ok);
+ getString(topDict.fullNameSID, buf2, &ok);
(*outputFunc)(outputStream, "/FullName (", 11);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") readonly def\n", 15);
}
if (topDict.familyNameSID != 0) {
- getString(topDict.familyNameSID, buf, &ok);
+ getString(topDict.familyNameSID, buf2, &ok);
(*outputFunc)(outputStream, "/FamilyName (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") readonly def\n", 15);
}
if (topDict.weightSID != 0) {
- getString(topDict.weightSID, buf, &ok);
+ getString(topDict.weightSID, buf2, &ok);
(*outputFunc)(outputStream, "/Weight (", 9);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") readonly def\n", 15);
}
if (topDict.isFixedPitch) {
@@ -194,32 +203,43 @@ void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
} else {
(*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
}
- sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/UnderlinePosition {0:.4g} def\n",
+ topDict.underlinePosition);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/UnderlineThickness {0:.4g} def\n",
+ topDict.underlineThickness);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "end readonly def\n", 17);
(*outputFunc)(outputStream, "/FontName /", 11);
- (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, psName, psNameLen);
(*outputFunc)(outputStream, " def\n", 5);
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FontType 1 def\n", 16);
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
- topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
- topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
- topDict.fontBBox[0], topDict.fontBBox[1],
- topDict.fontBBox[2], topDict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
if (topDict.uniqueID != 0) {
- sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
// write the encoding
@@ -233,8 +253,9 @@ void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
enc = newEncoding ? newEncoding : encoding;
for (i = 0; i < 256; ++i) {
if (enc[i]) {
- sprintf(buf, "dup %d /%s put\n", i, enc[i]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
}
(*outputFunc)(outputStream, "readonly def\n", 13);
@@ -261,89 +282,112 @@ void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
if (privateDicts[0].nBlueValues) {
eexecWrite(&eb, "/BlueValues [");
for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}",
+ i > 0 ? " " : "", privateDicts[0].blueValues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[0].nOtherBlues) {
eexecWrite(&eb, "/OtherBlues [");
for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}",
+ i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[0].nFamilyBlues) {
eexecWrite(&eb, "/FamilyBlues [");
for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}",
+ i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[0].nFamilyOtherBlues) {
eexecWrite(&eb, "/FamilyOtherBlues [");
for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
- sprintf(buf, "%s%d", i > 0 ? " " : "",
- privateDicts[0].familyOtherBlues[i]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "",
+ privateDicts[0].familyOtherBlues[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[0].blueScale != 0.039625) {
- sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
- eexecWrite(&eb, buf);
+ buf = GString::format("/BlueScale {0:.4g} def\n",
+ privateDicts[0].blueScale);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].blueShift != 7) {
- sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
- eexecWrite(&eb, buf);
+ buf = GString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].blueFuzz != 1) {
- sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
- eexecWrite(&eb, buf);
+ buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].hasStdHW) {
- sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
- eexecWrite(&eb, buf);
+ buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].hasStdVW) {
- sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
- eexecWrite(&eb, buf);
+ buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].nStemSnapH) {
eexecWrite(&eb, "/StemSnapH [");
for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
- sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:.4g}",
+ i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[0].nStemSnapV) {
eexecWrite(&eb, "/StemSnapV [");
for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
- sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:.4g}",
+ i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[0].hasForceBold) {
- sprintf(buf, "/ForceBold %s def\n",
- privateDicts[0].forceBold ? "true" : "false");
- eexecWrite(&eb, buf);
+ buf = GString::format("/ForceBold {0:s} def\n",
+ privateDicts[0].forceBold ? "true" : "false");
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].forceBoldThreshold != 0) {
- sprintf(buf, "/ForceBoldThreshold %g def\n",
- privateDicts[0].forceBoldThreshold);
- eexecWrite(&eb, buf);
+ buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
+ privateDicts[0].forceBoldThreshold);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].languageGroup != 0) {
- sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
- eexecWrite(&eb, buf);
+ buf = GString::format("/LanguageGroup {0:d} def\n",
+ privateDicts[0].languageGroup);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[0].expansionFactor != 0.06) {
- sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
- eexecWrite(&eb, buf);
+ buf = GString::format("/ExpansionFactor {0:.4g} def\n",
+ privateDicts[0].expansionFactor);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
// set up subroutines
@@ -354,15 +398,17 @@ void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
}
// write the CharStrings
- sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
- eexecWrite(&eb, buf);
+ buf = GString::format("2 index /CharStrings {0:d} dict dup begin\n",
+ nGlyphs);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
for (i = 0; i < nGlyphs; ++i) {
ok = gTrue;
getIndexVal(&charStringsIdx, i, &val, &ok);
if (ok) {
- getString(charset[i], buf, &ok);
+ getString(charset[i], buf2, &ok);
if (ok) {
- eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
+ eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
}
}
}
@@ -392,7 +438,8 @@ void FoFiType1C::convertToCIDType0(char *psName,
Type1CIndex subrIdx;
Type1CIndexVal val;
int nCIDs, gdBytes;
- char buf[512], buf2[512];
+ GString *buf;
+ char buf2[256];
GBool ok;
int gid, offset, n, i, j, k;
@@ -456,169 +503,204 @@ void FoFiType1C::convertToCIDType0(char *psName,
(*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
ok = gTrue;
- getString(topDict.registrySID, buf, &ok);
+ getString(topDict.registrySID, buf2, &ok);
if (ok) {
(*outputFunc)(outputStream, " /Registry (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") def\n", 6);
}
ok = gTrue;
- getString(topDict.orderingSID, buf, &ok);
+ getString(topDict.orderingSID, buf2, &ok);
if (ok) {
(*outputFunc)(outputStream, " /Ordering (", 13);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, buf2, strlen(buf2));
(*outputFunc)(outputStream, ") def\n", 6);
}
} else {
(*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
(*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
}
- sprintf(buf, " /Supplement %d def\n", topDict.supplement);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format(" /Supplement {0:d} def\n", topDict.supplement);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "end def\n", 8);
if (topDict.hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- topDict.fontMatrix[0], topDict.fontMatrix[1],
- topDict.fontMatrix[2], topDict.fontMatrix[3],
- topDict.fontMatrix[4], topDict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
} else if (privateDicts[0].hasFontMatrix) {
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
} else {
(*outputFunc)(outputStream,
"/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
}
- sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
- topDict.fontBBox[0], topDict.fontBBox[1],
- topDict.fontBBox[2], topDict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
(*outputFunc)(outputStream, " /FSType 8 def\n", 16);
(*outputFunc)(outputStream, "end def\n", 8);
// CIDFont-specific entries
- sprintf(buf, "/CIDCount %d def\n", nCIDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/CIDCount {0:d} def\n", nCIDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
- sprintf(buf, "/GDBytes %d def\n", gdBytes);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/GDBytes {0:d} def\n", gdBytes);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
if (topDict.paintType != 0) {
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
// FDArray entry
- sprintf(buf, "/FDArray %d array\n", nFDs);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FDArray {0:d} array\n", nFDs);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
for (i = 0; i < nFDs; ++i) {
- sprintf(buf, "dup %d 10 dict begin\n", i);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("dup {0:d} 10 dict begin\n", i);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FontType 1 def\n", 16);
if (privateDicts[i].hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- privateDicts[i].fontMatrix[0],
- privateDicts[i].fontMatrix[1],
- privateDicts[i].fontMatrix[2],
- privateDicts[i].fontMatrix[3],
- privateDicts[i].fontMatrix[4],
- privateDicts[i].fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ privateDicts[i].fontMatrix[0],
+ privateDicts[i].fontMatrix[1],
+ privateDicts[i].fontMatrix[2],
+ privateDicts[i].fontMatrix[3],
+ privateDicts[i].fontMatrix[4],
+ privateDicts[i].fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
} else {
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
}
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
if (privateDicts[i].nBlueValues) {
(*outputFunc)(outputStream, "/BlueValues [", 13);
for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:s}{1:d}",
+ j > 0 ? " " : "", privateDicts[i].blueValues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
}
if (privateDicts[i].nOtherBlues) {
(*outputFunc)(outputStream, "/OtherBlues [", 13);
for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:s}{1:d}",
+ j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
}
if (privateDicts[i].nFamilyBlues) {
(*outputFunc)(outputStream, "/FamilyBlues [", 14);
for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:s}{1:d}",
+ j > 0 ? " " : "",
+ privateDicts[i].familyBlues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
}
if (privateDicts[i].nFamilyOtherBlues) {
(*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
- sprintf(buf, "%s%d", j > 0 ? " " : "",
- privateDicts[i].familyOtherBlues[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:s}{1:d}", j > 0 ? " " : "",
+ privateDicts[i].familyOtherBlues[j]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
}
if (privateDicts[i].blueScale != 0.039625) {
- sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/BlueScale {0:.4g} def\n",
+ privateDicts[i].blueScale);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].blueShift != 7) {
- sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/BlueShift {0:d} def\n",
+ privateDicts[i].blueShift);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].blueFuzz != 1) {
- sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].hasStdHW) {
- sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].hasStdVW) {
- sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].nStemSnapH) {
(*outputFunc)(outputStream, "/StemSnapH [", 12);
for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
- sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ 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);
}
if (privateDicts[i].nStemSnapV) {
(*outputFunc)(outputStream, "/StemSnapV [", 12);
for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
- sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ 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);
}
if (privateDicts[i].hasForceBold) {
- sprintf(buf, "/ForceBold %s def\n",
- privateDicts[i].forceBold ? "true" : "false");
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/ForceBold {0:s} def\n",
+ privateDicts[i].forceBold ? "true" : "false");
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].forceBoldThreshold != 0) {
- sprintf(buf, "/ForceBoldThreshold %g def\n",
- privateDicts[i].forceBoldThreshold);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
+ privateDicts[i].forceBoldThreshold);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].languageGroup != 0) {
- sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/LanguageGroup {0:d} def\n",
+ privateDicts[i].languageGroup);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (privateDicts[i].expansionFactor != 0.06) {
- sprintf(buf, "/ExpansionFactor %g def\n",
- privateDicts[i].expansionFactor);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/ExpansionFactor {0:.4g} def\n",
+ privateDicts[i].expansionFactor);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "currentdict end def\n", 20);
(*outputFunc)(outputStream, "currentdict end put\n", 20);
@@ -627,26 +709,28 @@ void FoFiType1C::convertToCIDType0(char *psName,
// start the binary section
offset = (nCIDs + 1) * (1 + gdBytes);
- sprintf(buf, "(Hex) %d StartData\n",
- offset + charStrings->getLength());
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("(Hex) {0:d} StartData\n",
+ offset + charStrings->getLength());
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
// write the charstring offset (CIDMap) table
for (i = 0; i <= nCIDs; i += 6) {
for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
if (i+j < nCIDs && cidMap[i+j] >= 0) {
- buf[0] = (char)fdSelect[cidMap[i+j]];
+ buf2[0] = (char)fdSelect[cidMap[i+j]];
} else {
- buf[0] = (char)0;
+ buf2[0] = (char)0;
}
n = offset + charStringOffsets[i+j];
for (k = gdBytes; k >= 1; --k) {
- buf[k] = (char)(n & 0xff);
+ buf2[k] = (char)(n & 0xff);
n >>= 8;
}
for (k = 0; k <= gdBytes; ++k) {
- sprintf(buf2, "%02x", buf[k] & 0xff);
- (*outputFunc)(outputStream, buf2, 2);
+ buf = GString::format("{0:02x}", buf2[k] & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
}
(*outputFunc)(outputStream, "\n", 1);
@@ -656,8 +740,9 @@ void FoFiType1C::convertToCIDType0(char *psName,
n = charStrings->getLength();
for (i = 0; i < n; i += 32) {
for (j = 0; j < 32 && i+j < n; ++j) {
- sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (i + 32 >= n) {
(*outputFunc)(outputStream, ">", 1);
@@ -677,7 +762,7 @@ void FoFiType1C::convertToType0(char *psName,
Type1CIndex subrIdx;
Type1CIndexVal val;
int nCIDs;
- char buf[512];
+ GString *buf;
Type1CEexecBuf eb;
GBool ok;
int fd, i, j, k;
@@ -702,9 +787,9 @@ void FoFiType1C::convertToType0(char *psName,
//~ this assumes that all CIDs in this block have the same FD --
//~ to handle multiple FDs correctly, need to somehow divide the
- //~ font up by FD
+ //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
fd = 0;
- for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
if (cidMap[i+j] >= 0) {
fd = fdSelect[cidMap[i+j]];
break;
@@ -715,42 +800,50 @@ void FoFiType1C::convertToType0(char *psName,
(*outputFunc)(outputStream, "16 dict begin\n", 14);
(*outputFunc)(outputStream, "/FontName /", 11);
(*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x def\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("_{0:02x} def\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
(*outputFunc)(outputStream, "/FontType 1 def\n", 16);
if (privateDicts[fd].hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- privateDicts[fd].fontMatrix[0],
- privateDicts[fd].fontMatrix[1],
- privateDicts[fd].fontMatrix[2],
- privateDicts[fd].fontMatrix[3],
- privateDicts[fd].fontMatrix[4],
- privateDicts[fd].fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ privateDicts[fd].fontMatrix[0],
+ privateDicts[fd].fontMatrix[1],
+ privateDicts[fd].fontMatrix[2],
+ privateDicts[fd].fontMatrix[3],
+ privateDicts[fd].fontMatrix[4],
+ privateDicts[fd].fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
} else if (topDict.hasFontMatrix) {
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
} else {
(*outputFunc)(outputStream,
"/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
}
- sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
- topDict.fontBBox[0], topDict.fontBBox[1],
- topDict.fontBBox[2], topDict.fontBBox[3]);
- (*outputFunc)(outputStream, buf, strlen(buf));
- sprintf(buf, "/PaintType %d def\n", topDict.paintType);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
+ topDict.fontBBox[0], topDict.fontBBox[1],
+ topDict.fontBBox[2], topDict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
+ buf = GString::format("/PaintType {0:d} def\n", topDict.paintType);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
if (topDict.paintType != 0) {
- sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
for (j = 0; j < 256 && i+j < nCIDs; ++j) {
- sprintf(buf, "dup %d /c%02x put\n", j, j);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
if (j < 256) {
- sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
+ j);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "readonly def\n", 13);
(*outputFunc)(outputStream, "currentdict end\n", 16);
@@ -775,91 +868,116 @@ void FoFiType1C::convertToType0(char *psName,
if (privateDicts[fd].nBlueValues) {
eexecWrite(&eb, "/BlueValues [");
for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}",
+ k > 0 ? " " : "",
+ privateDicts[fd].blueValues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[fd].nOtherBlues) {
eexecWrite(&eb, "/OtherBlues [");
for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}",
+ k > 0 ? " " : "",
+ privateDicts[fd].otherBlues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[fd].nFamilyBlues) {
eexecWrite(&eb, "/FamilyBlues [");
for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "",
- privateDicts[fd].familyBlues[k]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
+ privateDicts[fd].familyBlues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[fd].nFamilyOtherBlues) {
eexecWrite(&eb, "/FamilyOtherBlues [");
for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
- sprintf(buf, "%s%d", k > 0 ? " " : "",
- privateDicts[fd].familyOtherBlues[k]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "",
+ privateDicts[fd].familyOtherBlues[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[fd].blueScale != 0.039625) {
- sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
- eexecWrite(&eb, buf);
+ buf = GString::format("/BlueScale {0:.4g} def\n",
+ privateDicts[fd].blueScale);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].blueShift != 7) {
- sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
- eexecWrite(&eb, buf);
+ buf = GString::format("/BlueShift {0:d} def\n",
+ privateDicts[fd].blueShift);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].blueFuzz != 1) {
- sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
- eexecWrite(&eb, buf);
+ buf = GString::format("/BlueFuzz {0:d} def\n",
+ privateDicts[fd].blueFuzz);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].hasStdHW) {
- sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
- eexecWrite(&eb, buf);
+ buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].hasStdVW) {
- sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
- eexecWrite(&eb, buf);
+ buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].nStemSnapH) {
eexecWrite(&eb, "/StemSnapH [");
for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
- sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:.4g}",
+ k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[fd].nStemSnapV) {
eexecWrite(&eb, "/StemSnapV [");
for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
- sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
- eexecWrite(&eb, buf);
+ buf = GString::format("{0:s}{1:.4g}",
+ k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
eexecWrite(&eb, "] def\n");
}
if (privateDicts[fd].hasForceBold) {
- sprintf(buf, "/ForceBold %s def\n",
- privateDicts[fd].forceBold ? "true" : "false");
- eexecWrite(&eb, buf);
+ buf = GString::format("/ForceBold {0:s} def\n",
+ privateDicts[fd].forceBold ? "true" : "false");
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].forceBoldThreshold != 0) {
- sprintf(buf, "/ForceBoldThreshold %g def\n",
- privateDicts[fd].forceBoldThreshold);
- eexecWrite(&eb, buf);
+ buf = GString::format("/ForceBoldThreshold {0:.4g} def\n",
+ privateDicts[fd].forceBoldThreshold);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].languageGroup != 0) {
- sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
- eexecWrite(&eb, buf);
+ buf = GString::format("/LanguageGroup {0:d} def\n",
+ privateDicts[fd].languageGroup);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
if (privateDicts[fd].expansionFactor != 0.06) {
- sprintf(buf, "/ExpansionFactor %g def\n",
- privateDicts[fd].expansionFactor);
- eexecWrite(&eb, buf);
+ buf = GString::format("/ExpansionFactor {0:.4g} def\n",
+ privateDicts[fd].expansionFactor);
+ eexecWrite(&eb, buf->getCString());
+ delete buf;
}
// set up the subroutines
@@ -870,8 +988,7 @@ void FoFiType1C::convertToType0(char *psName,
}
// start the CharStrings
- sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
- eexecWrite(&eb, buf);
+ eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
// write the .notdef CharString
ok = gTrue;
@@ -887,9 +1004,10 @@ void FoFiType1C::convertToType0(char *psName,
ok = gTrue;
getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
if (ok) {
- sprintf(buf, "c%02x", j);
- eexecCvtGlyph(&eb, buf, val.pos, val.len,
+ buf = GString::format("c{0:02x}", j);
+ eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
&subrIdx, &privateDicts[fd]);
+ delete buf;
}
}
}
@@ -917,27 +1035,30 @@ void FoFiType1C::convertToType0(char *psName,
(*outputFunc)(outputStream, " def\n", 5);
(*outputFunc)(outputStream, "/FontType 0 def\n", 16);
if (topDict.hasFontMatrix) {
- sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
- topDict.fontMatrix[0], topDict.fontMatrix[1],
- topDict.fontMatrix[2], topDict.fontMatrix[3],
- topDict.fontMatrix[4], topDict.fontMatrix[5]);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
+ topDict.fontMatrix[0], topDict.fontMatrix[1],
+ topDict.fontMatrix[2], topDict.fontMatrix[3],
+ topDict.fontMatrix[4], topDict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
} else {
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
}
(*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
(*outputFunc)(outputStream, "/Encoding [\n", 12);
for (i = 0; i < nCIDs; i += 256) {
- sprintf(buf, "%d\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("{0:d}\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
(*outputFunc)(outputStream, "/FDepVector [\n", 14);
for (i = 0; i < nCIDs; i += 256) {
(*outputFunc)(outputStream, "/", 1);
(*outputFunc)(outputStream, psName, strlen(psName));
- sprintf(buf, "_%02x findfont\n", i >> 8);
- (*outputFunc)(outputStream, buf, strlen(buf));
+ buf = GString::format("_{0:02x} findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
+ delete buf;
}
(*outputFunc)(outputStream, "] def\n", 6);
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
@@ -949,15 +1070,16 @@ void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
int offset, int nBytes,
Type1CIndex *subrIdx,
Type1CPrivateDict *pDict) {
- char buf[512];
+ GString *buf;
GString *charBuf;
// generate the charstring
charBuf = new GString();
cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
- sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
- eexecWrite(eb, buf);
+ buf = GString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
+ eexecWrite(eb, buf->getCString());
+ delete buf;
eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
charBuf->getLength());
eexecWrite(eb, " ND\n");
diff --git a/Build/source/libs/xpdf/fofi/FoFiType1C.h b/Build/source/libs/xpdf/fofi/FoFiType1C.h
index 62649ed949d..eec27555494 100644
--- a/Build/source/libs/xpdf/fofi/FoFiType1C.h
+++ b/Build/source/libs/xpdf/fofi/FoFiType1C.h
@@ -157,8 +157,9 @@ public:
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
- // otherwise it will be left as binary data.
- void convertToType1(char **newEncoding, GBool ascii,
+ // otherwise it will be left as binary data. If <psName> is non-NULL,
+ // it will be used as the PostScript font name.
+ void convertToType1(char *psName, char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
diff --git a/Build/source/libs/xpdf/goo/FixedPoint.cc b/Build/source/libs/xpdf/goo/FixedPoint.cc
index f969959a66b..47c2834a34b 100644
--- a/Build/source/libs/xpdf/goo/FixedPoint.cc
+++ b/Build/source/libs/xpdf/goo/FixedPoint.cc
@@ -18,13 +18,15 @@
#include "FixedPoint.h"
+#define ln2 ((FixedPoint)0.69314718)
+
FixedPoint FixedPoint::sqrt(FixedPoint x) {
FixedPoint y0, y1, z;
if (x.val <= 0) {
y1.val = 0;
} else {
- y1.val = x.val >> 1;
+ y1.val = x.val == 1 ? 2 : x.val >> 1;
do {
y0.val = y1.val;
z = x / y0;
@@ -34,10 +36,9 @@ FixedPoint FixedPoint::sqrt(FixedPoint x) {
return y1;
}
-//~ this is not very accurate
FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
FixedPoint t, t2, lnx0, lnx, z0, z;
- int d, i;
+ int d, n, i;
if (y.val <= 0) {
z.val = 0;
@@ -56,6 +57,8 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
lnx.val <<= 1;
t = y * lnx;
// exp(y * ln(x))
+ n = floor(t / ln2);
+ t -= ln2 * n;
t2 = t;
d = 1;
i = 1;
@@ -67,6 +70,11 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
++i;
d *= i;
} while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift));
+ if (n >= 0) {
+ z.val <<= n;
+ } else if (n < 0) {
+ z.val >>= -n;
+ }
}
return z;
}
@@ -92,4 +100,19 @@ int FixedPoint::div(int x, int y) {
#endif
}
+GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
+#if 1 //~tmp
+ FixPtInt64 z;
+
+ z = ((FixPtInt64)x.val << fixptShift) / y.val;
+ if ((z == 0 && x != 0) ||
+ z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) {
+ return gFalse;
+ }
+ result->val = z;
+ return gTrue;
+#else
+#endif
+}
+
#endif // USE_FIXEDPOINT
diff --git a/Build/source/libs/xpdf/goo/FixedPoint.h b/Build/source/libs/xpdf/goo/FixedPoint.h
index 7e89018edb9..abcb212101d 100644
--- a/Build/source/libs/xpdf/goo/FixedPoint.h
+++ b/Build/source/libs/xpdf/goo/FixedPoint.h
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "gtypes.h"
#define fixptShift 16
#define fixptMaskL ((1 << fixptShift) - 1)
@@ -135,6 +136,10 @@ public:
static FixedPoint pow(FixedPoint x, FixedPoint y);
+ // Compute *result = x/y; return false if there is an underflow or
+ // overflow.
+ static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
+
private:
static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; }
diff --git a/Build/source/libs/xpdf/goo/GString.cc b/Build/source/libs/xpdf/goo/GString.cc
index 049dcf38dc9..de280ad9842 100644
--- a/Build/source/libs/xpdf/goo/GString.cc
+++ b/Build/source/libs/xpdf/goo/GString.cc
@@ -18,14 +18,66 @@
#include <stddef.h>
#include <string.h>
#include <ctype.h>
-#include "gtypes.h"
+#include <math.h>
+#include "gmem.h"
#include "GString.h"
+//------------------------------------------------------------------------
+
+union GStringFormatArg {
+ int i;
+ Guint ui;
+ long l;
+ Gulong ul;
+ double f;
+ char c;
+ char *s;
+ GString *gs;
+};
+
+enum GStringFormatType {
+ fmtIntDecimal,
+ fmtIntHex,
+ fmtIntOctal,
+ fmtIntBinary,
+ fmtUIntDecimal,
+ fmtUIntHex,
+ fmtUIntOctal,
+ fmtUIntBinary,
+ fmtLongDecimal,
+ fmtLongHex,
+ fmtLongOctal,
+ fmtLongBinary,
+ fmtULongDecimal,
+ fmtULongHex,
+ fmtULongOctal,
+ fmtULongBinary,
+ fmtDouble,
+ fmtDoubleTrim,
+ fmtChar,
+ fmtString,
+ fmtGString,
+ fmtSpace
+};
+
+static char *formatStrings[] = {
+ "d", "x", "o", "b", "ud", "ux", "uo", "ub",
+ "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
+ "f", "g",
+ "c",
+ "s",
+ "t",
+ "w",
+ NULL
+};
+
+//------------------------------------------------------------------------
+
static inline int size(int len) {
int delta;
-
- delta = len < 256 ? 7 : 255;
- return ((len + 1) + delta) & ~delta;
+ for (delta = 8; delta < len && delta < 0x100000; delta <<= 1) ;
+ // this is ((len + 1) + (delta - 1)) & ~(delta - 1)
+ return (len + delta) & ~(delta - 1);
}
inline void GString::resize(int length1) {
@@ -92,28 +144,30 @@ GString::GString(GString *str1, GString *str2) {
GString *GString::fromInt(int x) {
char buf[24]; // enough space for 64-bit ints plus a little extra
- GBool neg;
- Guint y;
- int i;
+ char *p;
+ int len;
- i = 24;
- if (x == 0) {
- buf[--i] = '0';
- } else {
- if ((neg = x < 0)) {
- y = (Guint)-x;
- } else {
- y = (Guint)x;
- }
- while (i > 0 && y > 0) {
- buf[--i] = '0' + y % 10;
- y /= 10;
- }
- if (neg && i > 0) {
- buf[--i] = '-';
- }
- }
- return new GString(buf + i, 24 - i);
+ formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len);
+ return new GString(p, len);
+}
+
+GString *GString::format(char *fmt, ...) {
+ va_list argList;
+ GString *s;
+
+ s = new GString();
+ va_start(argList, fmt);
+ s->appendfv(fmt, argList);
+ va_end(argList);
+ return s;
+}
+
+GString *GString::formatv(char *fmt, va_list argList) {
+ GString *s;
+
+ s = new GString();
+ s->appendfv(fmt, argList);
+ return s;
}
GString::~GString() {
@@ -159,6 +213,351 @@ GString *GString::append(const char *str, int lengthA) {
return this;
}
+GString *GString::appendf(char *fmt, ...) {
+ va_list argList;
+
+ va_start(argList, fmt);
+ appendfv(fmt, argList);
+ va_end(argList);
+ return this;
+}
+
+GString *GString::appendfv(char *fmt, va_list argList) {
+ GStringFormatArg *args;
+ int argsLen, argsSize;
+ GStringFormatArg arg;
+ int idx, width, prec;
+ GBool reverseAlign, zeroFill;
+ GStringFormatType ft;
+ char buf[65];
+ int len, i;
+ char *p0, *p1, *str;
+
+ argsLen = 0;
+ argsSize = 8;
+ args = (GStringFormatArg *)gmallocn(argsSize, sizeof(GStringFormatArg));
+
+ p0 = fmt;
+ while (*p0) {
+ if (*p0 == '{') {
+ ++p0;
+ if (*p0 == '{') {
+ ++p0;
+ append('{');
+ } else {
+
+ // parse the format string
+ if (!(*p0 >= '0' && *p0 <= '9')) {
+ break;
+ }
+ idx = *p0 - '0';
+ for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
+ idx = 10 * idx + (*p0 - '0');
+ }
+ if (*p0 != ':') {
+ break;
+ }
+ ++p0;
+ if (*p0 == '-') {
+ reverseAlign = gTrue;
+ ++p0;
+ } else {
+ reverseAlign = gFalse;
+ }
+ width = 0;
+ zeroFill = *p0 == '0';
+ for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
+ width = 10 * width + (*p0 - '0');
+ }
+ if (*p0 == '.') {
+ ++p0;
+ prec = 0;
+ for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
+ prec = 10 * prec + (*p0 - '0');
+ }
+ } else {
+ prec = 0;
+ }
+ for (ft = (GStringFormatType)0;
+ formatStrings[ft];
+ ft = (GStringFormatType)(ft + 1)) {
+ if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
+ break;
+ }
+ }
+ if (!formatStrings[ft]) {
+ break;
+ }
+ p0 += strlen(formatStrings[ft]);
+ if (*p0 != '}') {
+ break;
+ }
+ ++p0;
+
+ // fetch the argument
+ if (idx > argsLen) {
+ break;
+ }
+ if (idx == argsLen) {
+ if (argsLen == argsSize) {
+ argsSize *= 2;
+ args = (GStringFormatArg *)greallocn(args, argsSize,
+ sizeof(GStringFormatArg));
+ }
+ switch (ft) {
+ case fmtIntDecimal:
+ case fmtIntHex:
+ case fmtIntOctal:
+ case fmtIntBinary:
+ case fmtSpace:
+ args[argsLen].i = va_arg(argList, int);
+ break;
+ case fmtUIntDecimal:
+ case fmtUIntHex:
+ case fmtUIntOctal:
+ case fmtUIntBinary:
+ args[argsLen].ui = va_arg(argList, Guint);
+ break;
+ case fmtLongDecimal:
+ case fmtLongHex:
+ case fmtLongOctal:
+ case fmtLongBinary:
+ args[argsLen].l = va_arg(argList, long);
+ break;
+ case fmtULongDecimal:
+ case fmtULongHex:
+ case fmtULongOctal:
+ case fmtULongBinary:
+ args[argsLen].ul = va_arg(argList, Gulong);
+ break;
+ case fmtDouble:
+ case fmtDoubleTrim:
+ args[argsLen].f = va_arg(argList, double);
+ break;
+ case fmtChar:
+ args[argsLen].c = (char)va_arg(argList, int);
+ break;
+ case fmtString:
+ args[argsLen].s = va_arg(argList, char *);
+ break;
+ case fmtGString:
+ args[argsLen].gs = va_arg(argList, GString *);
+ break;
+ }
+ ++argsLen;
+ }
+
+ // format the argument
+ arg = args[idx];
+ switch (ft) {
+ case fmtIntDecimal:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
+ break;
+ case fmtIntHex:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
+ break;
+ case fmtIntOctal:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtIntBinary:
+ formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtUIntDecimal:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10,
+ &str, &len);
+ break;
+ case fmtUIntHex:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16,
+ &str, &len);
+ break;
+ case fmtUIntOctal:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtUIntBinary:
+ formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtLongDecimal:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
+ break;
+ case fmtLongHex:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
+ break;
+ case fmtLongOctal:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtLongBinary:
+ formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtULongDecimal:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10,
+ &str, &len);
+ break;
+ case fmtULongHex:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16,
+ &str, &len);
+ break;
+ case fmtULongOctal:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
+ break;
+ case fmtULongBinary:
+ formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
+ break;
+ case fmtDouble:
+ formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
+ break;
+ case fmtDoubleTrim:
+ formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
+ break;
+ case fmtChar:
+ buf[0] = arg.c;
+ str = buf;
+ len = 1;
+ reverseAlign = !reverseAlign;
+ break;
+ case fmtString:
+ str = arg.s;
+ len = strlen(str);
+ reverseAlign = !reverseAlign;
+ break;
+ case fmtGString:
+ str = arg.gs->getCString();
+ len = arg.gs->getLength();
+ reverseAlign = !reverseAlign;
+ break;
+ case fmtSpace:
+ str = buf;
+ len = 0;
+ width = arg.i;
+ break;
+ }
+
+ // append the formatted arg, handling width and alignment
+ if (!reverseAlign && len < width) {
+ for (i = len; i < width; ++i) {
+ append(' ');
+ }
+ }
+ append(str, len);
+ if (reverseAlign && len < width) {
+ for (i = len; i < width; ++i) {
+ append(' ');
+ }
+ }
+ }
+
+ } else if (*p0 == '}') {
+ ++p0;
+ if (*p0 == '}') {
+ ++p0;
+ }
+ append('}');
+
+ } else {
+ for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ;
+ append(p0, p1 - p0);
+ p0 = p1;
+ }
+ }
+
+ gfree(args);
+ return this;
+}
+
+void GString::formatInt(long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len) {
+ static char vals[17] = "0123456789abcdef";
+ GBool neg;
+ int start, i, j;
+
+ i = bufSize;
+ if ((neg = x < 0)) {
+ x = -x;
+ }
+ start = neg ? 1 : 0;
+ if (x == 0) {
+ buf[--i] = '0';
+ } else {
+ while (i > start && x) {
+ buf[--i] = vals[x % base];
+ x /= base;
+ }
+ }
+ if (zeroFill) {
+ for (j = bufSize - i; i > start && j < width - start; ++j) {
+ buf[--i] = '0';
+ }
+ }
+ if (neg) {
+ buf[--i] = '-';
+ }
+ *p = buf + i;
+ *len = bufSize - i;
+}
+
+void GString::formatUInt(Gulong x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len) {
+ static char vals[17] = "0123456789abcdef";
+ int i, j;
+
+ i = bufSize;
+ if (x == 0) {
+ buf[--i] = '0';
+ } else {
+ while (i > 0 && x) {
+ buf[--i] = vals[x % base];
+ x /= base;
+ }
+ }
+ if (zeroFill) {
+ for (j = bufSize - i; i > 0 && j < width; ++j) {
+ buf[--i] = '0';
+ }
+ }
+ *p = buf + i;
+ *len = bufSize - i;
+}
+
+void GString::formatDouble(double x, char *buf, int bufSize, int prec,
+ GBool trim, char **p, int *len) {
+ GBool neg, started;
+ double x2;
+ int d, i, j;
+
+ if ((neg = x < 0)) {
+ x = -x;
+ }
+ x = floor(x * pow(10.0, prec) + 0.5);
+ i = bufSize;
+ started = !trim;
+ for (j = 0; j < prec && i > 1; ++j) {
+ x2 = floor(0.1 * (x + 0.5));
+ d = (int)floor(x - 10 * x2 + 0.5);
+ if (started || d != 0) {
+ buf[--i] = '0' + d;
+ started = gTrue;
+ }
+ x = x2;
+ }
+ if (i > 1 && started) {
+ buf[--i] = '.';
+ }
+ if (i > 1) {
+ do {
+ x2 = floor(0.1 * (x + 0.5));
+ d = (int)floor(x - 10 * x2 + 0.5);
+ buf[--i] = '0' + d;
+ x = x2;
+ } while (i > 1 && x);
+ }
+ if (neg) {
+ buf[--i] = '-';
+ }
+ *p = buf + i;
+ *len = bufSize - i;
+}
+
GString *GString::insert(int i, char c) {
int j;
diff --git a/Build/source/libs/xpdf/goo/GString.h b/Build/source/libs/xpdf/goo/GString.h
index f4ff7c6a9ee..dd22e2d8f6b 100644
--- a/Build/source/libs/xpdf/goo/GString.h
+++ b/Build/source/libs/xpdf/goo/GString.h
@@ -17,6 +17,9 @@
#pragma interface
#endif
+#include <stdarg.h>
+#include "gtypes.h"
+
class GString {
public:
@@ -43,6 +46,30 @@ public:
// Convert an integer to a string.
static GString *fromInt(int x);
+ // Create a formatted string. Similar to printf, but without the
+ // string overflow issues. Formatting elements consist of:
+ // {<arg>:[<width>][.<precision>]<type>}
+ // where:
+ // - <arg> is the argument number (arg 0 is the first argument
+ // following the format string) -- NB: args must be first used in
+ // order; they can be reused in any order
+ // - <width> is the field width -- negative to reverse the alignment;
+ // starting with a leading zero to zero-fill (for integers)
+ // - <precision> is the number of digits to the right of the decimal
+ // point (for floating point numbers)
+ // - <type> is one of:
+ // d, x, o, b -- int in decimal, hex, octal, binary
+ // ud, ux, uo, ub -- unsigned int
+ // ld, lx, lo, lb, uld, ulx, ulo, ulb -- long, unsigned long
+ // f, g -- double
+ // c -- char
+ // s -- string (char *)
+ // t -- GString *
+ // w -- blank space; arg determines width
+ // To get literal curly braces, use {{ or }}.
+ static GString *format(char *fmt, ...);
+ static GString *formatv(char *fmt, va_list argList);
+
// Destructor.
~GString();
@@ -67,6 +94,10 @@ public:
GString *append(const char *str);
GString *append(const char *str, int lengthA);
+ // Append a formatted string.
+ GString *appendf(char *fmt, ...);
+ GString *appendfv(char *fmt, va_list argList);
+
// Insert a character or string.
GString *insert(int i, char c);
GString *insert(int i, GString *str);
@@ -92,6 +123,14 @@ private:
char *s;
void resize(int length1);
+ static void formatInt(long x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len);
+ static void formatUInt(Gulong x, char *buf, int bufSize,
+ GBool zeroFill, int width, int base,
+ char **p, int *len);
+ static void formatDouble(double x, char *buf, int bufSize, int prec,
+ GBool trim, char **p, int *len);
};
#endif
diff --git a/Build/source/libs/xpdf/goo/Makefile.in b/Build/source/libs/xpdf/goo/Makefile.in
index fe992f46ac5..4cebea29e0b 100644
--- a/Build/source/libs/xpdf/goo/Makefile.in
+++ b/Build/source/libs/xpdf/goo/Makefile.in
@@ -5,6 +5,7 @@
# Copyright 1996 Derek B. Noonburg
#
# Modified for pdftex by Martin Schröder 2005
+# $Id$
#
#========================================================================
@@ -43,17 +44,17 @@ CXX_SRC = \
$(srcdir)/GHash.cc \
$(srcdir)/GList.cc \
$(srcdir)/GString.cc \
+ $(srcdir)/gmem.cc \
$(srcdir)/gmempp.cc \
$(srcdir)/gfile.cc
C_SRC = \
- $(srcdir)/gmem.c \
$(srcdir)/parseargs.c
#------------------------------------------------------------------------
-GOO_CXX_OBJS = FixedPoint.o GHash.o GList.o GString.o gmempp.o gfile.o
-GOO_C_OBJS = gmem.o parseargs.o
+GOO_CXX_OBJS = FixedPoint.o GHash.o GList.o GString.o gmem.o gmempp.o gfile.o
+GOO_C_OBJS = parseargs.o
GOO_OBJS = $(GOO_CXX_OBJS) $(GOO_C_OBJS)
libGoo.a: $(GOO_OBJS)
diff --git a/Build/source/libs/xpdf/goo/depend.mk b/Build/source/libs/xpdf/goo/depend.mk
index c0dfb37f7b5..8aa02de24cb 100644
--- a/Build/source/libs/xpdf/goo/depend.mk
+++ b/Build/source/libs/xpdf/goo/depend.mk
@@ -23,7 +23,7 @@ GString.o: $(srcdir)/GString.cc ../aconf.h \
$(srcdirparent)/aconf2.h \
$(srcdir)/gtypes.h \
$(srcdir)/GString.h
-gmem.o: $(srcdir)/gmem.c ../aconf.h \
+gmem.o: $(srcdir)/gmem.cc ../aconf.h \
$(srcdirparent)/aconf2.h \
$(srcdir)/gmem.h
parseargs.o: $(srcdir)/parseargs.c \
diff --git a/Build/source/libs/xpdf/goo/gfile.cc b/Build/source/libs/xpdf/goo/gfile.cc
index caa96e7459b..740b3ea1ff6 100644
--- a/Build/source/libs/xpdf/goo/gfile.cc
+++ b/Build/source/libs/xpdf/goo/gfile.cc
@@ -10,7 +10,9 @@
#include <aconf.h>
-#ifndef WIN32
+#ifdef WIN32
+# include <time.h>
+#else
# if defined(MACOS)
# include <sys/stat.h>
# elif !defined(ACORN)
@@ -441,21 +443,45 @@ time_t getModTime(char *fileName) {
GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
#if defined(WIN32)
//---------- Win32 ----------
- char *s;
-
- if (!(s = _tempnam(getenv("TEMP"), NULL))) {
- return gFalse;
- }
- *name = new GString(s);
- free(s);
- if (ext) {
- (*name)->append(ext);
+ char *tempDir;
+ GString *s, *s2;
+ char buf[32];
+ FILE *f2;
+ int t, i;
+
+ // this has the standard race condition problem, but I haven't found
+ // a better way to generate temp file names with extensions on
+ // Windows
+ if ((tempDir = getenv("TEMP"))) {
+ s = new GString(tempDir);
+ s->append('\\');
+ } else {
+ s = new GString();
}
- if (!(*f = fopen((*name)->getCString(), mode))) {
- delete (*name);
- return gFalse;
+ s->append("x");
+ t = (int)time(NULL);
+ for (i = 0; i < 1000; ++i) {
+ sprintf(buf, "%d", t + i);
+ s2 = s->copy()->append(buf);
+ if (ext) {
+ s2->append(ext);
+ }
+ if (!(f2 = fopen(s2->getCString(), "r"))) {
+ if (!(f2 = fopen(s2->getCString(), mode))) {
+ delete s2;
+ delete s;
+ return gFalse;
+ }
+ *name = s2;
+ *f = f2;
+ delete s;
+ return gTrue;
+ }
+ fclose(f2);
+ delete s2;
}
- return gTrue;
+ delete s;
+ return gFalse;
#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS)
//---------- non-Unix ----------
char *s;
@@ -672,9 +698,9 @@ GDirEntry *GDir::getNextEntry() {
struct dirent *ent;
e = NULL;
if (dir) {
- ent = readdir(dir);
+ ent = (struct dirent *)readdir(dir);
if (ent && !strcmp(ent->d_name, ".")) {
- ent = readdir(dir);
+ ent = (struct dirent *)readdir(dir);
}
if (ent) {
e = new GDirEntry(path->getCString(), ent->d_name, doStat);
diff --git a/Build/source/libs/xpdf/goo/gfile.h b/Build/source/libs/xpdf/goo/gfile.h
index 8817e8b2381..82f1d7a98e3 100644
--- a/Build/source/libs/xpdf/goo/gfile.h
+++ b/Build/source/libs/xpdf/goo/gfile.h
@@ -46,9 +46,6 @@
# endif
# endif
#endif
-#if defined(__DJGPP__)
-typedef unsigned int time_t;
-#endif
#include "gtypes.h"
class GString;
@@ -86,9 +83,7 @@ extern time_t getModTime(char *fileName);
// should be done to the returned file pointer; the file may be
// reopened later for reading, but not for writing. The <mode> string
// should be "w" or "wb". Returns true on success.
-#ifndef PDF_PARSER_ONLY
extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
-#endif
// Execute <command>. Returns true on success.
extern GBool executeCommand(char *cmd);
diff --git a/Build/source/libs/xpdf/goo/gmem.c b/Build/source/libs/xpdf/goo/gmem.cc
index b97535adf04..6b13b38d0f0 100644
--- a/Build/source/libs/xpdf/goo/gmem.c
+++ b/Build/source/libs/xpdf/goo/gmem.cc
@@ -17,14 +17,17 @@
#ifdef DEBUG_MEM
typedef struct _GMemHdr {
+ unsigned int magic;
int size;
int index;
- struct _GMemHdr *next;
+ struct _GMemHdr *next, *prev;
} GMemHdr;
#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
#define gMemTrlSize (sizeof(long))
+#define gMemMagic 0xabcd9999
+
#if gmemTrlSize==8
#define gMemDeadVal 0xdeadbeefdeadbeefUL
#else
@@ -35,19 +38,8 @@ typedef struct _GMemHdr {
#define gMemDataSize(size) \
((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
-#define gMemNLists 64
-#define gMemListShift 4
-#define gMemListMask (gMemNLists - 1)
-static GMemHdr *gMemList[gMemNLists] = {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
+static GMemHdr *gMemHead = NULL;
+static GMemHdr *gMemTail = NULL;
static int gMemIndex = 0;
static int gMemAlloc = 0;
@@ -55,57 +47,75 @@ static int gMemInUse = 0;
#endif /* DEBUG_MEM */
-void *gmalloc(int size) {
+void *gmalloc(int size) GMEM_EXCEP {
#ifdef DEBUG_MEM
int size1;
char *mem;
GMemHdr *hdr;
void *data;
- int lst;
unsigned long *trl, *p;
- if (size <= 0)
+ 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
}
hdr = (GMemHdr *)mem;
data = (void *)(mem + gMemHdrSize);
trl = (unsigned long *)(mem + gMemHdrSize + size1);
+ hdr->magic = gMemMagic;
hdr->size = size;
hdr->index = gMemIndex++;
- lst = ((int)hdr >> gMemListShift) & gMemListMask;
- hdr->next = gMemList[lst];
- gMemList[lst] = hdr;
+ if (gMemTail) {
+ gMemTail->next = hdr;
+ hdr->prev = gMemTail;
+ gMemTail = hdr;
+ } else {
+ hdr->prev = NULL;
+ gMemHead = gMemTail = hdr;
+ }
+ hdr->next = NULL;
++gMemAlloc;
gMemInUse += size;
- for (p = (unsigned long *)data; p <= trl; ++p)
+ for (p = (unsigned long *)data; p <= trl; ++p) {
*p = gMemDeadVal;
+ }
return data;
#else
void *p;
- if (size <= 0)
+ if (size <= 0) {
return NULL;
+ }
if (!(p = malloc(size))) {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
fprintf(stderr, "Out of memory\n");
exit(1);
+#endif
}
return p;
#endif
}
-void *grealloc(void *p, int size) {
+void *grealloc(void *p, int size) GMEM_EXCEP {
#ifdef DEBUG_MEM
GMemHdr *hdr;
void *q;
int oldSize;
if (size <= 0) {
- if (p)
+ if (p) {
gfree(p);
+ }
return NULL;
}
if (p) {
@@ -122,23 +132,29 @@ void *grealloc(void *p, int size) {
void *q;
if (size <= 0) {
- if (p)
+ if (p) {
free(p);
+ }
return NULL;
}
- if (p)
+ if (p) {
q = realloc(p, size);
- else
+ } else {
q = malloc(size);
+ }
if (!q) {
+#if USE_EXCEPTIONS
+ throw GMemException();
+#else
fprintf(stderr, "Out of memory\n");
exit(1);
+#endif
}
return q;
#endif
}
-void *gmallocn(int nObjs, int objSize) {
+void *gmallocn(int nObjs, int objSize) GMEM_EXCEP {
int n;
if (nObjs == 0) {
@@ -146,13 +162,17 @@ void *gmallocn(int nObjs, int objSize) {
}
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
}
return gmalloc(n);
}
-void *greallocn(void *p, int nObjs, int objSize) {
+void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP {
int n;
if (nObjs == 0) {
@@ -163,8 +183,12 @@ void *greallocn(void *p, int nObjs, int objSize) {
}
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
}
return grealloc(p, n);
}
@@ -173,22 +197,23 @@ void gfree(void *p) {
#ifdef DEBUG_MEM
int size;
GMemHdr *hdr;
- GMemHdr *prevHdr, *q;
- int lst;
unsigned long *trl, *clr;
if (p) {
hdr = (GMemHdr *)((char *)p - gMemHdrSize);
- lst = ((int)hdr >> gMemListShift) & gMemListMask;
- for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
- if (q == hdr)
- break;
- }
- if (q) {
- if (prevHdr)
- prevHdr->next = hdr->next;
- else
- gMemList[lst] = hdr->next;
+ if (hdr->magic == gMemMagic &&
+ ((hdr->prev == NULL) == (hdr == gMemHead)) &&
+ ((hdr->next == NULL) == (hdr == gMemTail))) {
+ if (hdr->prev) {
+ hdr->prev->next = hdr->next;
+ } else {
+ gMemHead = hdr->next;
+ }
+ if (hdr->next) {
+ hdr->next->prev = hdr->prev;
+ } else {
+ gMemTail = hdr->prev;
+ }
--gMemAlloc;
gMemInUse -= hdr->size;
size = gMemDataSize(hdr->size);
@@ -197,32 +222,32 @@ void gfree(void *p) {
fprintf(stderr, "Overwrite past end of block %d at address %p\n",
hdr->index, p);
}
- for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
+ for (clr = (unsigned long *)hdr; clr <= trl; ++clr) {
*clr = gMemDeadVal;
+ }
free(hdr);
} else {
fprintf(stderr, "Attempted to free bad address %p\n", p);
}
}
#else
- if (p)
+ if (p) {
free(p);
+ }
#endif
}
#ifdef DEBUG_MEM
void gMemReport(FILE *f) {
GMemHdr *p;
- int lst;
fprintf(f, "%d memory allocations in all\n", gMemIndex);
if (gMemAlloc > 0) {
fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
fprintf(f, " index size\n");
fprintf(f, "-------- --------\n");
- for (lst = 0; lst < gMemNLists; ++lst) {
- for (p = gMemList[lst]; p; p = p->next)
- fprintf(f, "%8d %8d\n", p->index, p->size);
+ for (p = gMemHead; p; p = p->next) {
+ fprintf(f, "%8d %8d\n", p->index, p->size);
}
} else {
fprintf(f, "No memory blocks left allocated\n");
diff --git a/Build/source/libs/xpdf/goo/gmem.h b/Build/source/libs/xpdf/goo/gmem.h
index e74d1822318..da34736f216 100644
--- a/Build/source/libs/xpdf/goo/gmem.h
+++ b/Build/source/libs/xpdf/goo/gmem.h
@@ -10,6 +10,23 @@
#define GMEM_H
#include <stdio.h>
+#include <aconf.h>
+
+#if USE_EXCEPTIONS
+
+class GMemException {
+public:
+ GMemException() {}
+ ~GMemException() {}
+};
+
+#define GMEM_EXCEP throw(GMemException)
+
+#else // USE_EXCEPTIONS
+
+#define GMEM_EXCEP
+
+#endif // USE_EXCEPTIONS
#ifdef __cplusplus
extern "C" {
@@ -19,13 +36,13 @@ extern "C" {
* Same as malloc, but prints error message and exits if malloc()
* returns NULL.
*/
-extern void *gmalloc(int size);
+extern void *gmalloc(int size) GMEM_EXCEP;
/*
* Same as realloc, but prints error message and exits if realloc()
* returns NULL. If <p> is NULL, calls malloc instead of realloc().
*/
-extern void *grealloc(void *p, int size);
+extern void *grealloc(void *p, int size) GMEM_EXCEP;
/*
* These are similar to gmalloc and grealloc, but take an object count
@@ -33,8 +50,8 @@ extern void *grealloc(void *p, int size);
* bytes, but there is an additional error check that the total size
* doesn't overflow an int.
*/
-extern void *gmallocn(int nObjs, int objSize);
-extern void *greallocn(void *p, int nObjs, int objSize);
+extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP;
+extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP;
/*
* Same as free, but checks for and ignores NULL pointers.
diff --git a/Build/source/libs/xpdf/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf/Catalog.cc
index fd235d63c4b..de282c3feb6 100644
--- a/Build/source/libs/xpdf/xpdf/Catalog.cc
+++ b/Build/source/libs/xpdf/xpdf/Catalog.cc
@@ -2,7 +2,7 @@
//
// Catalog.cc
//
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
//
//========================================================================
@@ -28,8 +28,9 @@
//------------------------------------------------------------------------
Catalog::Catalog(XRef *xrefA) {
- Object catDict, pagesDict;
+ Object catDict, pagesDict, pagesDictRef;
Object obj, obj2;
+ char *alreadyRead;
int numPages0;
int i;
@@ -71,7 +72,16 @@ Catalog::Catalog(XRef *xrefA) {
pageRefs[i].num = -1;
pageRefs[i].gen = -1;
}
- numPages = readPageTree(pagesDict.getDict(), NULL, 0);
+ alreadyRead = (char *)gmalloc(xref->getNumObjects());
+ memset(alreadyRead, 0, xref->getNumObjects());
+ if (catDict.dictLookupNF("Pages", &pagesDictRef)->isRef() &&
+ pagesDictRef.getRefNum() >= 0 &&
+ pagesDictRef.getRefNum() < xref->getNumObjects()) {
+ alreadyRead[pagesDictRef.getRefNum()] = 1;
+ }
+ pagesDictRef.free();
+ numPages = readPageTree(pagesDict.getDict(), NULL, 0, alreadyRead);
+ gfree(alreadyRead);
if (numPages != numPages0) {
error(-1, "Page count in top-level pages object is incorrect");
}
@@ -169,7 +179,8 @@ GString *Catalog::readMetadata() {
return s;
}
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
+ char *alreadyRead) {
Object kids;
Object kid;
Object kidRef;
@@ -185,6 +196,17 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
goto err1;
}
for (i = 0; i < kids.arrayGetLength(); ++i) {
+ kids.arrayGetNF(i, &kidRef);
+ if (kidRef.isRef() &&
+ kidRef.getRefNum() >= 0 &&
+ kidRef.getRefNum() < xref->getNumObjects()) {
+ if (alreadyRead[kidRef.getRefNum()]) {
+ error(-1, "Loop in Pages tree");
+ kidRef.free();
+ continue;
+ }
+ alreadyRead[kidRef.getRefNum()] = 1;
+ }
kids.arrayGet(i, &kid);
if (kid.isDict("Page")) {
attrs2 = new PageAttrs(attrs1, kid.getDict());
@@ -204,17 +226,15 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
}
}
pages[start] = page;
- kids.arrayGetNF(i, &kidRef);
if (kidRef.isRef()) {
pageRefs[start].num = kidRef.getRefNum();
pageRefs[start].gen = kidRef.getRefGen();
}
- kidRef.free();
++start;
// This should really be isDict("Pages"), but I've seen at least one
// PDF file where the /Type entry is missing.
} else if (kid.isDict()) {
- if ((start = readPageTree(kid.getDict(), attrs1, start))
+ if ((start = readPageTree(kid.getDict(), attrs1, start, alreadyRead))
< 0)
goto err2;
} else {
@@ -222,6 +242,7 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
start+1, kid.getTypeName());
}
kid.free();
+ kidRef.free();
}
delete attrs1;
kids.free();
diff --git a/Build/source/libs/xpdf/xpdf/Catalog.h b/Build/source/libs/xpdf/xpdf/Catalog.h
index c38f1098500..6403194f974 100644
--- a/Build/source/libs/xpdf/xpdf/Catalog.h
+++ b/Build/source/libs/xpdf/xpdf/Catalog.h
@@ -2,7 +2,7 @@
//
// Catalog.h
//
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
//
//========================================================================
@@ -65,6 +65,10 @@ public:
// NULL if <name> is not a destination.
LinkDest *findDest(GString *name);
+ Object *getDests() { return &dests; }
+
+ Object *getNameTree() { return &nameTree; }
+
Object *getOutline() { return &outline; }
Object *getAcroForm() { return &acroForm; }
@@ -85,7 +89,8 @@ private:
Object acroForm; // AcroForm dictionary
GBool ok; // true if catalog is valid
- int readPageTree(Dict *pages, PageAttrs *attrs, int start);
+ int readPageTree(Dict *pages, PageAttrs *attrs, int start,
+ char *alreadyRead);
Object *findDestInTree(Object *tree, GString *name, Object *obj);
};
diff --git a/Build/source/libs/xpdf/xpdf/Decrypt.cc b/Build/source/libs/xpdf/xpdf/Decrypt.cc
index 91eb452a815..03205897cf4 100644
--- a/Build/source/libs/xpdf/xpdf/Decrypt.cc
+++ b/Build/source/libs/xpdf/xpdf/Decrypt.cc
@@ -18,6 +18,9 @@
static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
+static void aesKeyExpansion(DecryptAESState *s,
+ Guchar *objKey, int objKeyLen);
+static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last);
static void md5(Guchar *msg, int msgLen, Guchar *digest);
static Guchar passwordPad[32] = {
@@ -31,37 +34,6 @@ static Guchar passwordPad[32] = {
// Decrypt
//------------------------------------------------------------------------
-Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
- int i;
-
- // construct object key
- for (i = 0; i < keyLength; ++i) {
- objKey[i] = fileKey[i];
- }
- objKey[keyLength] = objNum & 0xff;
- objKey[keyLength + 1] = (objNum >> 8) & 0xff;
- objKey[keyLength + 2] = (objNum >> 16) & 0xff;
- objKey[keyLength + 3] = objGen & 0xff;
- objKey[keyLength + 4] = (objGen >> 8) & 0xff;
- md5(objKey, keyLength + 5, objKey);
-
- // set up for decryption
- x = y = 0;
- if ((objKeyLength = keyLength + 5) > 16) {
- objKeyLength = 16;
- }
- rc4InitKey(objKey, objKeyLength, state);
-}
-
-void Decrypt::reset() {
- x = y = 0;
- rc4InitKey(objKey, objKeyLength, state);
-}
-
-Guchar Decrypt::decryptByte(Guchar c) {
- return rc4DecryptByte(state, &x, &y, c);
-}
-
GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
GString *ownerKey, GString *userKey,
int permissions, GString *fileID,
@@ -206,6 +178,144 @@ GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
}
//------------------------------------------------------------------------
+// DecryptStream
+//------------------------------------------------------------------------
+
+DecryptStream::DecryptStream(Stream *strA, Guchar *fileKey,
+ CryptAlgorithm algoA, int keyLength,
+ int objNum, int objGen):
+ FilterStream(strA)
+{
+ int n, i;
+
+ algo = algoA;
+
+ // construct object key
+ for (i = 0; i < keyLength; ++i) {
+ objKey[i] = fileKey[i];
+ }
+ objKey[keyLength] = objNum & 0xff;
+ objKey[keyLength + 1] = (objNum >> 8) & 0xff;
+ objKey[keyLength + 2] = (objNum >> 16) & 0xff;
+ objKey[keyLength + 3] = objGen & 0xff;
+ objKey[keyLength + 4] = (objGen >> 8) & 0xff;
+ if (algo == cryptAES) {
+ objKey[keyLength + 5] = 0x73; // 's'
+ objKey[keyLength + 6] = 0x41; // 'A'
+ objKey[keyLength + 7] = 0x6c; // 'l'
+ objKey[keyLength + 8] = 0x54; // 'T'
+ n = keyLength + 9;
+ } else {
+ n = keyLength + 5;
+ }
+ md5(objKey, n, objKey);
+ if ((objKeyLength = keyLength + 5) > 16) {
+ objKeyLength = 16;
+ }
+}
+
+DecryptStream::~DecryptStream() {
+ delete str;
+}
+
+void DecryptStream::reset() {
+ int i;
+
+ str->reset();
+ switch (algo) {
+ case cryptRC4:
+ state.rc4.x = state.rc4.y = 0;
+ rc4InitKey(objKey, objKeyLength, state.rc4.state);
+ state.rc4.buf = EOF;
+ break;
+ case cryptAES:
+ aesKeyExpansion(&state.aes, objKey, objKeyLength);
+ for (i = 0; i < 16; ++i) {
+ state.aes.cbc[i] = str->getChar();
+ }
+ state.aes.bufIdx = 16;
+ break;
+ }
+}
+
+int DecryptStream::getChar() {
+ Guchar in[16];
+ int c, i;
+
+ c = EOF; // make gcc happy
+ switch (algo) {
+ case cryptRC4:
+ if (state.rc4.buf == EOF) {
+ c = str->getChar();
+ if (c != EOF) {
+ state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x,
+ &state.rc4.y, (Guchar)c);
+ }
+ }
+ c = state.rc4.buf;
+ state.rc4.buf = EOF;
+ 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;
+ }
+ aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
+ }
+ if (state.aes.bufIdx == 16) {
+ c = EOF;
+ } else {
+ c = state.aes.buf[state.aes.bufIdx++];
+ }
+ break;
+ }
+ return c;
+}
+
+int DecryptStream::lookChar() {
+ Guchar in[16];
+ int c, i;
+
+ c = EOF; // make gcc happy
+ switch (algo) {
+ case cryptRC4:
+ if (state.rc4.buf == EOF) {
+ c = str->getChar();
+ if (c != EOF) {
+ state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x,
+ &state.rc4.y, (Guchar)c);
+ }
+ }
+ c = state.rc4.buf;
+ break;
+ case cryptAES:
+ if (state.aes.bufIdx == 16) {
+ for (i = 0; i < 16; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ return EOF;
+ }
+ in[i] = c;
+ }
+ aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
+ }
+ if (state.aes.bufIdx == 16) {
+ c = EOF;
+ } else {
+ c = state.aes.buf[state.aes.bufIdx];
+ }
+ break;
+ }
+ return c;
+}
+
+GBool DecryptStream::isBinary(GBool last) {
+ return str->isBinary(last);
+}
+
+//------------------------------------------------------------------------
// RC4-compatible decryption
//------------------------------------------------------------------------
@@ -239,6 +349,261 @@ static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
}
//------------------------------------------------------------------------
+// AES decryption
+//------------------------------------------------------------------------
+
+static Guchar sbox[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+static Guchar invSbox[256] = {
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+static Guint rcon[11] = {
+ 0x00000000, // unused
+ 0x01000000,
+ 0x02000000,
+ 0x04000000,
+ 0x08000000,
+ 0x10000000,
+ 0x20000000,
+ 0x40000000,
+ 0x80000000,
+ 0x1b000000,
+ 0x36000000
+};
+
+static inline Guint subWord(Guint x) {
+ return (sbox[x >> 24] << 24)
+ | (sbox[(x >> 16) & 0xff] << 16)
+ | (sbox[(x >> 8) & 0xff] << 8)
+ | sbox[x & 0xff];
+}
+
+static inline Guint rotWord(Guint x) {
+ return ((x << 8) & 0xffffffff) | (x >> 24);
+}
+
+static inline void invSubBytes(Guchar *state) {
+ int i;
+
+ for (i = 0; i < 16; ++i) {
+ state[i] = invSbox[state[i]];
+ }
+}
+
+static inline void invShiftRows(Guchar *state) {
+ Guchar t;
+
+ t = state[7];
+ state[7] = state[6];
+ state[6] = state[5];
+ state[5] = state[4];
+ state[4] = t;
+
+ t = state[8];
+ state[8] = state[10];
+ state[10] = t;
+ t = state[9];
+ state[9] = state[11];
+ state[11] = t;
+
+ t = state[12];
+ state[12] = state[13];
+ state[13] = state[14];
+ state[14] = state[15];
+ state[15] = t;
+}
+
+// {09} \cdot s
+static inline Guchar mul09(Guchar s) {
+ Guchar s2, s4, s8;
+
+ s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+ s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+ s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+ return s ^ s8;
+}
+
+// {0b} \cdot s
+static inline Guchar mul0b(Guchar s) {
+ Guchar s2, s4, s8;
+
+ s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+ s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+ s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+ return s ^ s2 ^ s8;
+}
+
+// {0d} \cdot s
+static inline Guchar mul0d(Guchar s) {
+ Guchar s2, s4, s8;
+
+ s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+ s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+ s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+ return s ^ s4 ^ s8;
+}
+
+// {0e} \cdot s
+static inline Guchar mul0e(Guchar s) {
+ Guchar s2, s4, s8;
+
+ s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+ s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+ s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+ return s2 ^ s4 ^ s8;
+}
+
+static inline void invMixColumns(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] = mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3);
+ state[4+c] = mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3);
+ state[8+c] = mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3);
+ state[12+c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3);
+ }
+}
+
+static inline void invMixColumnsW(Guint *w) {
+ int c;
+ Guchar s0, s1, s2, s3;
+
+ for (c = 0; c < 4; ++c) {
+ s0 = w[c] >> 24;
+ s1 = w[c] >> 16;
+ s2 = w[c] >> 8;
+ s3 = w[c];
+ w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24)
+ | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16)
+ | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8)
+ | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3));
+ }
+}
+
+static inline void addRoundKey(Guchar *state, Guint *w) {
+ int c;
+
+ for (c = 0; c < 4; ++c) {
+ state[c] ^= w[c] >> 24;
+ state[4+c] ^= w[c] >> 16;
+ state[8+c] ^= w[c] >> 8;
+ state[12+c] ^= w[c];
+ }
+}
+
+static void aesKeyExpansion(DecryptAESState *s,
+ Guchar *objKey, int objKeyLen) {
+ Guint temp;
+ int i, round;
+
+ //~ this assumes objKeyLen == 16
+
+ for (i = 0; i < 4; ++i) {
+ s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) +
+ (objKey[4*i+2] << 8) + objKey[4*i+3];
+ }
+ for (i = 4; i < 44; ++i) {
+ temp = s->w[i-1];
+ if (!(i & 3)) {
+ temp = subWord(rotWord(temp)) ^ rcon[i/4];
+ }
+ s->w[i] = s->w[i-4] ^ temp;
+ }
+ for (round = 1; round <= 9; ++round) {
+ invMixColumnsW(&s->w[round * 4]);
+ }
+}
+
+static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) {
+ int c, round, n, i;
+
+ // initial state
+ for (c = 0; c < 4; ++c) {
+ s->state[c] = in[4*c];
+ s->state[4+c] = in[4*c+1];
+ s->state[8+c] = in[4*c+2];
+ s->state[12+c] = in[4*c+3];
+ }
+
+ // round 0
+ addRoundKey(s->state, &s->w[10 * 4]);
+
+ // rounds 1-9
+ for (round = 9; round >= 1; --round) {
+ invSubBytes(s->state);
+ invShiftRows(s->state);
+ invMixColumns(s->state);
+ addRoundKey(s->state, &s->w[round * 4]);
+ }
+
+ // round 10
+ invSubBytes(s->state);
+ invShiftRows(s->state);
+ addRoundKey(s->state, &s->w[0]);
+
+ // CBC
+ for (c = 0; c < 4; ++c) {
+ s->buf[4*c] = s->state[c] ^ s->cbc[4*c];
+ s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1];
+ s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2];
+ s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3];
+ }
+
+ // save the input block for the next CBC
+ for (i = 0; i < 16; ++i) {
+ s->cbc[i] = in[i];
+ }
+
+ // remove padding
+ s->bufIdx = 0;
+ if (last) {
+ n = s->buf[15];
+ for (i = 15; i >= n; --i) {
+ s->buf[i] = s->buf[i-n];
+ }
+ s->bufIdx = n;
+ }
+}
+
+//------------------------------------------------------------------------
// MD5 message digest
//------------------------------------------------------------------------
diff --git a/Build/source/libs/xpdf/xpdf/Decrypt.h b/Build/source/libs/xpdf/xpdf/Decrypt.h
index 2beba581583..56f34b77f26 100644
--- a/Build/source/libs/xpdf/xpdf/Decrypt.h
+++ b/Build/source/libs/xpdf/xpdf/Decrypt.h
@@ -17,6 +17,8 @@
#include "gtypes.h"
#include "GString.h"
+#include "Object.h"
+#include "Stream.h"
//------------------------------------------------------------------------
// Decrypt
@@ -25,15 +27,6 @@
class Decrypt {
public:
- // Initialize the decryptor object.
- Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
-
- // Reset decryption.
- void reset();
-
- // Decrypt one byte.
- Guchar decryptByte(Guchar c);
-
// Generate a file key. The <fileKey> buffer must have space for at
// least 16 bytes. Checks <ownerPassword> and then <userPassword>
// and returns true if either is correct. Sets <ownerPasswordOk> if
@@ -53,11 +46,50 @@ private:
int permissions, GString *fileID,
GString *userPassword, Guchar *fileKey,
GBool encryptMetadata);
+};
- int objKeyLength;
- Guchar objKey[21];
+//------------------------------------------------------------------------
+// DecryptStream
+//------------------------------------------------------------------------
+
+struct DecryptRC4State {
Guchar state[256];
Guchar x, y;
+ int buf;
+};
+
+struct DecryptAESState {
+ Guint w[44];
+ Guchar state[16];
+ Guchar cbc[16];
+ Guchar buf[16];
+ int bufIdx;
+};
+
+class DecryptStream: public FilterStream {
+public:
+
+ DecryptStream(Stream *strA, Guchar *fileKey,
+ CryptAlgorithm algoA, int keyLength,
+ int objNum, int objGen);
+ virtual ~DecryptStream();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GBool isBinary(GBool last);
+ virtual Stream *getUndecodedStream() { return this; }
+
+private:
+
+ CryptAlgorithm algo;
+ int objKeyLength;
+ Guchar objKey[16 + 9];
+
+ union {
+ DecryptRC4State rc4;
+ DecryptAESState aes;
+ } state;
};
#endif
diff --git a/Build/source/libs/xpdf/xpdf/Function.cc b/Build/source/libs/xpdf/xpdf/Function.cc
index f6996412a8b..a4d51c73821 100644
--- a/Build/source/libs/xpdf/xpdf/Function.cc
+++ b/Build/source/libs/xpdf/xpdf/Function.cc
@@ -190,10 +190,11 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
Object obj1, obj2;
Guint buf, bitMask;
int bits;
- int s;
+ Guint s;
int i;
samples = NULL;
+ sBuf = NULL;
ok = gFalse;
//----- initialize the generic stuff
@@ -204,6 +205,14 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
error(-1, "Type 0 function is missing range");
goto err1;
}
+ if (m > sampledFuncMaxInputs) {
+ error(-1, "Sampled functions with more than %d inputs are unsupported",
+ sampledFuncMaxInputs);
+ goto err1;
+ }
+
+ //----- buffer
+ sBuf = (double *)gmallocn(1 << m, sizeof(double));
//----- get the stream
if (!funcObj->isStream()) {
@@ -239,7 +248,7 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
goto err2;
}
sampleBits = obj1.getInt();
- sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
+ sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
obj1.free();
//----- Encode
@@ -347,12 +356,16 @@ SampledFunction::~SampledFunction() {
if (samples) {
gfree(samples);
}
+ if (sBuf) {
+ gfree(sBuf);
+ }
}
SampledFunction::SampledFunction(SampledFunction *func) {
memcpy(this, func, sizeof(SampledFunction));
samples = (double *)gmallocn(nSamples, sizeof(double));
memcpy(samples, func->samples, nSamples * sizeof(double));
+ sBuf = (double *)gmallocn(1 << m, sizeof(double));
}
void SampledFunction::transform(double *in, double *out) {
@@ -360,7 +373,6 @@ void SampledFunction::transform(double *in, double *out) {
int e[funcMaxInputs][2];
double efrac0[funcMaxInputs];
double efrac1[funcMaxInputs];
- double s[1 << funcMaxInputs];
int i, j, k, idx, t;
// map input values into sample array
@@ -389,18 +401,18 @@ void SampledFunction::transform(double *in, double *out) {
for (k = 0, t = j; k < m; ++k, t >>= 1) {
idx += idxMul[k] * (e[k][t & 1]);
}
- s[j] = samples[idx];
+ sBuf[j] = samples[idx];
}
// do m sets of interpolations
for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
for (k = 0; k < t; k += 2) {
- s[k >> 1] = efrac0[j] * s[k] + efrac1[j] * s[k+1];
+ sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1];
}
}
// map output value to range
- out[i] = s[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
+ out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
if (out[i] < range[i][0]) {
out[i] = range[i][0];
} else if (out[i] > range[i][1]) {
@@ -540,6 +552,7 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
funcs = NULL;
bounds = NULL;
encode = NULL;
+ scale = NULL;
//----- initialize the generic stuff
if (!init(dict)) {
@@ -559,6 +572,7 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
funcs = (Function **)gmallocn(k, sizeof(Function *));
bounds = (double *)gmallocn(k + 1, sizeof(double));
encode = (double *)gmallocn(2 * k, sizeof(double));
+ scale = (double *)gmallocn(k, sizeof(double));
for (i = 0; i < k; ++i) {
funcs[i] = NULL;
}
@@ -609,6 +623,17 @@ StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
}
obj1.free();
+ //----- pre-compute the scale factors
+ for (i = 0; i < k; ++i) {
+ if (bounds[i] == bounds[i+1]) {
+ // avoid a divide-by-zero -- in this situation, function i will
+ // never be used anyway
+ scale[i] = 0;
+ } else {
+ scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
+ }
+ }
+
ok = gTrue;
return;
@@ -630,6 +655,8 @@ StitchingFunction::StitchingFunction(StitchingFunction *func) {
memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
encode = (double *)gmallocn(2 * k, sizeof(double));
memcpy(encode, func->encode, 2 * k * sizeof(double));
+ scale = (double *)gmallocn(k, sizeof(double));
+ memcpy(scale, func->scale, k * sizeof(double));
ok = gTrue;
}
@@ -646,6 +673,7 @@ StitchingFunction::~StitchingFunction() {
gfree(funcs);
gfree(bounds);
gfree(encode);
+ gfree(scale);
}
void StitchingFunction::transform(double *in, double *out) {
@@ -664,8 +692,7 @@ void StitchingFunction::transform(double *in, double *out) {
break;
}
}
- x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
- (encode[2*i+1] - encode[2*i]);
+ x = encode[2*i] + (x - bounds[i]) * scale[i];
funcs[i]->transform(&x, out);
}
@@ -1180,14 +1207,25 @@ GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
GString *PostScriptFunction::getToken(Stream *str) {
GString *s;
int c;
+ GBool comment;
s = new GString();
- do {
- c = str->getChar();
- if (c != EOF) {
- codeString->append(c);
+ comment = gFalse;
+ while (1) {
+ if ((c = str->getChar()) == EOF) {
+ break;
}
- } while (c != EOF && isspace(c));
+ codeString->append(c);
+ if (comment) {
+ if (c == '\x0a' || c == '\x0d') {
+ comment = gFalse;
+ }
+ } else if (c == '%') {
+ comment = gTrue;
+ } else if (!isspace(c)) {
+ break;
+ }
+ }
if (c == '{' || c == '}') {
s->append((char)c);
} else if (isdigit(c) || c == '.' || c == '-') {
diff --git a/Build/source/libs/xpdf/xpdf/Function.h b/Build/source/libs/xpdf/xpdf/Function.h
index bfaf83e300e..334a4390fa1 100644
--- a/Build/source/libs/xpdf/xpdf/Function.h
+++ b/Build/source/libs/xpdf/xpdf/Function.h
@@ -27,8 +27,9 @@ class PSStack;
// Function
//------------------------------------------------------------------------
-#define funcMaxInputs 8
-#define funcMaxOutputs 32
+#define funcMaxInputs 32
+#define funcMaxOutputs 32
+#define sampledFuncMaxInputs 16
class Function {
public:
@@ -131,6 +132,7 @@ private:
int idxMul[funcMaxInputs]; // sample array index multipliers
double *samples; // the samples
int nSamples; // size of the samples array
+ double *sBuf; // buffer for the transform function
GBool ok;
};
@@ -180,6 +182,7 @@ public:
Function *getFunc(int i) { return funcs[i]; }
double *getBounds() { return bounds; }
double *getEncode() { return encode; }
+ double *getScale() { return scale; }
private:
@@ -189,6 +192,7 @@ private:
Function **funcs;
double *bounds;
double *encode;
+ double *scale;
GBool ok;
};
diff --git a/Build/source/libs/xpdf/xpdf/GfxFont.cc b/Build/source/libs/xpdf/xpdf/GfxFont.cc
index a4581c0ff35..9af7efcf8c6 100644
--- a/Build/source/libs/xpdf/xpdf/GfxFont.cc
+++ b/Build/source/libs/xpdf/xpdf/GfxFont.cc
@@ -235,6 +235,19 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
error(-1, "Mismatch between font type and embedded font file");
}
type = fontCIDType0C;
+ } else if (obj4.isName("OpenType")) {
+ embFontID = obj2.getRef();
+ if (type == fontTrueType) {
+ type = fontTrueTypeOT;
+ } else if (type == fontType1) {
+ type = fontType1COT;
+ } else if (type == fontCIDType0) {
+ type = fontCIDType0COT;
+ } else if (type == fontCIDType2) {
+ type = fontCIDType2OT;
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
} else {
error(-1, "Unknown embedded font type '%s'",
obj4.isName() ? obj4.getName() : "???");
@@ -751,6 +764,15 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
}
}
+
+ // if the 'mapUnknownCharNames' flag is set, do a simple pass-through
+ // mapping for unknown character names
+ } else if (missing && globalParams->getMapUnknownCharNames()) {
+ for (code = 0; code < 256; ++code) {
+ if (!toUnicode[code]) {
+ toUnicode[code] = code;
+ }
+ }
}
// construct the char code -> Unicode mapping object
@@ -973,10 +995,10 @@ Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
useMacRoman = gTrue;
}
} else {
- if (macRomanCmap >= 0) {
- cmap = macRomanCmap;
- } else if (msSymbolCmap >= 0) {
+ if (msSymbolCmap >= 0) {
cmap = msSymbolCmap;
+ } else if (macRomanCmap >= 0) {
+ cmap = macRomanCmap;
}
}
diff --git a/Build/source/libs/xpdf/xpdf/GfxFont.h b/Build/source/libs/xpdf/xpdf/GfxFont.h
index 62dfd0881ad..d076692fc86 100644
--- a/Build/source/libs/xpdf/xpdf/GfxFont.h
+++ b/Build/source/libs/xpdf/xpdf/GfxFont.h
@@ -35,12 +35,16 @@ enum GfxFontType {
fontUnknownType,
fontType1,
fontType1C,
+ fontType1COT,
fontType3,
fontTrueType,
+ fontTrueTypeOT,
//----- GfxCIDFont
fontCIDType0,
fontCIDType0C,
- fontCIDType2
+ fontCIDType0COT,
+ fontCIDType2,
+ fontCIDType2OT
};
//------------------------------------------------------------------------
@@ -127,6 +131,7 @@ public:
GString *getExtFontFile() { return extFontFile; }
// Get font descriptor flags.
+ int getFlags() { return flags; }
GBool isFixedWidth() { return flags & fontFixedWidth; }
GBool isSerif() { return flags & fontSerif; }
GBool isSymbolic() { return flags & fontSymbolic; }
diff --git a/Build/source/libs/xpdf/xpdf/GfxState.cc b/Build/source/libs/xpdf/xpdf/GfxState.cc
index 051c7b645c8..67b4f6fd92d 100644
--- a/Build/source/libs/xpdf/xpdf/GfxState.cc
+++ b/Build/source/libs/xpdf/xpdf/GfxState.cc
@@ -34,10 +34,12 @@ static inline double clip01(double x) {
//------------------------------------------------------------------------
-static struct {
+struct GfxBlendModeInfo {
char *name;
GfxBlendMode mode;
-} gfxBlendModeNames[] = {
+};
+
+static GfxBlendModeInfo gfxBlendModeNames[] = {
{ "Normal", gfxBlendNormal },
{ "Compatible", gfxBlendNormal },
{ "Multiply", gfxBlendMultiply },
@@ -58,7 +60,7 @@ static struct {
};
#define nGfxBlendModeNames \
- ((int)((sizeof(gfxBlendModeNames) / sizeof(char *))))
+ ((int)((sizeof(gfxBlendModeNames) / sizeof(GfxBlendModeInfo))))
//------------------------------------------------------------------------
@@ -186,6 +188,10 @@ void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = clip01(gfxColorComp1 - color->c[0]);
}
+void GfxDeviceGrayColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+}
+
//------------------------------------------------------------------------
// GfxCalGrayColorSpace
//------------------------------------------------------------------------
@@ -271,6 +277,10 @@ void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = clip01(gfxColorComp1 - color->c[0]);
}
+void GfxCalGrayColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+}
+
//------------------------------------------------------------------------
// GfxDeviceRGBColorSpace
//------------------------------------------------------------------------
@@ -316,6 +326,12 @@ void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = k;
}
+void GfxDeviceRGBColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+ color->c[1] = 0;
+ color->c[2] = 0;
+}
+
//------------------------------------------------------------------------
// GfxCalRGBColorSpace
//------------------------------------------------------------------------
@@ -447,6 +463,12 @@ void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = k;
}
+void GfxCalRGBColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+ color->c[1] = 0;
+ color->c[2] = 0;
+}
+
//------------------------------------------------------------------------
// GfxDeviceCMYKColorSpace
//------------------------------------------------------------------------
@@ -537,6 +559,13 @@ void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = clip01(color->c[3]);
}
+void GfxDeviceCMYKColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+ color->c[1] = 0;
+ color->c[2] = 0;
+ color->c[3] = gfxColorComp1;
+}
+
//------------------------------------------------------------------------
// GfxLabColorSpace
//------------------------------------------------------------------------
@@ -714,6 +743,24 @@ void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = k;
}
+void GfxLabColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+ if (aMin > 0) {
+ color->c[1] = dblToCol(aMin);
+ } else if (aMax < 0) {
+ color->c[1] = dblToCol(aMax);
+ } else {
+ color->c[1] = 0;
+ }
+ if (bMin > 0) {
+ color->c[2] = dblToCol(bMin);
+ } else if (bMax < 0) {
+ color->c[2] = dblToCol(bMax);
+ } else {
+ color->c[2] = 0;
+ }
+}
+
void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
int maxImgPixel) {
decodeLow[0] = 0;
@@ -839,6 +886,20 @@ void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
alt->getCMYK(color, cmyk);
}
+void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ if (rangeMin[i] > 0) {
+ color->c[i] = dblToCol(rangeMin[i]);
+ } else if (rangeMax[i] < 0) {
+ color->c[i] = dblToCol(rangeMax[i]);
+ } else {
+ color->c[i] = 0;
+ }
+ }
+}
+
void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
double *decodeRange,
int maxImgPixel) {
@@ -991,6 +1052,10 @@ void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
base->getCMYK(mapColorToBase(color, &color2), cmyk);
}
+void GfxIndexedColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = 0;
+}
+
void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
double *decodeRange,
int maxImgPixel) {
@@ -1008,6 +1073,7 @@ GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
name = nameA;
alt = altA;
func = funcA;
+ nonMarking = !name->cmp("None");
}
GfxSeparationColorSpace::~GfxSeparationColorSpace() {
@@ -1104,6 +1170,10 @@ void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
alt->getCMYK(&color2, cmyk);
}
+void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) {
+ color->c[0] = gfxColorComp1;
+}
+
//------------------------------------------------------------------------
// GfxDeviceNColorSpace
//------------------------------------------------------------------------
@@ -1114,6 +1184,7 @@ GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
nComps = nCompsA;
alt = altA;
func = funcA;
+ nonMarking = gFalse;
}
GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
@@ -1134,6 +1205,7 @@ GfxColorSpace *GfxDeviceNColorSpace::copy() {
for (i = 0; i < nComps; ++i) {
cs->names[i] = names[i]->copy();
}
+ cs->nonMarking = nonMarking;
return cs;
}
@@ -1183,8 +1255,12 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
}
obj1.free();
cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
+ cs->nonMarking = gTrue;
for (i = 0; i < nCompsA; ++i) {
cs->names[i] = namesA[i];
+ if (namesA[i]->cmp("None")) {
+ cs->nonMarking = gFalse;
+ }
}
return cs;
@@ -1245,6 +1321,14 @@ void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
alt->getCMYK(&color2, cmyk);
}
+void GfxDeviceNColorSpace::getDefaultColor(GfxColor *color) {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ color->c[i] = gfxColorComp1;
+ }
+}
+
//------------------------------------------------------------------------
// GfxPatternColorSpace
//------------------------------------------------------------------------
@@ -1300,6 +1384,10 @@ void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->k = 1;
}
+void GfxPatternColorSpace::getDefaultColor(GfxColor *color) {
+ // not used
+}
+
//------------------------------------------------------------------------
// Pattern
//------------------------------------------------------------------------
@@ -3113,6 +3201,11 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
maxPixel = (1 << bits) - 1;
colorSpace = colorSpaceA;
+ // initialize
+ for (k = 0; k < gfxColorMaxComps; ++k) {
+ lookup[k] = NULL;
+ }
+
// get decode map
if (decode->isNull()) {
nComps = colorSpace->getNComps();
@@ -3147,9 +3240,6 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
// Optimization: for Indexed and Separation color spaces (which have
// only one component), we store color values in the lookup table
// rather than component values.
- for (k = 0; k < gfxColorMaxComps; ++k) {
- lookup[k] = NULL;
- }
colorSpace2 = NULL;
nComps2 = 0;
if (colorSpace->getMode() == csIndexed) {
@@ -3506,10 +3596,12 @@ void GfxPath::offset(double dx, double dy) {
// GfxState
//------------------------------------------------------------------------
-GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
int rotateA, GBool upsideDown) {
double kx, ky;
+ hDPI = hDPIA;
+ vDPI = vDPIA;
rotate = rotateA;
px1 = pageBox->x1;
py1 = pageBox->y1;
@@ -3566,6 +3658,7 @@ GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
strokeOpacity = 1;
fillOverprint = gFalse;
strokeOverprint = gFalse;
+ transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL;
lineWidth = 1;
lineDash = NULL;
@@ -3575,6 +3668,7 @@ GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
lineJoin = 0;
lineCap = 0;
miterLimit = 10;
+ strokeAdjust = gFalse;
font = NULL;
fontSize = 0;
@@ -3601,6 +3695,8 @@ GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
}
GfxState::~GfxState() {
+ int i;
+
if (fillColorSpace) {
delete fillColorSpace;
}
@@ -3613,6 +3709,11 @@ GfxState::~GfxState() {
if (strokePattern) {
delete strokePattern;
}
+ for (i = 0; i < 4; ++i) {
+ if (transfer[i]) {
+ delete transfer[i];
+ }
+ }
gfree(lineDash);
if (path) {
// this gets set to NULL by restore()
@@ -3625,6 +3726,8 @@ GfxState::~GfxState() {
// Used for copy();
GfxState::GfxState(GfxState *state) {
+ int i;
+
memcpy(this, state, sizeof(GfxState));
if (fillColorSpace) {
fillColorSpace = state->fillColorSpace->copy();
@@ -3638,6 +3741,11 @@ GfxState::GfxState(GfxState *state) {
if (strokePattern) {
strokePattern = state->strokePattern->copy();
}
+ for (i = 0; i < 4; ++i) {
+ if (transfer[i]) {
+ transfer[i] = state->transfer[i]->copy();
+ }
+ }
if (lineDashLength > 0) {
lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
@@ -3783,6 +3891,15 @@ void GfxState::concatCTM(double a, double b, double c,
}
}
+void GfxState::shiftCTM(double tx, double ty) {
+ ctm[4] += tx;
+ ctm[5] += ty;
+ clipXMin += tx;
+ clipYMin += ty;
+ clipXMax += tx;
+ clipYMax += ty;
+}
+
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
if (fillColorSpace) {
delete fillColorSpace;
@@ -3811,6 +3928,17 @@ void GfxState::setStrokePattern(GfxPattern *pattern) {
strokePattern = pattern;
}
+void GfxState::setTransfer(Function **funcs) {
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ if (transfer[i]) {
+ delete transfer[i];
+ }
+ transfer[i] = funcs[i];
+ }
+}
+
void GfxState::setLineDash(double *dash, int length, double start) {
if (lineDash)
gfree(lineDash);
@@ -3865,6 +3993,69 @@ void GfxState::clip() {
}
}
+void GfxState::clipToStrokePath() {
+ double xMin, yMin, xMax, yMax, x, y, t0, t1;
+ GfxSubpath *subpath;
+ int i, j;
+
+ xMin = xMax = yMin = yMax = 0; // make gcc happy
+ for (i = 0; i < path->getNumSubpaths(); ++i) {
+ subpath = path->getSubpath(i);
+ for (j = 0; j < subpath->getNumPoints(); ++j) {
+ transform(subpath->getX(j), subpath->getY(j), &x, &y);
+ if (i == 0 && j == 0) {
+ xMin = xMax = x;
+ yMin = yMax = y;
+ } else {
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ }
+ }
+ }
+
+ // allow for the line width
+ //~ miter joins can extend farther than this
+ t0 = fabs(ctm[0]);
+ t1 = fabs(ctm[2]);
+ if (t0 > t1) {
+ xMin -= 0.5 * lineWidth * t0;
+ xMax += 0.5 * lineWidth * t0;
+ } else {
+ xMin -= 0.5 * lineWidth * t1;
+ xMax += 0.5 * lineWidth * t1;
+ }
+ t0 = fabs(ctm[0]);
+ t1 = fabs(ctm[3]);
+ if (t0 > t1) {
+ yMin -= 0.5 * lineWidth * t0;
+ yMax += 0.5 * lineWidth * t0;
+ } else {
+ yMin -= 0.5 * lineWidth * t1;
+ yMax += 0.5 * lineWidth * t1;
+ }
+
+ if (xMin > clipXMin) {
+ clipXMin = xMin;
+ }
+ if (yMin > clipYMin) {
+ clipYMin = yMin;
+ }
+ if (xMax < clipXMax) {
+ clipXMax = xMax;
+ }
+ if (yMax < clipYMax) {
+ clipYMax = yMax;
+ }
+}
+
void GfxState::textShift(double tx, double ty) {
double dx, dy;
diff --git a/Build/source/libs/xpdf/xpdf/GfxState.h b/Build/source/libs/xpdf/xpdf/GfxState.h
index e1d68013dfc..f85643dcc63 100644
--- a/Build/source/libs/xpdf/xpdf/GfxState.h
+++ b/Build/source/libs/xpdf/xpdf/GfxState.h
@@ -148,11 +148,18 @@ public:
// Return the number of color components.
virtual int getNComps() = 0;
+ // Get this color space's default color.
+ virtual void getDefaultColor(GfxColor *color) = 0;
+
// Return the default ranges for each component, assuming an image
// with a max pixel value of <maxImgPixel>.
virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
int maxImgPixel);
+ // Returns true if painting operations in this color space never
+ // mark the page (e.g., the "None" colorant).
+ virtual GBool isNonMarking() { return gFalse; }
+
// Return the number of color space modes
static int getNumColorSpaceModes();
@@ -179,6 +186,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 1; }
+ virtual void getDefaultColor(GfxColor *color);
private:
};
@@ -203,6 +211,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 1; }
+ virtual void getDefaultColor(GfxColor *color);
// CalGray-specific access.
double getWhiteX() { return whiteX; }
@@ -237,6 +246,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 3; }
+ virtual void getDefaultColor(GfxColor *color);
private:
};
@@ -261,6 +271,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 3; }
+ virtual void getDefaultColor(GfxColor *color);
// CalRGB-specific access.
double getWhiteX() { return whiteX; }
@@ -299,6 +310,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 4; }
+ virtual void getDefaultColor(GfxColor *color);
private:
};
@@ -323,6 +335,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 3; }
+ virtual void getDefaultColor(GfxColor *color);
virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
int maxImgPixel);
@@ -368,6 +381,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return nComps; }
+ virtual void getDefaultColor(GfxColor *color);
virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
int maxImgPixel);
@@ -404,6 +418,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 1; }
+ virtual void getDefaultColor(GfxColor *color);
virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
int maxImgPixel);
@@ -442,6 +457,9 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 1; }
+ virtual void getDefaultColor(GfxColor *color);
+
+ virtual GBool isNonMarking() { return nonMarking; }
// Separation-specific access.
GString *getName() { return name; }
@@ -453,6 +471,7 @@ private:
GString *name; // colorant name
GfxColorSpace *alt; // alternate color space
Function *func; // tint transform (into alternate color space)
+ GBool nonMarking;
};
//------------------------------------------------------------------------
@@ -475,6 +494,9 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return nComps; }
+ virtual void getDefaultColor(GfxColor *color);
+
+ virtual GBool isNonMarking() { return nonMarking; }
// DeviceN-specific access.
GString *getColorantName(int i) { return names[i]; }
@@ -488,6 +510,7 @@ private:
*names[gfxColorMaxComps];
GfxColorSpace *alt; // alternate color space
Function *func; // tint transform (into alternate color space)
+ GBool nonMarking;
};
//------------------------------------------------------------------------
@@ -510,6 +533,7 @@ public:
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual int getNComps() { return 0; }
+ virtual void getDefaultColor(GfxColor *color);
// Pattern-specific access.
GfxColorSpace *getUnder() { return under; }
@@ -992,7 +1016,7 @@ public:
// Construct a default GfxState, for a device with resolution <hDPI>
// x <vDPI>, page box <pageBox>, page rotation <rotateA>, and
// coordinate system specified by <upsideDown>.
- GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+ GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
int rotateA, GBool upsideDown);
// Destructor.
@@ -1002,6 +1026,8 @@ public:
GfxState *copy() { return new GfxState(this); }
// Accessors.
+ double getHDPI() { return hDPI; }
+ double getVDPI() { return vDPI; }
double *getCTM() { return ctm; }
double getX1() { return px1; }
double getY1() { return py1; }
@@ -1033,6 +1059,7 @@ public:
double getStrokeOpacity() { return strokeOpacity; }
GBool getFillOverprint() { return fillOverprint; }
GBool getStrokeOverprint() { return strokeOverprint; }
+ Function **getTransfer() { return transfer; }
double getLineWidth() { return lineWidth; }
void getLineDash(double **dash, int *length, double *start)
{ *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
@@ -1040,6 +1067,7 @@ public:
int getLineJoin() { return lineJoin; }
int getLineCap() { return lineCap; }
double getMiterLimit() { return miterLimit; }
+ GBool getStrokeAdjust() { return strokeAdjust; }
GfxFont *getFont() { return font; }
double getFontSize() { return fontSize; }
double *getTextMat() { return textMat; }
@@ -1087,6 +1115,7 @@ public:
double d, double e, double f);
void concatCTM(double a, double b, double c,
double d, double e, double f);
+ void shiftCTM(double tx, double ty);
void setFillColorSpace(GfxColorSpace *colorSpace);
void setStrokeColorSpace(GfxColorSpace *colorSpace);
void setFillColor(GfxColor *color) { fillColor = *color; }
@@ -1098,12 +1127,14 @@ public:
void setStrokeOpacity(double opac) { strokeOpacity = opac; }
void setFillOverprint(GBool op) { fillOverprint = op; }
void setStrokeOverprint(GBool op) { strokeOverprint = op; }
+ void setTransfer(Function **funcs);
void setLineWidth(double width) { lineWidth = width; }
void setLineDash(double *dash, int length, double start);
void setFlatness(int flatness1) { flatness = flatness1; }
void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
void setLineCap(int lineCap1) { lineCap = lineCap1; }
void setMiterLimit(double limit) { miterLimit = limit; }
+ void setStrokeAdjust(GBool sa) { strokeAdjust = sa; }
void setFont(GfxFont *fontA, double fontSizeA)
{ font = fontA; fontSize = fontSizeA; }
void setTextMat(double a, double b, double c,
@@ -1137,6 +1168,7 @@ public:
// Update clip region.
void clip();
+ void clipToStrokePath();
// Text position.
void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
@@ -1155,6 +1187,7 @@ public:
private:
+ double hDPI, vDPI; // resolution
double ctm[6]; // coord transform matrix
double px1, py1, px2, py2; // page corners (user coords)
double pageWidth, pageHeight; // page size (pixels)
@@ -1171,6 +1204,10 @@ private:
double strokeOpacity; // stroke opacity
GBool fillOverprint; // fill overprint
GBool strokeOverprint; // stroke overprint
+ Function *transfer[4]; // transfer function (entries may be: all
+ // NULL = identity; last three NULL =
+ // single function; all four non-NULL =
+ // R,G,B,gray functions)
double lineWidth; // line width
double *lineDash; // line dash
@@ -1180,6 +1217,7 @@ private:
int lineJoin; // line join style
int lineCap; // line cap style
double miterLimit; // line miter limit
+ GBool strokeAdjust; // stroke adjustment
GfxFont *font; // font
double fontSize; // font size
diff --git a/Build/source/libs/xpdf/xpdf/GlobalParams.cc b/Build/source/libs/xpdf/xpdf/GlobalParams.cc
index 7d4013818e4..2b07a1964fd 100644
--- a/Build/source/libs/xpdf/xpdf/GlobalParams.cc
+++ b/Build/source/libs/xpdf/xpdf/GlobalParams.cc
@@ -43,6 +43,10 @@
#endif
#include "GlobalParams.h"
+#ifdef WIN32
+# define strcasecmp stricmp
+#endif
+
#if MULTITHREADED
# define lockGlobalParams gLockMutex(&mutex)
# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
@@ -153,6 +157,251 @@ DisplayFontParam::~DisplayFontParam() {
}
}
+#ifdef WIN32
+
+//------------------------------------------------------------------------
+// WinFontInfo
+//------------------------------------------------------------------------
+
+class WinFontInfo: public DisplayFontParam {
+public:
+
+ GBool bold, italic;
+
+ static WinFontInfo *make(GString *nameA, GBool boldA, GBool italicA,
+ HKEY regKey, char *winFontDir);
+ WinFontInfo(GString *nameA, GBool boldA, GBool italicA,
+ GString *fileNameA);
+ virtual ~WinFontInfo();
+ GBool equals(WinFontInfo *fi);
+};
+
+WinFontInfo *WinFontInfo::make(GString *nameA, GBool boldA, GBool italicA,
+ HKEY regKey, char *winFontDir) {
+ GString *regName;
+ GString *fileNameA;
+ char buf[MAX_PATH];
+ DWORD n;
+ char c;
+ int i;
+
+ //----- find the font file
+ fileNameA = NULL;
+ regName = nameA->copy();
+ if (boldA) {
+ regName->append(" Bold");
+ }
+ if (italicA) {
+ regName->append(" Italic");
+ }
+ regName->append(" (TrueType)");
+ n = sizeof(buf);
+ if (RegQueryValueEx(regKey, regName->getCString(), NULL, NULL,
+ (LPBYTE)buf, &n) == ERROR_SUCCESS) {
+ fileNameA = new GString(winFontDir);
+ fileNameA->append('\\')->append(buf);
+ }
+ delete regName;
+ if (!fileNameA) {
+ delete nameA;
+ return NULL;
+ }
+
+ //----- normalize the font name
+ i = 0;
+ while (i < nameA->getLength()) {
+ c = nameA->getChar(i);
+ if (c == ' ' || c == ',' || c == '-') {
+ nameA->del(i);
+ } else {
+ ++i;
+ }
+ }
+
+ return new WinFontInfo(nameA, boldA, italicA, fileNameA);
+}
+
+WinFontInfo::WinFontInfo(GString *nameA, GBool boldA, GBool italicA,
+ GString *fileNameA):
+ DisplayFontParam(nameA, displayFontTT)
+{
+ bold = boldA;
+ italic = italicA;
+ tt.fileName = fileNameA;
+}
+
+WinFontInfo::~WinFontInfo() {
+}
+
+GBool WinFontInfo::equals(WinFontInfo *fi) {
+ return !name->cmp(fi->name) && bold == fi->bold && italic == fi->italic;
+}
+
+//------------------------------------------------------------------------
+// WinFontList
+//------------------------------------------------------------------------
+
+class WinFontList {
+public:
+
+ WinFontList(char *winFontDirA);
+ ~WinFontList();
+ WinFontInfo *find(GString *font);
+
+private:
+
+ void add(WinFontInfo *fi);
+ static int CALLBACK enumFunc1(CONST LOGFONT *font,
+ CONST TEXTMETRIC *metrics,
+ DWORD type, LPARAM data);
+ static int CALLBACK enumFunc2(CONST LOGFONT *font,
+ CONST TEXTMETRIC *metrics,
+ DWORD type, LPARAM data);
+
+ GList *fonts; // [WinFontInfo]
+ HDC dc; // (only used during enumeration)
+ HKEY regKey; // (only used during enumeration)
+ char *winFontDir; // (only used during enumeration)
+};
+
+WinFontList::WinFontList(char *winFontDirA) {
+ OSVERSIONINFO version;
+ char *path;
+
+ fonts = new GList();
+ dc = GetDC(NULL);
+ winFontDir = winFontDirA;
+ version.dwOSVersionInfoSize = sizeof(version);
+ GetVersionEx(&version);
+ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\";
+ } else {
+ path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\";
+ }
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
+ KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
+ &regKey) == ERROR_SUCCESS) {
+ EnumFonts(dc, NULL, &WinFontList::enumFunc1, (LPARAM)this);
+ RegCloseKey(regKey);
+ }
+ ReleaseDC(NULL, dc);
+}
+
+WinFontList::~WinFontList() {
+ deleteGList(fonts, WinFontInfo);
+}
+
+void WinFontList::add(WinFontInfo *fi) {
+ int i;
+
+ for (i = 0; i < fonts->getLength(); ++i) {
+ if (((WinFontInfo *)fonts->get(i))->equals(fi)) {
+ delete fi;
+ return;
+ }
+ }
+ fonts->append(fi);
+}
+
+WinFontInfo *WinFontList::find(GString *font) {
+ GString *name;
+ GBool bold, italic;
+ WinFontInfo *fi;
+ char c;
+ int n, i;
+
+ name = font->copy();
+
+ // remove space, comma, dash chars
+ i = 0;
+ while (i < name->getLength()) {
+ c = name->getChar(i);
+ if (c == ' ' || c == ',' || c == '-') {
+ name->del(i);
+ } else {
+ ++i;
+ }
+ }
+ n = name->getLength();
+
+ // remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.)
+ if (!strcmp(name->getCString() + n - 2, "MT")) {
+ name->del(n - 2, 2);
+ n -= 2;
+ }
+
+ // look for "Italic"
+ if (!strcmp(name->getCString() + n - 6, "Italic")) {
+ name->del(n - 6, 6);
+ italic = gTrue;
+ n -= 6;
+ } else {
+ italic = gFalse;
+ }
+
+ // look for "Bold"
+ if (!strcmp(name->getCString() + n - 4, "Bold")) {
+ name->del(n - 4, 4);
+ bold = gTrue;
+ n -= 4;
+ } else {
+ bold = gFalse;
+ }
+
+ // remove trailing "MT" (FooMT-Bold, etc.)
+ if (!strcmp(name->getCString() + n - 2, "MT")) {
+ name->del(n - 2, 2);
+ n -= 2;
+ }
+
+ // remove trailing "PS"
+ if (!strcmp(name->getCString() + n - 2, "PS")) {
+ name->del(n - 2, 2);
+ n -= 2;
+ }
+
+ // search for the font
+ fi = NULL;
+ for (i = 0; i < fonts->getLength(); ++i) {
+ fi = (WinFontInfo *)fonts->get(i);
+ if (!fi->name->cmp(name) && fi->bold == bold && fi->italic == italic) {
+ break;
+ }
+ fi = NULL;
+ }
+
+ delete name;
+ return fi;
+}
+
+int CALLBACK WinFontList::enumFunc1(CONST LOGFONT *font,
+ CONST TEXTMETRIC *metrics,
+ DWORD type, LPARAM data) {
+ WinFontList *fl = (WinFontList *)data;
+
+ EnumFonts(fl->dc, font->lfFaceName, &WinFontList::enumFunc2, (LPARAM)fl);
+ return 1;
+}
+
+int CALLBACK WinFontList::enumFunc2(CONST LOGFONT *font,
+ CONST TEXTMETRIC *metrics,
+ DWORD type, LPARAM data) {
+ WinFontList *fl = (WinFontList *)data;
+ WinFontInfo *fi;
+
+ if (type & TRUETYPE_FONTTYPE) {
+ if ((fi = WinFontInfo::make(new GString(font->lfFaceName),
+ font->lfWeight >= 600,
+ font->lfItalic ? gTrue : gFalse,
+ fl->regKey, fl->winFontDir))) {
+ fl->add(fi);
+ }
+ }
+ return 1;
+}
+
+#endif // WIN32
+
//------------------------------------------------------------------------
// PSFontParam
//------------------------------------------------------------------------
@@ -173,6 +422,41 @@ PSFontParam::~PSFontParam() {
}
}
+#ifndef PDF_PARSER_ONLY
+//------------------------------------------------------------------------
+// KeyBinding
+//------------------------------------------------------------------------
+
+KeyBinding::KeyBinding(int codeA, int modsA, int contextA, char *cmd0) {
+ code = codeA;
+ mods = modsA;
+ context = contextA;
+ cmds = new GList();
+ cmds->append(new GString(cmd0));
+}
+
+KeyBinding::KeyBinding(int codeA, int modsA, int contextA,
+ char *cmd0, char *cmd1) {
+ code = codeA;
+ mods = modsA;
+ context = contextA;
+ cmds = new GList();
+ cmds->append(new GString(cmd0));
+ cmds->append(new GString(cmd1));
+}
+
+KeyBinding::KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA) {
+ code = codeA;
+ mods = modsA;
+ context = contextA;
+ cmds = cmdsA;
+}
+
+KeyBinding::~KeyBinding() {
+ deleteGList(cmds, GString);
+}
+#endif
+
#ifdef ENABLE_PLUGINS
//------------------------------------------------------------------------
// Plugin
@@ -525,6 +809,7 @@ GlobalParams::GlobalParams(char *cfgFileName) {
psEmbedTrueType = gTrue;
psEmbedCIDPostScript = gTrue;
psEmbedCIDTrueType = gTrue;
+ psPreload = gFalse;
psOPI = gFalse;
psASCIIHex = gFalse;
textEncoding = new GString("Latin1");
@@ -543,9 +828,21 @@ GlobalParams::GlobalParams(char *cfgFileName) {
enableT1lib = gTrue;
enableFreeType = gTrue;
antialias = gTrue;
+ vectorAntialias = gTrue;
+ strokeAdjust = gTrue;
+ screenType = screenUnset;
+ screenSize = -1;
+ screenDotRadius = -1;
+ screenGamma = 1.0;
+ screenBlackThreshold = 0.0;
+ screenWhiteThreshold = 1.0;
urlCommand = NULL;
movieCommand = NULL;
mapNumericCharNames = gTrue;
+ mapUnknownCharNames = gFalse;
+#ifndef PDF_PARSER_ONLY
+ createDefaultKeyBindings();
+#endif
printCommands = gFalse;
errQuiet = gFalse;
@@ -555,6 +852,10 @@ GlobalParams::GlobalParams(char *cfgFileName) {
unicodeMapCache = new UnicodeMapCache();
cMapCache = new CMapCache();
+#ifdef WIN32
+ winFontList = NULL;
+#endif
+
#ifdef ENABLE_PLUGINS
plugins = new GList();
securityHandlers = new GList();
@@ -616,180 +917,342 @@ GlobalParams::GlobalParams(char *cfgFileName) {
}
}
if (f) {
+#ifndef PDF_PARSER_ONLY
parseFile(fileName, f);
+#endif
delete fileName;
fclose(f);
}
}
+#ifndef PDF_PARSER_ONLY
+void GlobalParams::createDefaultKeyBindings() {
+ keyBindings = new GList();
+
+ //----- mouse buttons
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModNone,
+ xpdfKeyContextAny, "startSelection"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModNone,
+ xpdfKeyContextAny, "endSelection",
+ "followLinkNoSel"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress2, xpdfKeyModNone,
+ xpdfKeyContextAny, "startPan"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease2, xpdfKeyModNone,
+ xpdfKeyContextAny, "endPan"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress3, xpdfKeyModNone,
+ xpdfKeyContextAny, "postPopupMenu"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress4, xpdfKeyModNone,
+ xpdfKeyContextAny,
+ "scrollUpPrevPage(16)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress5, xpdfKeyModNone,
+ xpdfKeyContextAny,
+ "scrollDownNextPage(16)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress6, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollLeft(16)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress7, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollRight(16)"));
+
+ //----- keys
+ keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModCtrl,
+ xpdfKeyContextAny, "gotoPage(1)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollToTopLeft"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModCtrl,
+ xpdfKeyContextAny, "gotoLastPage"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModNone,
+ xpdfKeyContextAny,
+ "scrollToBottomRight"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModNone,
+ xpdfKeyContextAny, "pageUp"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeBackspace, xpdfKeyModNone,
+ xpdfKeyContextAny, "pageUp"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeDelete, xpdfKeyModNone,
+ xpdfKeyContextAny, "pageUp"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModNone,
+ xpdfKeyContextAny, "pageDown"));
+ keyBindings->append(new KeyBinding(' ', xpdfKeyModNone,
+ xpdfKeyContextAny, "pageDown"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeLeft, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollLeft(16)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeRight, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollRight(16)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollUp(16)"));
+ keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModNone,
+ xpdfKeyContextAny, "scrollDown(16)"));
+ keyBindings->append(new KeyBinding('o', xpdfKeyModNone,
+ xpdfKeyContextAny, "open"));
+ keyBindings->append(new KeyBinding('O', xpdfKeyModNone,
+ xpdfKeyContextAny, "open"));
+ keyBindings->append(new KeyBinding('r', xpdfKeyModNone,
+ xpdfKeyContextAny, "reload"));
+ keyBindings->append(new KeyBinding('R', xpdfKeyModNone,
+ xpdfKeyContextAny, "reload"));
+ keyBindings->append(new KeyBinding('f', xpdfKeyModNone,
+ xpdfKeyContextAny, "find"));
+ keyBindings->append(new KeyBinding('F', xpdfKeyModNone,
+ xpdfKeyContextAny, "find"));
+ keyBindings->append(new KeyBinding('f', xpdfKeyModCtrl,
+ xpdfKeyContextAny, "find"));
+ keyBindings->append(new KeyBinding('g', xpdfKeyModCtrl,
+ xpdfKeyContextAny, "findNext"));
+ keyBindings->append(new KeyBinding('p', xpdfKeyModCtrl,
+ xpdfKeyContextAny, "print"));
+ keyBindings->append(new KeyBinding('n', xpdfKeyModNone,
+ xpdfKeyContextScrLockOff, "nextPage"));
+ keyBindings->append(new KeyBinding('N', xpdfKeyModNone,
+ xpdfKeyContextScrLockOff, "nextPage"));
+ keyBindings->append(new KeyBinding('n', xpdfKeyModNone,
+ xpdfKeyContextScrLockOn,
+ "nextPageNoScroll"));
+ keyBindings->append(new KeyBinding('N', xpdfKeyModNone,
+ xpdfKeyContextScrLockOn,
+ "nextPageNoScroll"));
+ keyBindings->append(new KeyBinding('p', xpdfKeyModNone,
+ xpdfKeyContextScrLockOff, "prevPage"));
+ keyBindings->append(new KeyBinding('P', xpdfKeyModNone,
+ xpdfKeyContextScrLockOff, "prevPage"));
+ keyBindings->append(new KeyBinding('p', xpdfKeyModNone,
+ xpdfKeyContextScrLockOn,
+ "prevPageNoScroll"));
+ keyBindings->append(new KeyBinding('P', xpdfKeyModNone,
+ xpdfKeyContextScrLockOn,
+ "prevPageNoScroll"));
+ keyBindings->append(new KeyBinding('v', xpdfKeyModNone,
+ xpdfKeyContextAny, "goForward"));
+ keyBindings->append(new KeyBinding('b', xpdfKeyModNone,
+ xpdfKeyContextAny, "goBackward"));
+ keyBindings->append(new KeyBinding('g', xpdfKeyModNone,
+ xpdfKeyContextAny, "focusToPageNum"));
+ keyBindings->append(new KeyBinding('0', xpdfKeyModNone,
+ xpdfKeyContextAny, "zoomPercent(125)"));
+ keyBindings->append(new KeyBinding('+', xpdfKeyModNone,
+ xpdfKeyContextAny, "zoomIn"));
+ keyBindings->append(new KeyBinding('-', xpdfKeyModNone,
+ xpdfKeyContextAny, "zoomOut"));
+ keyBindings->append(new KeyBinding('z', xpdfKeyModNone,
+ xpdfKeyContextAny, "zoomFitPage"));
+ keyBindings->append(new KeyBinding('w', xpdfKeyModNone,
+ xpdfKeyContextAny, "zoomFitWidth"));
+ keyBindings->append(new KeyBinding('f', xpdfKeyModAlt,
+ xpdfKeyContextAny,
+ "toggleFullScreenMode"));
+ keyBindings->append(new KeyBinding('l', xpdfKeyModCtrl,
+ xpdfKeyContextAny, "redraw"));
+ keyBindings->append(new KeyBinding('w', xpdfKeyModCtrl,
+ xpdfKeyContextAny, "closeWindow"));
+ keyBindings->append(new KeyBinding('?', xpdfKeyModNone,
+ xpdfKeyContextAny, "about"));
+ keyBindings->append(new KeyBinding('q', xpdfKeyModNone,
+ xpdfKeyContextAny, "quit"));
+ keyBindings->append(new KeyBinding('Q', xpdfKeyModNone,
+ xpdfKeyContextAny, "quit"));
+}
+
void GlobalParams::parseFile(GString *fileName, FILE *f) {
int line;
- GList *tokens;
- GString *cmd, *incFile;
- char *p1, *p2;
char buf[512];
- FILE *f2;
line = 1;
while (getLine(buf, sizeof(buf) - 1, f)) {
+ parseLine(buf, fileName, line);
+ ++line;
+ }
+}
- // break the line into tokens
- tokens = new GList();
- p1 = buf;
- while (*p1) {
- for (; *p1 && isspace(*p1); ++p1) ;
- if (!*p1) {
- break;
- }
- if (*p1 == '"' || *p1 == '\'') {
- for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
- ++p1;
- } else {
- for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
- }
- tokens->append(new GString(p1, p2 - p1));
- p1 = *p2 ? p2 + 1 : p2;
- }
+void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
+ GList *tokens;
+ GString *cmd, *incFile;
+ char *p1, *p2;
+ FILE *f2;
- if (tokens->getLength() > 0 &&
- ((GString *)tokens->get(0))->getChar(0) != '#') {
- cmd = (GString *)tokens->get(0);
- if (!cmd->cmp("include")) {
- if (tokens->getLength() == 2) {
- incFile = (GString *)tokens->get(1);
- if ((f2 = fopen(incFile->getCString(), "r"))) {
- parseFile(incFile, f2);
- fclose(f2);
- } else {
- error(-1, "Couldn't find included config file: '%s' (%s:%d)",
- incFile->getCString(), fileName->getCString(), line);
- }
+ // break the line into tokens
+ tokens = new GList();
+ p1 = buf;
+ while (*p1) {
+ for (; *p1 && isspace(*p1); ++p1) ;
+ if (!*p1) {
+ break;
+ }
+ if (*p1 == '"' || *p1 == '\'') {
+ for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
+ ++p1;
+ } else {
+ for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
+ }
+ tokens->append(new GString(p1, p2 - p1));
+ p1 = *p2 ? p2 + 1 : p2;
+ }
+
+ // parse the line
+ if (tokens->getLength() > 0 &&
+ ((GString *)tokens->get(0))->getChar(0) != '#') {
+ cmd = (GString *)tokens->get(0);
+ if (!cmd->cmp("include")) {
+ if (tokens->getLength() == 2) {
+ incFile = (GString *)tokens->get(1);
+ if ((f2 = fopen(incFile->getCString(), "r"))) {
+ parseFile(incFile, f2);
+ fclose(f2);
} else {
- error(-1, "Bad 'include' config file command (%s:%d)",
- fileName->getCString(), line);
+ error(-1, "Couldn't find included config file: '%s' (%s:%d)",
+ incFile->getCString(), fileName->getCString(), line);
}
- } else if (!cmd->cmp("nameToUnicode")) {
- parseNameToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("cidToUnicode")) {
- parseCIDToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("unicodeToUnicode")) {
- parseUnicodeToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("unicodeMap")) {
- parseUnicodeMap(tokens, fileName, line);
- } else if (!cmd->cmp("cMapDir")) {
- parseCMapDir(tokens, fileName, line);
- } else if (!cmd->cmp("toUnicodeDir")) {
- parseToUnicodeDir(tokens, fileName, line);
- } else if (!cmd->cmp("displayFontT1")) {
- parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayFontTT")) {
- parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
- } else if (!cmd->cmp("displayNamedCIDFontT1")) {
- parseDisplayFont(tokens, displayNamedCIDFonts,
- displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayCIDFontT1")) {
- parseDisplayFont(tokens, displayCIDFonts,
- displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayNamedCIDFontTT")) {
- parseDisplayFont(tokens, displayNamedCIDFonts,
- displayFontTT, fileName, line);
- } else if (!cmd->cmp("displayCIDFontTT")) {
- parseDisplayFont(tokens, displayCIDFonts,
- displayFontTT, fileName, line);
- } else if (!cmd->cmp("psFile")) {
- parsePSFile(tokens, fileName, line);
- } else if (!cmd->cmp("psFont")) {
- parsePSFont(tokens, fileName, line);
- } else if (!cmd->cmp("psNamedFont16")) {
- parsePSFont16("psNamedFont16", psNamedFonts16,
- tokens, fileName, line);
- } else if (!cmd->cmp("psFont16")) {
- parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
- } else if (!cmd->cmp("psPaperSize")) {
- parsePSPaperSize(tokens, fileName, line);
- } else if (!cmd->cmp("psImageableArea")) {
- parsePSImageableArea(tokens, fileName, line);
- } else if (!cmd->cmp("psCrop")) {
- parseYesNo("psCrop", &psCrop, tokens, fileName, line);
- } else if (!cmd->cmp("psExpandSmaller")) {
- parseYesNo("psExpandSmaller", &psExpandSmaller,
- tokens, fileName, line);
- } else if (!cmd->cmp("psShrinkLarger")) {
- parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
- } else if (!cmd->cmp("psCenter")) {
- parseYesNo("psCenter", &psCenter, tokens, fileName, line);
- } else if (!cmd->cmp("psDuplex")) {
- parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
- } else if (!cmd->cmp("psLevel")) {
- parsePSLevel(tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedType1Fonts")) {
- parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
- parseYesNo("psEmbedTrueType", &psEmbedTrueType,
- tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
- parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
- tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
- parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
- tokens, fileName, line);
- } else if (!cmd->cmp("psOPI")) {
- parseYesNo("psOPI", &psOPI, tokens, fileName, line);
- } else if (!cmd->cmp("psASCIIHex")) {
- parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
- } else if (!cmd->cmp("textEncoding")) {
- parseTextEncoding(tokens, fileName, line);
- } else if (!cmd->cmp("textEOL")) {
- parseTextEOL(tokens, fileName, line);
- } else if (!cmd->cmp("textPageBreaks")) {
- parseYesNo("textPageBreaks", &textPageBreaks,
- tokens, fileName, line);
- } else if (!cmd->cmp("textKeepTinyChars")) {
- parseYesNo("textKeepTinyChars", &textKeepTinyChars,
- tokens, fileName, line);
- } else if (!cmd->cmp("fontDir")) {
- parseFontDir(tokens, fileName, line);
- } else if (!cmd->cmp("initialZoom")) {
- 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("antialias")) {
- parseYesNo("antialias", &antialias, tokens, fileName, line);
- } else if (!cmd->cmp("urlCommand")) {
- parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
- } else if (!cmd->cmp("movieCommand")) {
- parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
- } else if (!cmd->cmp("mapNumericCharNames")) {
- parseYesNo("mapNumericCharNames", &mapNumericCharNames,
- tokens, fileName, line);
- } else if (!cmd->cmp("printCommands")) {
- parseYesNo("printCommands", &printCommands, tokens, fileName, line);
- } else if (!cmd->cmp("errQuiet")) {
- parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
} else {
- error(-1, "Unknown config file command '%s' (%s:%d)",
- cmd->getCString(), fileName->getCString(), line);
- if (!cmd->cmp("displayFontX") ||
- !cmd->cmp("displayNamedCIDFontX") ||
- !cmd->cmp("displayCIDFontX")) {
- error(-1, "-- Xpdf no longer supports X fonts");
- } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
- error(-1, "-- The t1libControl and freetypeControl options have been replaced");
- error(-1, " by the enableT1lib, enableFreeType, and antialias options");
- } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
- error(-1, "-- the config file format has changed since Xpdf 0.9x");
- }
+ error(-1, "Bad 'include' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+ } else if (!cmd->cmp("nameToUnicode")) {
+ parseNameToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("cidToUnicode")) {
+ parseCIDToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("unicodeToUnicode")) {
+ parseUnicodeToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("unicodeMap")) {
+ parseUnicodeMap(tokens, fileName, line);
+ } else if (!cmd->cmp("cMapDir")) {
+ parseCMapDir(tokens, fileName, line);
+ } else if (!cmd->cmp("toUnicodeDir")) {
+ parseToUnicodeDir(tokens, fileName, line);
+ } else if (!cmd->cmp("displayFontT1")) {
+ parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayFontTT")) {
+ parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontT1")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontT1")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontTT")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontTT, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontTT")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontTT, fileName, line);
+ } else if (!cmd->cmp("psFile")) {
+ parsePSFile(tokens, fileName, line);
+ } else if (!cmd->cmp("psFont")) {
+ parsePSFont(tokens, fileName, line);
+ } else if (!cmd->cmp("psNamedFont16")) {
+ parsePSFont16("psNamedFont16", psNamedFonts16,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psFont16")) {
+ parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
+ } else if (!cmd->cmp("psPaperSize")) {
+ parsePSPaperSize(tokens, fileName, line);
+ } else if (!cmd->cmp("psImageableArea")) {
+ parsePSImageableArea(tokens, fileName, line);
+ } else if (!cmd->cmp("psCrop")) {
+ parseYesNo("psCrop", &psCrop, tokens, fileName, line);
+ } else if (!cmd->cmp("psExpandSmaller")) {
+ parseYesNo("psExpandSmaller", &psExpandSmaller,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psShrinkLarger")) {
+ parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
+ } else if (!cmd->cmp("psCenter")) {
+ parseYesNo("psCenter", &psCenter, tokens, fileName, line);
+ } else if (!cmd->cmp("psDuplex")) {
+ parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
+ } else if (!cmd->cmp("psLevel")) {
+ parsePSLevel(tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedType1Fonts")) {
+ parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
+ parseYesNo("psEmbedTrueType", &psEmbedTrueType,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
+ parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
+ parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psPreload")) {
+ parseYesNo("psPreload", &psPreload, tokens, fileName, line);
+ } else if (!cmd->cmp("psOPI")) {
+ parseYesNo("psOPI", &psOPI, tokens, fileName, line);
+ } else if (!cmd->cmp("psASCIIHex")) {
+ parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
+ } else if (!cmd->cmp("textEncoding")) {
+ parseTextEncoding(tokens, fileName, line);
+ } else if (!cmd->cmp("textEOL")) {
+ parseTextEOL(tokens, fileName, line);
+ } else if (!cmd->cmp("textPageBreaks")) {
+ parseYesNo("textPageBreaks", &textPageBreaks,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("textKeepTinyChars")) {
+ parseYesNo("textKeepTinyChars", &textKeepTinyChars,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("fontDir")) {
+ parseFontDir(tokens, fileName, line);
+ } else if (!cmd->cmp("initialZoom")) {
+ 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("antialias")) {
+ parseYesNo("antialias", &antialias, tokens, fileName, line);
+ } else if (!cmd->cmp("vectorAntialias")) {
+ parseYesNo("vectorAntialias", &vectorAntialias,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("strokeAdjust")) {
+ parseYesNo("strokeAdjust", &strokeAdjust, tokens, fileName, line);
+ } else if (!cmd->cmp("screenType")) {
+ parseScreenType(tokens, fileName, line);
+ } else if (!cmd->cmp("screenSize")) {
+ parseInteger("screenSize", &screenSize, tokens, fileName, line);
+ } else if (!cmd->cmp("screenDotRadius")) {
+ parseInteger("screenDotRadius", &screenDotRadius,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("screenGamma")) {
+ parseFloat("screenGamma", &screenGamma,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("screenBlackThreshold")) {
+ parseFloat("screenBlackThreshold", &screenBlackThreshold,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("screenWhiteThreshold")) {
+ parseFloat("screenWhiteThreshold", &screenWhiteThreshold,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("urlCommand")) {
+ parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
+ } else if (!cmd->cmp("movieCommand")) {
+ parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
+ } else if (!cmd->cmp("mapNumericCharNames")) {
+ parseYesNo("mapNumericCharNames", &mapNumericCharNames,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("mapUnknownCharNames")) {
+ parseYesNo("mapUnknownCharNames", &mapUnknownCharNames,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("bind")) {
+ parseBind(tokens, fileName, line);
+ } else if (!cmd->cmp("unbind")) {
+ parseUnbind(tokens, fileName, line);
+ } else if (!cmd->cmp("printCommands")) {
+ parseYesNo("printCommands", &printCommands, tokens, fileName, line);
+ } else if (!cmd->cmp("errQuiet")) {
+ parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
+ } else {
+ error(-1, "Unknown config file command '%s' (%s:%d)",
+ cmd->getCString(), fileName->getCString(), line);
+ if (!cmd->cmp("displayFontX") ||
+ !cmd->cmp("displayNamedCIDFontX") ||
+ !cmd->cmp("displayCIDFontX")) {
+ error(-1, "-- Xpdf no longer supports X fonts");
+ } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
+ error(-1, "-- The t1libControl and freetypeControl options have been replaced");
+ error(-1, " by the enableT1lib, enableFreeType, and antialias options");
+ } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
+ error(-1, "-- the config file format has changed since Xpdf 0.9x");
}
}
-
- deleteGList(tokens, GString);
- ++line;
}
+
+ deleteGList(tokens, GString);
}
+#endif
void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
int line) {
@@ -1112,6 +1575,216 @@ void GlobalParams::parseInitialZoom(GList *tokens,
initialZoom = ((GString *)tokens->get(1))->copy();
}
+void GlobalParams::parseScreenType(GList *tokens, GString *fileName,
+ int line) {
+ GString *tok;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'screenType' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (!tok->cmp("dispersed")) {
+ screenType = screenDispersed;
+ } else if (!tok->cmp("clustered")) {
+ screenType = screenClustered;
+ } else if (!tok->cmp("stochasticClustered")) {
+ screenType = screenStochasticClustered;
+ } else {
+ error(-1, "Bad 'screenType' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+}
+
+#ifndef PDF_PARSER_ONLY
+void GlobalParams::parseBind(GList *tokens, GString *fileName, int line) {
+ KeyBinding *binding;
+ GList *cmds;
+ int code, mods, context, i;
+
+ if (tokens->getLength() < 4) {
+ error(-1, "Bad 'bind' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2),
+ &code, &mods, &context,
+ "bind", tokens, fileName, line)) {
+ return;
+ }
+ for (i = 0; i < keyBindings->getLength(); ++i) {
+ binding = (KeyBinding *)keyBindings->get(i);
+ if (binding->code == code &&
+ binding->mods == mods &&
+ binding->context == context) {
+ delete (KeyBinding *)keyBindings->del(i);
+ break;
+ }
+ }
+ cmds = new GList();
+ for (i = 3; i < tokens->getLength(); ++i) {
+ cmds->append(((GString *)tokens->get(i))->copy());
+ }
+ keyBindings->append(new KeyBinding(code, mods, context, cmds));
+}
+
+void GlobalParams::parseUnbind(GList *tokens, GString *fileName, int line) {
+ KeyBinding *binding;
+ int code, mods, context, i;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'unbind' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2),
+ &code, &mods, &context,
+ "unbind", tokens, fileName, line)) {
+ return;
+ }
+ for (i = 0; i < keyBindings->getLength(); ++i) {
+ binding = (KeyBinding *)keyBindings->get(i);
+ if (binding->code == code &&
+ binding->mods == mods &&
+ binding->context == context) {
+ delete (KeyBinding *)keyBindings->del(i);
+ break;
+ }
+ }
+}
+
+GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr,
+ int *code, int *mods, int *context,
+ char *cmdName,
+ GList *tokens, GString *fileName, int line) {
+ char *p0;
+
+ *mods = xpdfKeyModNone;
+ p0 = modKeyStr->getCString();
+ while (1) {
+ if (!strncmp(p0, "shift-", 6)) {
+ *mods |= xpdfKeyModShift;
+ p0 += 6;
+ } else if (!strncmp(p0, "ctrl-", 5)) {
+ *mods |= xpdfKeyModCtrl;
+ p0 += 5;
+ } else if (!strncmp(p0, "alt-", 4)) {
+ *mods |= xpdfKeyModAlt;
+ p0 += 4;
+ } else {
+ break;
+ }
+ }
+
+ if (!strcmp(p0, "space")) {
+ *code = ' ';
+ } else if (!strcmp(p0, "tab")) {
+ *code = xpdfKeyCodeTab;
+ } else if (!strcmp(p0, "return")) {
+ *code = xpdfKeyCodeReturn;
+ } else if (!strcmp(p0, "enter")) {
+ *code = xpdfKeyCodeEnter;
+ } else if (!strcmp(p0, "backspace")) {
+ *code = xpdfKeyCodeBackspace;
+ } else if (!strcmp(p0, "insert")) {
+ *code = xpdfKeyCodeInsert;
+ } else if (!strcmp(p0, "delete")) {
+ *code = xpdfKeyCodeDelete;
+ } else if (!strcmp(p0, "home")) {
+ *code = xpdfKeyCodeHome;
+ } else if (!strcmp(p0, "end")) {
+ *code = xpdfKeyCodeEnd;
+ } else if (!strcmp(p0, "pgup")) {
+ *code = xpdfKeyCodePgUp;
+ } else if (!strcmp(p0, "pgdn")) {
+ *code = xpdfKeyCodePgDn;
+ } else if (!strcmp(p0, "left")) {
+ *code = xpdfKeyCodeLeft;
+ } else if (!strcmp(p0, "right")) {
+ *code = xpdfKeyCodeRight;
+ } else if (!strcmp(p0, "up")) {
+ *code = xpdfKeyCodeUp;
+ } else if (!strcmp(p0, "down")) {
+ *code = xpdfKeyCodeDown;
+ } else if (p0[0] == 'f' && p0[1] >= '1' && p0[1] <= '9' && !p0[2]) {
+ *code = xpdfKeyCodeF1 + (p0[1] - '1');
+ } else if (p0[0] == 'f' &&
+ ((p0[1] >= '1' && p0[1] <= '2' && p0[2] >= '0' && p0[2] <= '9') ||
+ (p0[1] == '3' && p0[2] >= '0' && p0[2] <= '5')) &&
+ !p0[3]) {
+ *code = xpdfKeyCodeF1 + 10 * (p0[1] - '0') + (p0[2] - '0') - 1;
+ } else if (!strncmp(p0, "mousePress", 10) &&
+ p0[10] >= '1' && p0[10] <= '7' && !p0[11]) {
+ *code = xpdfKeyCodeMousePress1 + (p0[10] - '1');
+ } else if (!strncmp(p0, "mouseRelease", 12) &&
+ p0[12] >= '1' && p0[12] <= '7' && !p0[13]) {
+ *code = xpdfKeyCodeMouseRelease1 + (p0[12] - '1');
+ } else if (*p0 >= 0x20 && *p0 <= 0x7e && !p0[1]) {
+ *code = (int)*p0;
+ } else {
+ error(-1, "Bad key/modifier in '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return gFalse;
+ }
+
+ p0 = contextStr->getCString();
+ if (!strcmp(p0, "any")) {
+ *context = xpdfKeyContextAny;
+ } else {
+ *context = xpdfKeyContextAny;
+ while (1) {
+ if (!strncmp(p0, "fullScreen", 10)) {
+ *context |= xpdfKeyContextFullScreen;
+ p0 += 10;
+ } else if (!strncmp(p0, "window", 6)) {
+ *context |= xpdfKeyContextWindow;
+ p0 += 6;
+ } else if (!strncmp(p0, "continuous", 10)) {
+ *context |= xpdfKeyContextContinuous;
+ p0 += 10;
+ } else if (!strncmp(p0, "singlePage", 10)) {
+ *context |= xpdfKeyContextSinglePage;
+ p0 += 10;
+ } else if (!strncmp(p0, "overLink", 8)) {
+ *context |= xpdfKeyContextOverLink;
+ p0 += 8;
+ } else if (!strncmp(p0, "offLink", 7)) {
+ *context |= xpdfKeyContextOffLink;
+ p0 += 7;
+ } else if (!strncmp(p0, "outline", 7)) {
+ *context |= xpdfKeyContextOutline;
+ p0 += 7;
+ } else if (!strncmp(p0, "mainWin", 7)) {
+ *context |= xpdfKeyContextMainWin;
+ p0 += 7;
+ } else if (!strncmp(p0, "scrLockOn", 9)) {
+ *context |= xpdfKeyContextScrLockOn;
+ p0 += 9;
+ } else if (!strncmp(p0, "scrLockOff", 10)) {
+ *context |= xpdfKeyContextScrLockOff;
+ p0 += 10;
+ } else {
+ error(-1, "Bad context in '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return gFalse;
+ }
+ if (!*p0) {
+ break;
+ }
+ if (*p0 != ',') {
+ error(-1, "Bad context in '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return gFalse;
+ }
+ ++p0;
+ }
+ }
+
+ return gTrue;
+}
+#endif
+
void GlobalParams::parseCommand(char *cmdName, GString **val,
GList *tokens, GString *fileName, int line) {
if (tokens->getLength() != 2) {
@@ -1152,6 +1825,69 @@ GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
return gTrue;
}
+void GlobalParams::parseInteger(char *cmdName, int *val,
+ GList *tokens, GString *fileName, int line) {
+ GString *tok;
+ int i;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (tok->getLength() == 0) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ if (tok->getChar(0) == '-') {
+ i = 1;
+ } else {
+ i = 0;
+ }
+ for (; i < tok->getLength(); ++i) {
+ if (tok->getChar(i) < '0' || tok->getChar(i) > '9') {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ }
+ *val = atoi(tok->getCString());
+}
+
+void GlobalParams::parseFloat(char *cmdName, double *val,
+ GList *tokens, GString *fileName, int line) {
+ GString *tok;
+ int i;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (tok->getLength() == 0) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ if (tok->getChar(0) == '-') {
+ i = 1;
+ } else {
+ i = 0;
+ }
+ for (; i < tok->getLength(); ++i) {
+ if (!((tok->getChar(i) >= '0' && tok->getChar(i) <= '9') ||
+ tok->getChar(i) == '.')) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ }
+ *val = atof(tok->getCString());
+}
+
GlobalParams::~GlobalParams() {
GHashIter *iter;
GString *key;
@@ -1171,6 +1907,11 @@ GlobalParams::~GlobalParams() {
deleteGHash(displayFonts, DisplayFontParam);
deleteGHash(displayCIDFonts, DisplayFontParam);
deleteGHash(displayNamedCIDFonts, DisplayFontParam);
+#ifdef WIN32
+ if (winFontList) {
+ delete winFontList;
+ }
+#endif
if (psFile) {
delete psFile;
}
@@ -1186,6 +1927,9 @@ GlobalParams::~GlobalParams() {
if (movieCommand) {
delete movieCommand;
}
+#ifndef PDF_PARSER_ONLY
+ deleteGList(keyBindings, KeyBinding);
+#endif
cMapDirs->startIter(&iter);
while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
@@ -1241,7 +1985,7 @@ void GlobalParams::setupBaseFonts(char *dir) {
if ((SHGetSpecialFolderPathFunc =
(BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath,
int nFolder, BOOL fCreate))
- GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) {
+ GetProcAddress(shell32Lib, "SHGetSpecialFolderPathA"))) {
if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir,
CSIDL_FONTS, FALSE)) {
winFontDir[0] = '\0';
@@ -1317,6 +2061,12 @@ void GlobalParams::setupBaseFonts(char *dir) {
dfp->t1.fileName = fileName;
globalParams->addDisplayFont(dfp);
}
+
+#ifdef WIN32
+ if (winFontDir[0]) {
+ winFontList = new WinFontList(winFontDir);
+ }
+#endif
}
//------------------------------------------------------------------------
@@ -1419,6 +2169,11 @@ DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
lockGlobalParams;
dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
+#ifdef WIN32
+ if (!dfp && winFontList) {
+ dfp = winFontList->find(fontName);
+ }
+#endif
unlockGlobalParams;
return dfp;
}
@@ -1602,6 +2357,15 @@ GBool GlobalParams::getPSEmbedCIDTrueType() {
return e;
}
+GBool GlobalParams::getPSPreload() {
+ GBool preload;
+
+ lockGlobalParams;
+ preload = psPreload;
+ unlockGlobalParams;
+ return preload;
+}
+
GBool GlobalParams::getPSOPI() {
GBool opi;
@@ -1726,6 +2490,78 @@ GBool GlobalParams::getAntialias() {
return f;
}
+GBool GlobalParams::getVectorAntialias() {
+ GBool f;
+
+ lockGlobalParams;
+ f = vectorAntialias;
+ unlockGlobalParams;
+ return f;
+}
+
+GBool GlobalParams::getStrokeAdjust() {
+ GBool f;
+
+ lockGlobalParams;
+ f = strokeAdjust;
+ unlockGlobalParams;
+ return f;
+}
+
+ScreenType GlobalParams::getScreenType() {
+ ScreenType t;
+
+ lockGlobalParams;
+ t = screenType;
+ unlockGlobalParams;
+ return t;
+}
+
+int GlobalParams::getScreenSize() {
+ int size;
+
+ lockGlobalParams;
+ size = screenSize;
+ unlockGlobalParams;
+ return size;
+}
+
+int GlobalParams::getScreenDotRadius() {
+ int r;
+
+ lockGlobalParams;
+ r = screenDotRadius;
+ unlockGlobalParams;
+ return r;
+}
+
+double GlobalParams::getScreenGamma() {
+ double gamma;
+
+ lockGlobalParams;
+ gamma = screenGamma;
+ unlockGlobalParams;
+ return gamma;
+}
+
+double GlobalParams::getScreenBlackThreshold() {
+ double thresh;
+
+ lockGlobalParams;
+ thresh = screenBlackThreshold;
+ unlockGlobalParams;
+ return thresh;
+}
+
+double GlobalParams::getScreenWhiteThreshold() {
+ double thresh;
+
+ lockGlobalParams;
+ thresh = screenWhiteThreshold;
+ unlockGlobalParams;
+ return thresh;
+}
+
GBool GlobalParams::getMapNumericCharNames() {
GBool map;
@@ -1735,6 +2571,43 @@ GBool GlobalParams::getMapNumericCharNames() {
return map;
}
+GBool GlobalParams::getMapUnknownCharNames() {
+ GBool map;
+
+ lockGlobalParams;
+ map = mapUnknownCharNames;
+ unlockGlobalParams;
+ return map;
+}
+
+#ifndef PDF_PARSER_ONLY
+GList *GlobalParams::getKeyBinding(int code, int mods, int context) {
+ KeyBinding *binding;
+ GList *cmds;
+ int modMask;
+ int i, j;
+
+ lockGlobalParams;
+ cmds = NULL;
+ // for ASCII chars, ignore the shift modifier
+ modMask = code <= 0xff ? ~xpdfKeyModShift : ~0;
+ for (i = 0; i < keyBindings->getLength(); ++i) {
+ binding = (KeyBinding *)keyBindings->get(i);
+ if (binding->code == code &&
+ (binding->mods & modMask) == (mods & modMask) &&
+ (~binding->context | context) == ~0) {
+ cmds = new GList();
+ for (j = 0; j < binding->cmds->getLength(); ++j) {
+ cmds->append(((GString *)binding->cmds->get(j))->copy());
+ }
+ break;
+ }
+ }
+ unlockGlobalParams;
+ return cmds;
+}
+#endif
+
GBool GlobalParams::getPrintCommands() {
GBool p;
@@ -1745,12 +2618,9 @@ GBool GlobalParams::getPrintCommands() {
}
GBool GlobalParams::getErrQuiet() {
- GBool q;
-
- lockGlobalParams;
- q = errQuiet;
- unlockGlobalParams;
- return q;
+ // no locking -- this function may get called from inside a locked
+ // section
+ return errQuiet;
}
CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
@@ -1960,6 +2830,12 @@ void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
unlockGlobalParams;
}
+void GlobalParams::setPSPreload(GBool preload) {
+ lockGlobalParams;
+ psPreload = preload;
+ unlockGlobalParams;
+}
+
void GlobalParams::setPSOPI(GBool opi) {
lockGlobalParams;
psOPI = opi;
@@ -2048,12 +2924,63 @@ GBool GlobalParams::setAntialias(char *s) {
return ok;
}
+GBool GlobalParams::setVectorAntialias(char *s) {
+ GBool ok;
+
+ lockGlobalParams;
+ ok = parseYesNo2(s, &vectorAntialias);
+ unlockGlobalParams;
+ return ok;
+}
+
+void GlobalParams::setScreenType(ScreenType t) {
+ lockGlobalParams;
+ screenType = t;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setScreenSize(int size) {
+ lockGlobalParams;
+ screenSize = size;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setScreenDotRadius(int r) {
+ lockGlobalParams;
+ screenDotRadius = r;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setScreenGamma(double gamma) {
+ lockGlobalParams;
+ screenGamma = gamma;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setScreenBlackThreshold(double thresh) {
+ lockGlobalParams;
+ screenBlackThreshold = thresh;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setScreenWhiteThreshold(double thresh) {
+ lockGlobalParams;
+ screenWhiteThreshold = thresh;
+ unlockGlobalParams;
+}
+
void GlobalParams::setMapNumericCharNames(GBool map) {
lockGlobalParams;
mapNumericCharNames = map;
unlockGlobalParams;
}
+void GlobalParams::setMapUnknownCharNames(GBool map) {
+ lockGlobalParams;
+ mapUnknownCharNames = map;
+ unlockGlobalParams;
+}
+
void GlobalParams::setPrintCommands(GBool printCommandsA) {
lockGlobalParams;
printCommands = printCommandsA;
@@ -2082,7 +3009,7 @@ XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) {
lockGlobalParams;
for (i = 0; i < securityHandlers->getLength(); ++i) {
hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
- if (!stricmp(hdlr->name, name)) {
+ if (!strcasecmp(hdlr->name, name)) {
unlockGlobalParams;
return hdlr;
}
diff --git a/Build/source/libs/xpdf/xpdf/GlobalParams.h b/Build/source/libs/xpdf/xpdf/GlobalParams.h
index 99f78a76746..566d43ca7e7 100644
--- a/Build/source/libs/xpdf/xpdf/GlobalParams.h
+++ b/Build/source/libs/xpdf/xpdf/GlobalParams.h
@@ -35,6 +35,9 @@ class CMap;
class CMapCache;
struct XpdfSecurityHandler;
class GlobalParams;
+#ifdef WIN32
+class WinFontList;
+#endif
//------------------------------------------------------------------------
@@ -69,7 +72,7 @@ public:
};
DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
- ~DisplayFontParam();
+ virtual ~DisplayFontParam();
};
//------------------------------------------------------------------------
@@ -111,6 +114,83 @@ enum EndOfLineKind {
//------------------------------------------------------------------------
+enum ScreenType {
+ screenUnset,
+ screenDispersed,
+ screenClustered,
+ screenStochasticClustered
+};
+
+//------------------------------------------------------------------------
+
+#ifndef PDF_PARSER_ONLY
+class KeyBinding {
+public:
+
+ int code; // 0x20 .. 0xfe = ASCII,
+ // >=0x10000 = special keys, mouse buttons,
+ // etc. (xpdfKeyCode* symbols)
+ int mods; // modifiers (xpdfKeyMod* symbols, or-ed
+ // together)
+ int context; // context (xpdfKeyContext* symbols, or-ed
+ // together)
+ GList *cmds; // list of commands [GString]
+
+ KeyBinding(int codeA, int modsA, int contextA, char *cmd0);
+ KeyBinding(int codeA, int modsA, int contextA, char *cmd0, char *cmd1);
+ KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA);
+ ~KeyBinding();
+};
+
+#define xpdfKeyCodeTab 0x1000
+#define xpdfKeyCodeReturn 0x1001
+#define xpdfKeyCodeEnter 0x1002
+#define xpdfKeyCodeBackspace 0x1003
+#define xpdfKeyCodeInsert 0x1004
+#define xpdfKeyCodeDelete 0x1005
+#define xpdfKeyCodeHome 0x1006
+#define xpdfKeyCodeEnd 0x1007
+#define xpdfKeyCodePgUp 0x1008
+#define xpdfKeyCodePgDn 0x1009
+#define xpdfKeyCodeLeft 0x100a
+#define xpdfKeyCodeRight 0x100b
+#define xpdfKeyCodeUp 0x100c
+#define xpdfKeyCodeDown 0x100d
+#define xpdfKeyCodeF1 0x1100
+#define xpdfKeyCodeF35 0x1122
+#define xpdfKeyCodeMousePress1 0x2001
+#define xpdfKeyCodeMousePress2 0x2002
+#define xpdfKeyCodeMousePress3 0x2003
+#define xpdfKeyCodeMousePress4 0x2004
+#define xpdfKeyCodeMousePress5 0x2005
+#define xpdfKeyCodeMousePress6 0x2006
+#define xpdfKeyCodeMousePress7 0x2007
+#define xpdfKeyCodeMouseRelease1 0x2101
+#define xpdfKeyCodeMouseRelease2 0x2102
+#define xpdfKeyCodeMouseRelease3 0x2103
+#define xpdfKeyCodeMouseRelease4 0x2104
+#define xpdfKeyCodeMouseRelease5 0x2105
+#define xpdfKeyCodeMouseRelease6 0x2106
+#define xpdfKeyCodeMouseRelease7 0x2107
+#define xpdfKeyModNone 0
+#define xpdfKeyModShift (1 << 0)
+#define xpdfKeyModCtrl (1 << 1)
+#define xpdfKeyModAlt (1 << 2)
+#define xpdfKeyContextAny 0
+#define xpdfKeyContextFullScreen (1 << 0)
+#define xpdfKeyContextWindow (2 << 0)
+#define xpdfKeyContextContinuous (1 << 2)
+#define xpdfKeyContextSinglePage (2 << 2)
+#define xpdfKeyContextOverLink (1 << 4)
+#define xpdfKeyContextOffLink (2 << 4)
+#define xpdfKeyContextOutline (1 << 6)
+#define xpdfKeyContextMainWin (2 << 6)
+#define xpdfKeyContextScrLockOn (1 << 8)
+#define xpdfKeyContextScrLockOff (2 << 8)
+#endif
+
+//------------------------------------------------------------------------
+
class GlobalParams {
public:
@@ -126,6 +206,10 @@ public:
void setBaseDir(char *dir);
void setupBaseFonts(char *dir);
+#ifndef PDF_PARSER_ONLY
+ void parseLine(char *buf, GString *fileName, int line);
+#endif
+
//----- accessors
CharCode getMacRomanCharCode(char *charName);
@@ -154,6 +238,7 @@ public:
GBool getPSEmbedTrueType();
GBool getPSEmbedCIDPostScript();
GBool getPSEmbedCIDTrueType();
+ GBool getPSPreload();
GBool getPSOPI();
GBool getPSASCIIHex();
GString *getTextEncodingName();
@@ -166,9 +251,21 @@ public:
GBool getEnableT1lib();
GBool getEnableFreeType();
GBool getAntialias();
+ GBool getVectorAntialias();
+ GBool getStrokeAdjust();
+ ScreenType getScreenType();
+ int getScreenSize();
+ int getScreenDotRadius();
+ double getScreenGamma();
+ double getScreenBlackThreshold();
+ double getScreenWhiteThreshold();
GString *getURLCommand() { return urlCommand; }
GString *getMovieCommand() { return movieCommand; }
GBool getMapNumericCharNames();
+ GBool getMapUnknownCharNames();
+#ifndef PDF_PARSER_ONLY
+ GList *getKeyBinding(int code, int mods, int context);
+#endif
GBool getPrintCommands();
GBool getErrQuiet();
@@ -196,6 +293,7 @@ public:
void setPSEmbedTrueType(GBool embed);
void setPSEmbedCIDPostScript(GBool embed);
void setPSEmbedCIDTrueType(GBool embed);
+ void setPSPreload(GBool preload);
void setPSOPI(GBool opi);
void setPSASCIIHex(GBool hex);
void setTextEncoding(char *encodingName);
@@ -207,7 +305,15 @@ public:
GBool setEnableT1lib(char *s);
GBool setEnableFreeType(char *s);
GBool setAntialias(char *s);
+ GBool setVectorAntialias(char *s);
+ void setScreenType(ScreenType t);
+ void setScreenSize(int size);
+ void setScreenDotRadius(int r);
+ void setScreenGamma(double gamma);
+ void setScreenBlackThreshold(double thresh);
+ void setScreenWhiteThreshold(double thresh);
void setMapNumericCharNames(GBool map);
+ void setMapUnknownCharNames(GBool map);
void setPrintCommands(GBool printCommandsA);
void setErrQuiet(GBool errQuietA);
@@ -218,6 +324,9 @@ public:
private:
+#ifndef PDF_PARSER_ONLY
+ void createDefaultKeyBindings();
+#endif
void parseFile(GString *fileName, FILE *f);
void parseNameToUnicode(GList *tokens, GString *fileName, int line);
void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
@@ -239,11 +348,24 @@ private:
void parseTextEOL(GList *tokens, GString *fileName, int line);
void parseFontDir(GList *tokens, GString *fileName, int line);
void parseInitialZoom(GList *tokens, GString *fileName, int line);
+ void parseScreenType(GList *tokens, GString *fileName, int line);
+#ifndef PDF_PARSER_ONLY
+ void parseBind(GList *tokens, GString *fileName, int line);
+ void parseUnbind(GList *tokens, GString *fileName, int line);
+ GBool parseKey(GString *modKeyStr, GString *contextStr,
+ int *code, int *mods, int *context,
+ char *cmdName,
+ GList *tokens, GString *fileName, int line);
+#endif
void parseCommand(char *cmdName, GString **val,
GList *tokens, GString *fileName, int line);
void parseYesNo(char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line);
GBool parseYesNo2(char *token, GBool *flag);
+ void parseInteger(char *cmdName, int *val,
+ GList *tokens, GString *fileName, int line);
+ void parseFloat(char *cmdName, double *val,
+ GList *tokens, GString *fileName, int line);
UnicodeMap *getUnicodeMap2(GString *encodingName);
#ifdef ENABLE_PLUGINS
GBool loadPlugin(char *type, char *name);
@@ -273,6 +395,9 @@ private:
GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString]
GHash *displayFonts; // display font info, indexed by font name
// [DisplayFontParam]
+#ifdef WIN32
+ WinFontList *winFontList; // system TrueType fonts
+#endif
GHash *displayCIDFonts; // display CID font info, indexed by
// collection [DisplayFontParam]
GHash *displayNamedCIDFonts; // display CID font info, indexed by
@@ -298,6 +423,8 @@ private:
GBool psEmbedTrueType; // embed TrueType fonts?
GBool psEmbedCIDPostScript; // embed CID PostScript fonts?
GBool psEmbedCIDTrueType; // embed CID TrueType fonts?
+ GBool psPreload; // preload PostScript images and forms into
+ // memory
GBool psOPI; // generate PostScript OPI comments?
GBool psASCIIHex; // use ASCIIHex instead of ASCII85?
GString *textEncoding; // encoding (unicodeMap) to use for text
@@ -311,10 +438,22 @@ private:
GBool continuousView; // continuous view mode
GBool enableT1lib; // t1lib enable flag
GBool enableFreeType; // FreeType enable flag
- GBool antialias; // anti-aliasing enable flag
+ GBool antialias; // font anti-aliasing enable flag
+ GBool vectorAntialias; // vector anti-aliasing enable flag
+ GBool strokeAdjust; // stroke adjustment enable flag
+ ScreenType screenType; // halftone screen type
+ int screenSize; // screen matrix size
+ int screenDotRadius; // screen dot radius
+ double screenGamma; // screen gamma correction
+ double screenBlackThreshold; // screen black clamping threshold
+ double screenWhiteThreshold; // screen white clamping threshold
GString *urlCommand; // command executed for URL links
GString *movieCommand; // command executed for movie annotations
GBool mapNumericCharNames; // map numeric char names (from font subsets)?
+ GBool mapUnknownCharNames; // map unknown char names?
+#ifndef PDF_PARSER_ONLY
+ GList *keyBindings; // key & mouse button bindings [KeyBinding]
+#endif
GBool printCommands; // print the drawing commands
GBool errQuiet; // suppress error messages?
diff --git a/Build/source/libs/xpdf/xpdf/JBIG2Stream.cc b/Build/source/libs/xpdf/xpdf/JBIG2Stream.cc
index 5e263079d3a..a4f1b6eacdc 100644
--- a/Build/source/libs/xpdf/xpdf/JBIG2Stream.cc
+++ b/Build/source/libs/xpdf/xpdf/JBIG2Stream.cc
@@ -1099,7 +1099,7 @@ JBIG2CodeTable::~JBIG2CodeTable() {
// JBIG2Stream
//------------------------------------------------------------------------
-JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
+JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
FilterStream(strA)
{
pageBitmap = NULL;
@@ -1124,22 +1124,15 @@ JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
huffDecoder = new JBIG2HuffmanDecoder();
mmrDecoder = new JBIG2MMRDecoder();
- segments = globalSegments = new GList();
- if (globalsStream->isStream()) {
- curStr = globalsStream->getStream();
- curStr->reset();
- arithDecoder->setStream(curStr);
- huffDecoder->setStream(curStr);
- mmrDecoder->setStream(curStr);
- readSegments();
- }
-
- segments = NULL;
+ globalsStreamA->copy(&globalsStream);
+ segments = globalSegments = NULL;
curStr = NULL;
dataPtr = dataEnd = NULL;
}
JBIG2Stream::~JBIG2Stream() {
+ close();
+ globalsStream.free();
delete arithDecoder;
delete genericRegionStats;
delete refinementRegionStats;
@@ -1159,28 +1152,25 @@ JBIG2Stream::~JBIG2Stream() {
delete iaidStats;
delete huffDecoder;
delete mmrDecoder;
- if (pageBitmap) {
- delete pageBitmap;
- }
- if (segments) {
- deleteGList(segments, JBIG2Segment);
- }
- if (globalSegments) {
- deleteGList(globalSegments, JBIG2Segment);
- }
delete str;
}
void JBIG2Stream::reset() {
- if (pageBitmap) {
- delete pageBitmap;
- pageBitmap = NULL;
- }
- if (segments) {
- deleteGList(segments, JBIG2Segment);
+ // read the globals stream
+ globalSegments = new GList();
+ if (globalsStream.isStream()) {
+ segments = globalSegments;
+ curStr = globalsStream.getStream();
+ curStr->reset();
+ arithDecoder->setStream(curStr);
+ huffDecoder->setStream(curStr);
+ mmrDecoder->setStream(curStr);
+ readSegments();
+ curStr->close();
}
- segments = new GList();
+ // read the main stream
+ segments = new GList();
curStr = str;
curStr->reset();
arithDecoder->setStream(curStr);
@@ -1192,10 +1182,27 @@ void JBIG2Stream::reset() {
dataPtr = pageBitmap->getDataPtr();
dataEnd = dataPtr + pageBitmap->getDataSize();
} else {
- dataPtr = NULL;
+ dataPtr = dataEnd = NULL;
}
}
+void JBIG2Stream::close() {
+ if (pageBitmap) {
+ delete pageBitmap;
+ pageBitmap = NULL;
+ }
+ if (segments) {
+ deleteGList(segments, JBIG2Segment);
+ segments = NULL;
+ }
+ if (globalSegments) {
+ deleteGList(globalSegments, JBIG2Segment);
+ globalSegments = NULL;
+ }
+ dataPtr = dataEnd = NULL;
+ FilterStream::close();
+}
+
int JBIG2Stream::getChar() {
if (dataPtr && dataPtr < dataEnd) {
return (*dataPtr++ ^ 0xff) & 0xff;
@@ -2352,9 +2359,9 @@ void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
skipBitmap->clearToZero();
for (m = 0; m < gridH; ++m) {
- xx = gridX + m * stepY;
- yy = gridY + m * stepX;
for (n = 0; n < gridW; ++n) {
+ xx = gridX + m * stepY + n * stepX;
+ yy = gridY + m * stepX - n * stepY;
if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
skipBitmap->setPixel(n, m);
@@ -2401,6 +2408,9 @@ void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
}
gfree(grayImg);
+ if (skipBitmap) {
+ delete skipBitmap;
+ }
// combine the region bitmap into the page bitmap
if (imm) {
@@ -3331,7 +3341,7 @@ void JBIG2Stream::resetIntStats(int symCodeLen) {
iardwStats->reset();
iardhStats->reset();
iariStats->reset();
- if (iaidStats->getContextSize() == symCodeLen + 1) {
+ if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
iaidStats->reset();
} else {
delete iaidStats;
diff --git a/Build/source/libs/xpdf/xpdf/JBIG2Stream.h b/Build/source/libs/xpdf/xpdf/JBIG2Stream.h
index 44e09db2891..210d927a7cf 100644
--- a/Build/source/libs/xpdf/xpdf/JBIG2Stream.h
+++ b/Build/source/libs/xpdf/xpdf/JBIG2Stream.h
@@ -33,10 +33,11 @@ class JBIG2MMRDecoder;
class JBIG2Stream: public FilterStream {
public:
- JBIG2Stream(Stream *strA, Object *globalsStream);
+ JBIG2Stream(Stream *strA, Object *globalsStreamA);
virtual ~JBIG2Stream();
virtual StreamKind getKind() { return strJBIG2; }
virtual void reset();
+ virtual void close();
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent);
@@ -109,6 +110,7 @@ private:
GBool readULong(Guint *x);
GBool readLong(int *x);
+ Object globalsStream;
Guint pageW, pageH, curPageH;
Guint pageDefPixel;
JBIG2Bitmap *pageBitmap;
diff --git a/Build/source/libs/xpdf/xpdf/JPXStream.cc b/Build/source/libs/xpdf/xpdf/JPXStream.cc
index d483cd4bf92..7107854912d 100644
--- a/Build/source/libs/xpdf/xpdf/JPXStream.cc
+++ b/Build/source/libs/xpdf/xpdf/JPXStream.cc
@@ -177,6 +177,59 @@ static Guint signContext[5][5][2] = {
//------------------------------------------------------------------------
+#if 1 //----- disable coverage tracking
+
+#define cover(idx)
+
+#else //----- enable coverage tracking
+
+class JPXCover {
+public:
+
+ JPXCover(int sizeA);
+ ~JPXCover();
+ void incr(int idx);
+
+private:
+
+ int size, used;
+ int *data;
+};
+
+JPXCover::JPXCover(int sizeA) {
+ size = sizeA;
+ used = -1;
+ data = (int *)gmallocn(size, sizeof(int));
+ memset(data, 0, size * sizeof(int));
+}
+
+JPXCover::~JPXCover() {
+ int i;
+
+ printf("JPX coverage:\n");
+ for (i = 0; i <= used; ++i) {
+ printf(" %4d: %8d\n", i, data[i]);
+ }
+ gfree(data);
+}
+
+void JPXCover::incr(int idx) {
+ if (idx < size) {
+ ++data[idx];
+ if (idx > used) {
+ used = idx;
+ }
+ }
+}
+
+JPXCover jpxCover(150);
+
+#define cover(idx) jpxCover.incr(idx)
+
+#endif //----- coverage tracking
+
+//------------------------------------------------------------------------
+
JPXStream::JPXStream(Stream *strA):
FilterStream(strA)
{
@@ -196,6 +249,24 @@ JPXStream::JPXStream(Stream *strA):
}
JPXStream::~JPXStream() {
+ close();
+ delete str;
+}
+
+void JPXStream::reset() {
+ str->reset();
+ if (readBoxes()) {
+ curY = img.yOffset;
+ } else {
+ // readBoxes reported an error, so we go immediately to EOF
+ curY = img.ySize;
+ }
+ curX = img.xOffset;
+ curComp = 0;
+ readBufLen = 0;
+}
+
+void JPXStream::close() {
JPXTile *tile;
JPXTileComp *tileComp;
JPXResLevel *resLevel;
@@ -205,19 +276,23 @@ JPXStream::~JPXStream() {
Guint comp, i, k, r, pre, sb;
gfree(bpc);
+ bpc = NULL;
if (havePalette) {
gfree(palette.bpc);
gfree(palette.c);
+ havePalette = gFalse;
}
if (haveCompMap) {
gfree(compMap.comp);
gfree(compMap.type);
gfree(compMap.pComp);
+ haveCompMap = gFalse;
}
if (haveChannelDefn) {
gfree(channelDefn.idx);
gfree(channelDefn.type);
gfree(channelDefn.assoc);
+ haveChannelDefn = gFalse;
}
if (img.tiles) {
@@ -267,21 +342,9 @@ JPXStream::~JPXStream() {
}
}
gfree(img.tiles);
+ img.tiles = NULL;
}
- delete str;
-}
-
-void JPXStream::reset() {
- str->reset();
- if (readBoxes()) {
- curY = img.yOffset;
- } else {
- // readBoxes reported an error, so we go immediately to EOF
- curY = img.ySize;
- }
- curX = img.xOffset;
- curComp = 0;
- readBufLen = 0;
+ FilterStream::close();
}
int JPXStream::getChar() {
@@ -394,8 +457,10 @@ void JPXStream::getImageParams(int *bitsPerComponent,
} else {
while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
if (boxType == 0x6a703268) { // JP2 header
+ cover(0);
// skip the superbox
} else if (boxType == 0x69686472) { // image header
+ cover(1);
if (readULong(&dummy) &&
readULong(&dummy) &&
readUWord(&dummy) &&
@@ -407,6 +472,7 @@ void JPXStream::getImageParams(int *bitsPerComponent,
haveBPC = gTrue;
}
} else if (boxType == 0x636F6C72) { // color specification
+ cover(2);
if (readByte(&csMeth) &&
readByte(&csPrec1) &&
readByte(&dummy2)) {
@@ -440,11 +506,13 @@ void JPXStream::getImageParams(int *bitsPerComponent,
}
}
} else if (boxType == 0x6A703263) { // codestream
+ cover(3);
if (!(haveBPC && haveCSMode)) {
getImageParams2(bitsPerComponent, csMode);
}
break;
} else {
+ cover(4);
for (i = 0; i < dataLen; ++i) {
str->getChar();
}
@@ -462,6 +530,7 @@ void JPXStream::getImageParams2(int *bitsPerComponent,
while (readMarkerHdr(&segType, &segLen)) {
if (segType == 0x51) { // SIZ - image and tile size
+ cover(5);
if (readUWord(&dummy) &&
readULong(&dummy) &&
readULong(&dummy) &&
@@ -485,6 +554,7 @@ void JPXStream::getImageParams2(int *bitsPerComponent,
}
break;
} else {
+ cover(6);
if (segLen > 2) {
for (i = 0; i < segLen - 2; ++i) {
str->getChar();
@@ -505,6 +575,7 @@ GBool JPXStream::readBoxes() {
// wrapper) -- this appears to be a violation of the PDF spec, but
// Acrobat allows it
if (str->lookChar() == 0xff) {
+ cover(7);
error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
readCodestream(0);
nComps = img.nComps;
@@ -525,8 +596,10 @@ GBool JPXStream::readBoxes() {
// some things which should be subboxes of the JP2 header box
// show up outside of it - so we simply ignore the JP2 header
// box
+ cover(8);
break;
case 0x69686472: // image header
+ cover(9);
if (!readULong(&height) ||
!readULong(&width) ||
!readUWord(&nComps) ||
@@ -548,6 +621,7 @@ GBool JPXStream::readBoxes() {
haveImgHdr = gTrue;
break;
case 0x62706363: // bits per component
+ cover(10);
if (!haveImgHdr) {
error(getPos(), "Found bits per component box before image header box in JPX stream");
return gFalse;
@@ -564,11 +638,13 @@ GBool JPXStream::readBoxes() {
}
break;
case 0x636F6C72: // color specification
+ cover(11);
if (!readColorSpecBox(dataLen)) {
return gFalse;
}
break;
case 0x70636c72: // palette
+ cover(12);
if (!readUWord(&palette.nEntries) ||
!readUByte(&palette.nComps)) {
error(getPos(), "Unexpected EOF in JPX stream");
@@ -597,6 +673,7 @@ GBool JPXStream::readBoxes() {
havePalette = gTrue;
break;
case 0x636d6170: // component mapping
+ cover(13);
compMap.nChannels = dataLen / 4;
compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
@@ -612,6 +689,7 @@ GBool JPXStream::readBoxes() {
haveCompMap = gTrue;
break;
case 0x63646566: // channel definition
+ cover(14);
if (!readUWord(&channelDefn.nChannels)) {
error(getPos(), "Unexpected EOF in JPX stream");
return gFalse;
@@ -633,6 +711,7 @@ GBool JPXStream::readBoxes() {
haveChannelDefn = gTrue;
break;
case 0x6A703263: // contiguous codestream
+ cover(15);
if (!bpc) {
error(getPos(), "JPX stream is missing the image header box");
}
@@ -644,6 +723,7 @@ GBool JPXStream::readBoxes() {
}
break;
default:
+ cover(16);
for (i = 0; i < dataLen; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Unexpected EOF in JPX stream");
@@ -670,6 +750,7 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) {
}
switch (newCS.meth) {
case 1: // enumerated colorspace
+ cover(17);
if (!readULong(&csEnum)) {
goto err;
}
@@ -712,6 +793,7 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) {
}
} else if (dataLen == 7) {
//~ this assumes the 8-bit case
+ cover(92);
newCS.enumerated.cieLab.rl = 100;
newCS.enumerated.cieLab.ol = 0;
newCS.enumerated.cieLab.ra = 255;
@@ -758,6 +840,7 @@ GBool JPXStream::readColorSpecBox(Guint dataLen) {
case 2: // restricted ICC profile
case 3: // any ICC profile (JPX)
case 4: // vendor color (JPX)
+ cover(18);
for (i = 0; i < dataLen - 3; ++i) {
if (str->getChar() == EOF) {
goto err;
@@ -784,7 +867,7 @@ GBool JPXStream::readCodestream(Guint len) {
int segType;
GBool haveSIZ, haveCOD, haveQCD, haveSOT;
Guint precinctSize, style;
- Guint segLen, capabilities, nTiles, comp, i, j, r;
+ Guint segLen, capabilities, comp, i, j, r;
//----- main header
haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
@@ -796,8 +879,10 @@ GBool JPXStream::readCodestream(Guint len) {
switch (segType) {
case 0x4f: // SOC - start of codestream
// marker only
+ cover(19);
break;
case 0x51: // SIZ - image and tile size
+ cover(20);
if (!readUWord(&capabilities) ||
!readULong(&img.xSize) ||
!readULong(&img.ySize) ||
@@ -819,14 +904,14 @@ GBool JPXStream::readCodestream(Guint len) {
/ img.xTileSize;
img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
/ img.yTileSize;
- nTiles = img.nXTiles * img.nYTiles;
// check for overflow before allocating memory
if (img.nXTiles <= 0 || img.nYTiles <= 0 ||
img.nXTiles >= INT_MAX / img.nYTiles) {
error(getPos(), "Bad tile count in JPX SIZ marker segment");
return gFalse;
}
- img.tiles = (JPXTile *)gmallocn(nTiles, sizeof(JPXTile));
+ img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles,
+ sizeof(JPXTile));
for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps,
sizeof(JPXTileComp));
@@ -855,6 +940,7 @@ GBool JPXStream::readCodestream(Guint len) {
haveSIZ = gTrue;
break;
case 0x52: // COD - coding style default
+ cover(21);
if (!readUByte(&img.tiles[0].tileComps[0].style) ||
!readUByte(&img.tiles[0].progOrder) ||
!readUWord(&img.tiles[0].nLayers) ||
@@ -901,6 +987,7 @@ GBool JPXStream::readCodestream(Guint len) {
}
for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
if (img.tiles[0].tileComps[0].style & 0x01) {
+ cover(91);
if (!readUByte(&precinctSize)) {
error(getPos(), "Error in JPX COD marker segment");
return gFalse;
@@ -929,6 +1016,7 @@ GBool JPXStream::readCodestream(Guint len) {
haveCOD = gTrue;
break;
case 0x53: // COC - coding style component
+ cover(22);
if (!haveCOD) {
error(getPos(), "JPX COC marker segment before COD segment");
return gFalse;
@@ -998,6 +1086,7 @@ GBool JPXStream::readCodestream(Guint len) {
}
break;
case 0x5c: // QCD - quantization default
+ cover(23);
if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
error(getPos(), "Error in JPX QCD marker segment");
return gFalse;
@@ -1061,6 +1150,7 @@ GBool JPXStream::readCodestream(Guint len) {
haveQCD = gTrue;
break;
case 0x5d: // QCC - quantization component
+ cover(24);
if (!haveQCD) {
error(getPos(), "JPX QCC marker segment before QCD segment");
return gFalse;
@@ -1128,6 +1218,7 @@ GBool JPXStream::readCodestream(Guint len) {
}
break;
case 0x5e: // RGN - region of interest
+ cover(25);
#if 1 //~ ROI is unimplemented
fprintf(stderr, "RGN\n");
for (i = 0; i < segLen - 2; ++i) {
@@ -1148,6 +1239,7 @@ GBool JPXStream::readCodestream(Guint len) {
#endif
break;
case 0x5f: // POC - progression order change
+ cover(26);
#if 1 //~ progression order changes are unimplemented
fprintf(stderr, "POC\n");
for (i = 0; i < segLen - 2; ++i) {
@@ -1175,6 +1267,7 @@ GBool JPXStream::readCodestream(Guint len) {
#endif
break;
case 0x60: // PPM - packed packet headers, main header
+ cover(27);
#if 1 //~ packed packet headers are unimplemented
fprintf(stderr, "PPM\n");
for (i = 0; i < segLen - 2; ++i) {
@@ -1187,6 +1280,7 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x55: // TLM - tile-part lengths
// skipped
+ cover(28);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Error in JPX TLM marker segment");
@@ -1196,6 +1290,7 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x57: // PLM - packet length, main header
// skipped
+ cover(29);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Error in JPX PLM marker segment");
@@ -1205,6 +1300,7 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x63: // CRG - component registration
// skipped
+ cover(30);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Error in JPX CRG marker segment");
@@ -1214,6 +1310,7 @@ GBool JPXStream::readCodestream(Guint len) {
break;
case 0x64: // COM - comment
// skipped
+ cover(31);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Error in JPX COM marker segment");
@@ -1222,9 +1319,11 @@ GBool JPXStream::readCodestream(Guint len) {
}
break;
case 0x90: // SOT - start of tile
+ cover(32);
haveSOT = gTrue;
break;
default:
+ cover(33);
error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
@@ -1325,6 +1424,7 @@ GBool JPXStream::readTilePart() {
tilePartLen -= 2 + segLen;
switch (segType) {
case 0x52: // COD - coding style default
+ cover(34);
if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
!readUByte(&img.tiles[tileIdx].progOrder) ||
!readUWord(&img.tiles[tileIdx].nLayers) ||
@@ -1392,6 +1492,7 @@ GBool JPXStream::readTilePart() {
}
break;
case 0x53: // COC - coding style component
+ cover(35);
if ((img.nComps > 256 && !readUWord(&comp)) ||
(img.nComps <= 256 && !readUByte(&comp)) ||
comp >= img.nComps ||
@@ -1433,6 +1534,7 @@ GBool JPXStream::readTilePart() {
}
break;
case 0x5c: // QCD - quantization default
+ cover(36);
if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
error(getPos(), "Error in JPX QCD marker segment");
return gFalse;
@@ -1492,6 +1594,7 @@ GBool JPXStream::readTilePart() {
}
break;
case 0x5d: // QCC - quantization component
+ cover(37);
if ((img.nComps > 256 && !readUWord(&comp)) ||
(img.nComps <= 256 && !readUByte(&comp)) ||
comp >= img.nComps ||
@@ -1543,6 +1646,7 @@ GBool JPXStream::readTilePart() {
}
break;
case 0x5e: // RGN - region of interest
+ cover(38);
#if 1 //~ ROI is unimplemented
fprintf(stderr, "RGN\n");
for (i = 0; i < segLen - 2; ++i) {
@@ -1563,6 +1667,7 @@ GBool JPXStream::readTilePart() {
#endif
break;
case 0x5f: // POC - progression order change
+ cover(39);
#if 1 //~ progression order changes are unimplemented
fprintf(stderr, "POC\n");
for (i = 0; i < segLen - 2; ++i) {
@@ -1590,6 +1695,7 @@ GBool JPXStream::readTilePart() {
#endif
break;
case 0x61: // PPT - packed packet headers, tile-part hdr
+ cover(40);
#if 1 //~ packed packet headers are unimplemented
fprintf(stderr, "PPT\n");
for (i = 0; i < segLen - 2; ++i) {
@@ -1601,6 +1707,7 @@ GBool JPXStream::readTilePart() {
#endif
case 0x58: // PLT - packet length, tile-part header
// skipped
+ cover(41);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Error in JPX PLT marker segment");
@@ -1610,6 +1717,7 @@ GBool JPXStream::readTilePart() {
break;
case 0x64: // COM - comment
// skipped
+ cover(42);
for (i = 0; i < segLen - 2; ++i) {
if (str->getChar() == EOF) {
error(getPos(), "Error in JPX COM marker segment");
@@ -1618,9 +1726,11 @@ GBool JPXStream::readTilePart() {
}
break;
case 0x93: // SOD - start of data
+ cover(43);
haveSOD = gTrue;
break;
default:
+ cover(44);
error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
segType);
for (i = 0; i < segLen - 2; ++i) {
@@ -1818,6 +1928,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
while (1) {
if (tilePartToEOC) {
//~ peek for an EOC marker
+ cover(93);
} else if (tilePartLen == 0) {
break;
}
@@ -1828,12 +1939,16 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
//----- packet header
+ // setup
+ startBitBuf(tilePartLen);
+
// zero-length flag
if (!readBits(1, &bits)) {
goto err;
}
if (!bits) {
// packet is empty -- clear all code-block inclusion flags
+ cover(45);
for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
subband = &precinct->subbands[sb];
for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
@@ -1853,16 +1968,19 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
// skip code-blocks with no coefficients
if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
+ cover(46);
cb->included = gFalse;
continue;
}
// code-block inclusion
if (cb->seen) {
+ cover(47);
if (!readBits(1, &cb->included)) {
goto err;
}
} else {
+ cover(48);
ttVal = 0;
i = 0;
for (level = subband->maxTTLevel; level >= 0; --level) {
@@ -1896,9 +2014,11 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
}
if (cb->included) {
+ cover(49);
// zero bit-plane count
if (!cb->seen) {
+ cover(50);
ttVal = 0;
i = 0;
for (level = subband->maxTTLevel; level >= 0; --level) {
@@ -1932,26 +2052,33 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
goto err;
}
if (bits == 0) {
+ cover(51);
cb->nCodingPasses = 1;
} else {
if (!readBits(1, &bits)) {
goto err;
}
if (bits == 0) {
+ cover(52);
cb->nCodingPasses = 2;
} else {
+ cover(53);
if (!readBits(2, &bits)) {
goto err;
}
if (bits < 3) {
+ cover(54);
cb->nCodingPasses = 3 + bits;
} else {
+ cover(55);
if (!readBits(5, &bits)) {
goto err;
}
if (bits < 31) {
+ cover(56);
cb->nCodingPasses = 6 + bits;
} else {
+ cover(57);
if (!readBits(7, &bits)) {
goto err;
}
@@ -1985,8 +2112,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
}
}
}
- tilePartLen -= byteCount;
- clearBitBuf();
+ tilePartLen = finishBitBuf();
//----- packet data
@@ -2011,6 +2137,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
switch (tile->progOrder) {
case 0: // layer, resolution level, component, precinct
+ cover(58);
if (++tile->comp == img.nComps) {
tile->comp = 0;
if (++tile->res == tile->maxNDecompLevels + 1) {
@@ -2022,6 +2149,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
}
break;
case 1: // resolution level, layer, component, precinct
+ cover(59);
if (++tile->comp == img.nComps) {
tile->comp = 0;
if (++tile->layer == tile->nLayers) {
@@ -2034,6 +2162,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
break;
case 2: // resolution level, precinct, component, layer
//~ this isn't correct -- see B.12.1.3
+ cover(60);
if (++tile->layer == tile->nLayers) {
tile->layer = 0;
if (++tile->comp == img.nComps) {
@@ -2046,6 +2175,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
break;
case 3: // precinct, component, resolution level, layer
//~ this isn't correct -- see B.12.1.4
+ cover(61);
if (++tile->layer == tile->nLayers) {
tile->layer = 0;
if (++tile->res == tile->maxNDecompLevels + 1) {
@@ -2058,6 +2188,7 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
break;
case 4: // component, precinct, resolution level, layer
//~ this isn't correct -- see B.12.1.5
+ cover(62);
if (++tile->layer == tile->nLayers) {
tile->layer = 0;
if (++tile->res == tile->maxNDecompLevels + 1) {
@@ -2090,8 +2221,10 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
Guint i, x, y0, y1, y2;
if (cb->arithDecoder) {
+ cover(63);
cb->arithDecoder->restart(cb->dataLen);
} else {
+ cover(64);
cb->arithDecoder = new JArithmeticDecoder();
cb->arithDecoder->setStream(str, cb->dataLen);
cb->arithDecoder->start();
@@ -2106,6 +2239,7 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
//----- significance propagation pass
case jpxPassSigProp:
+ cover(65);
for (y0 = cb->y0, coeff0 = cb->coeffs;
y0 < cb->y1;
y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
@@ -2183,6 +2317,7 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
//----- magnitude refinement pass
case jpxPassMagRef:
+ cover(66);
for (y0 = cb->y0, coeff0 = cb->coeffs;
y0 < cb->y1;
y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
@@ -2244,6 +2379,7 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
//----- cleanup pass
case jpxPassCleanup:
+ cover(67);
for (y0 = cb->y0, coeff0 = cb->coeffs;
y0 < cb->y1;
y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
@@ -2405,6 +2541,8 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
Guint nx0, ny0, nx1, ny1;
Guint r, cbX, cbY, x, y;
+ cover(68);
+
//----- (NL)LL subband (resolution level 0)
resLevel = &tileComp->resLevels[0];
@@ -2415,14 +2553,17 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
qStyle = tileComp->quantStyle & 0x1f;
guard = (tileComp->quantStyle >> 5) & 7;
if (qStyle == 0) {
+ cover(69);
eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
shift = guard + eps - 1;
mu = 0; // make gcc happy
} else {
+ cover(70);
shift = guard - 1 + tileComp->prec;
mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
}
if (tileComp->transform == 0) {
+ cover(71);
shift += fracBits;
}
@@ -2442,18 +2583,24 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
if (val != 0) {
shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
if (shift2 > 0) {
+ cover(94);
val = (val << shift2) + (1 << (shift2 - 1));
} else {
+ cover(95);
val >>= -shift2;
}
if (qStyle == 0) {
+ cover(96);
if (tileComp->transform == 0) {
+ cover(97);
val &= -1 << fracBits;
}
} else {
+ cover(98);
val = (int)((double)val * mu);
}
if (coeff->flags & jpxCoeffSign) {
+ cover(99);
val = -val;
}
}
@@ -2474,11 +2621,13 @@ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
// and inverse transform to get (n-1)LL, which will be stored
// in the upper-left corner of the tile-component data array
if (r == tileComp->nDecompLevels) {
+ cover(72);
nx0 = tileComp->x0;
ny0 = tileComp->y0;
nx1 = tileComp->x1;
ny1 = tileComp->y1;
} else {
+ cover(73);
nx0 = tileComp->resLevels[r+1].x0;
ny0 = tileComp->resLevels[r+1].y0;
nx1 = tileComp->resLevels[r+1].x1;
@@ -2531,18 +2680,22 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
// i-quant parameters
if (qStyle == 0) {
+ cover(100);
eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
shift = guard + eps - 1;
mu = 0; // make gcc happy
} else {
+ cover(101);
shift = guard + tileComp->prec;
if (sb == 2) {
+ cover(102);
++shift;
}
t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
}
if (tileComp->transform == 0) {
+ cover(103);
shift += fracBits;
}
@@ -2565,18 +2718,23 @@ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
if (val != 0) {
shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
if (shift2 > 0) {
+ cover(74);
val = (val << shift2) + (1 << (shift2 - 1));
} else {
+ cover(75);
val >>= -shift2;
}
if (qStyle == 0) {
+ cover(76);
if (tileComp->transform == 0) {
val &= -1 << fracBits;
}
} else {
+ cover(77);
val = (int)((double)val * mu);
}
if (coeff->flags & jpxCoeffSign) {
+ cover(78);
val = -val;
}
}
@@ -2613,11 +2771,14 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
//----- special case for length = 1
if (i1 - i0 == 1) {
+ cover(79);
if (i0 & 1) {
+ cover(104);
*data >>= 1;
}
} else {
+ cover(80);
// choose an offset: this makes even buf[] indexes correspond to
// odd values of i, and vice versa
@@ -2633,19 +2794,25 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
//----- extend right
buf[end] = buf[end - 2];
if (i1 - i0 == 2) {
+ cover(81);
buf[end+1] = buf[offset + 1];
buf[end+2] = buf[offset];
buf[end+3] = buf[offset + 1];
} else {
+ cover(82);
buf[end+1] = buf[end - 3];
if (i1 - i0 == 3) {
+ cover(105);
buf[end+2] = buf[offset + 1];
buf[end+3] = buf[offset + 2];
} else {
+ cover(106);
buf[end+2] = buf[end - 4];
if (i1 - i0 == 4) {
+ cover(107);
buf[end+3] = buf[offset + 1];
} else {
+ cover(108);
buf[end+3] = buf[end - 5];
}
}
@@ -2656,12 +2823,14 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
buf[offset - 2] = buf[offset + 2];
buf[offset - 3] = buf[offset + 3];
if (offset == 4) {
+ cover(83);
buf[0] = buf[offset + 4];
}
//----- 9-7 irreversible filter
if (tileComp->transform == 0) {
+ cover(84);
// step 1 (even)
for (i = 1; i <= end + 2; i += 2) {
buf[i] = (int)(idwtKappa * buf[i]);
@@ -2690,6 +2859,7 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
//----- 5-3 reversible filter
} else {
+ cover(85);
// step 1 (even)
for (i = 3; i <= end; i += 2) {
buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
@@ -2718,6 +2888,7 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
//----- inverse multi-component transform
if (tile->multiComp == 1) {
+ cover(86);
if (img.nComps < 3 ||
tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
@@ -2728,6 +2899,7 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
// inverse irreversible multiple component transform
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) {
@@ -2744,6 +2916,7 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
// inverse reversible multiple component transform
} 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) {
@@ -2765,6 +2938,7 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
// signed: clip
if (tileComp->sgned) {
+ cover(89);
minVal = -(1 << (tileComp->prec - 1));
maxVal = (1 << (tileComp->prec - 1)) - 1;
dataPtr = tileComp->data;
@@ -2772,11 +2946,14 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
coeff = *dataPtr;
if (tileComp->transform == 0) {
+ cover(109);
coeff >>= fracBits;
}
if (coeff < minVal) {
+ cover(110);
coeff = minVal;
} else if (coeff > maxVal) {
+ cover(111);
coeff = maxVal;
}
*dataPtr++ = coeff;
@@ -2785,6 +2962,7 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
// unsigned: inverse DC level shift and clip
} else {
+ cover(90);
maxVal = (1 << tileComp->prec) - 1;
zeroVal = 1 << (tileComp->prec - 1);
dataPtr = tileComp->data;
@@ -2792,12 +2970,15 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
coeff = *dataPtr;
if (tileComp->transform == 0) {
+ cover(112);
coeff >>= fracBits;
}
coeff += zeroVal;
if (coeff < 0) {
+ cover(113);
coeff = 0;
} else if (coeff > maxVal) {
+ cover(114);
coeff = maxVal;
}
*dataPtr++ = coeff;
@@ -2930,10 +3111,10 @@ GBool JPXStream::readBits(int nBits, Guint *x) {
int c;
while (bitBufLen < nBits) {
- if ((c = str->getChar()) == EOF) {
+ if (byteCount == 0 || (c = str->getChar()) == EOF) {
return gFalse;
}
- ++byteCount;
+ --byteCount;
if (bitBufSkip) {
bitBuf = (bitBuf << 7) | (c & 0x7f);
bitBufLen += 7;
@@ -2948,8 +3129,16 @@ GBool JPXStream::readBits(int nBits, Guint *x) {
return gTrue;
}
-void JPXStream::clearBitBuf() {
+void JPXStream::startBitBuf(Guint byteCountA) {
bitBufLen = 0;
bitBufSkip = gFalse;
- byteCount = 0;
+ byteCount = byteCountA;
+}
+
+Guint JPXStream::finishBitBuf() {
+ if (bitBufSkip) {
+ str->getChar();
+ --byteCount;
+ }
+ return byteCount;
}
diff --git a/Build/source/libs/xpdf/xpdf/JPXStream.h b/Build/source/libs/xpdf/xpdf/JPXStream.h
index e64731db08a..e96e7d388e9 100644
--- a/Build/source/libs/xpdf/xpdf/JPXStream.h
+++ b/Build/source/libs/xpdf/xpdf/JPXStream.h
@@ -19,6 +19,7 @@
#include "Object.h"
#include "Stream.h"
+class JArithmeticDecoder;
class JArithmeticDecoderStats;
//------------------------------------------------------------------------
@@ -277,6 +278,7 @@ public:
virtual ~JPXStream();
virtual StreamKind getKind() { return strJPX; }
virtual void reset();
+ virtual void close();
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent);
@@ -317,7 +319,8 @@ private:
GBool readULong(Guint *x);
GBool readNBytes(int nBytes, GBool signd, int *x);
GBool readBits(int nBits, Guint *x);
- void clearBitBuf();
+ void startBitBuf(Guint byteCountA);
+ Guint finishBitBuf();
Guint nComps; // number of components
Guint *bpc; // bits per component, for each component
@@ -338,8 +341,7 @@ private:
int bitBufLen; // number of bits in bitBuf
GBool bitBufSkip; // true if next bit should be skipped
// (for bit stuffing)
- Guint byteCount; // number of bytes read since last call
- // to clearBitBuf
+ Guint byteCount; // number of available bytes left
Guint curX, curY, curComp; // current position for lookChar/getChar
Guint readBuf; // read buffer
diff --git a/Build/source/libs/xpdf/xpdf/Link.cc b/Build/source/libs/xpdf/xpdf/Link.cc
index 898ca20c355..ae2de537e36 100644
--- a/Build/source/libs/xpdf/xpdf/Link.cc
+++ b/Build/source/libs/xpdf/xpdf/Link.cc
@@ -288,7 +288,7 @@ LinkDest::LinkDest(Array *a) {
kind = destFitH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
top = obj2.getNum();
obj2.free();
@@ -302,7 +302,7 @@ LinkDest::LinkDest(Array *a) {
kind = destFitV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
left = obj2.getNum();
obj2.free();
@@ -316,25 +316,25 @@ LinkDest::LinkDest(Array *a) {
kind = destFitR;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
left = obj2.getNum();
obj2.free();
if (!a->get(3, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
bottom = obj2.getNum();
obj2.free();
if (!a->get(4, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
right = obj2.getNum();
obj2.free();
if (!a->get(5, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
top = obj2.getNum();
obj2.free();
@@ -356,7 +356,7 @@ LinkDest::LinkDest(Array *a) {
kind = destFitBH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
top = obj2.getNum();
obj2.free();
@@ -370,7 +370,7 @@ LinkDest::LinkDest(Array *a) {
kind = destFitBV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
- goto err1;
+ kind = destFit;
}
left = obj2.getNum();
obj2.free();
@@ -635,42 +635,13 @@ LinkUnknown::~LinkUnknown() {
}
//------------------------------------------------------------------------
-// LinkBorderStyle
-//------------------------------------------------------------------------
-
-LinkBorderStyle::LinkBorderStyle(LinkBorderType 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;
-}
-
-LinkBorderStyle::~LinkBorderStyle() {
- if (dash) {
- gfree(dash);
- }
-}
-
-//------------------------------------------------------------------------
// Link
//------------------------------------------------------------------------
Link::Link(Dict *dict, GString *baseURI) {
- Object obj1, obj2, obj3;
- LinkBorderType borderType;
- double borderWidth;
- double *borderDash;
- int borderDashLength;
- double borderR, borderG, borderB;
+ Object obj1, obj2;
double t;
- int i;
- borderStyle = NULL;
action = NULL;
ok = gFalse;
@@ -715,97 +686,6 @@ Link::Link(Dict *dict, GString *baseURI) {
y2 = t;
}
- // get the border style info
- borderType = linkBorderSolid;
- borderWidth = 1;
- borderDash = NULL;
- borderDashLength = 0;
- borderR = 0;
- borderG = 0;
- borderB = 1;
- if (dict->lookup("BS", &obj1)->isDict()) {
- if (obj1.dictLookup("S", &obj2)->isName()) {
- if (obj2.isName("S")) {
- borderType = linkBorderSolid;
- } else if (obj2.isName("D")) {
- borderType = linkBorderDashed;
- } else if (obj2.isName("B")) {
- borderType = linkBorderEmbossed;
- } else if (obj2.isName("I")) {
- borderType = linkBorderEngraved;
- } else if (obj2.isName("U")) {
- borderType = linkBorderUnderlined;
- }
- }
- 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 = linkBorderDashed;
- 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();
- }
- }
- }
- }
- 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 LinkBorderStyle(borderType, borderWidth,
- borderDash, borderDashLength,
- borderR, borderG, borderB);
-
// look for destination
if (!dict->lookup("Dest", &obj1)->isNull()) {
action = LinkAction::parseDest(&obj1);
@@ -833,9 +713,6 @@ Link::Link(Dict *dict, GString *baseURI) {
}
Link::~Link() {
- if (borderStyle) {
- delete borderStyle;
- }
if (action) {
delete action;
}
diff --git a/Build/source/libs/xpdf/xpdf/Link.h b/Build/source/libs/xpdf/xpdf/Link.h
index 9f044204966..698f2c85294 100644
--- a/Build/source/libs/xpdf/xpdf/Link.h
+++ b/Build/source/libs/xpdf/xpdf/Link.h
@@ -302,42 +302,6 @@ private:
};
//------------------------------------------------------------------------
-// LinkBorderStyle
-//------------------------------------------------------------------------
-
-enum LinkBorderType {
- linkBorderSolid,
- linkBorderDashed,
- linkBorderEmbossed,
- linkBorderEngraved,
- linkBorderUnderlined
-};
-
-class LinkBorderStyle {
-public:
-
- LinkBorderStyle(LinkBorderType typeA, double widthA,
- double *dashA, int dashLengthA,
- double rA, double gA, double bA);
- ~LinkBorderStyle();
-
- LinkBorderType 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; }
-
-private:
-
- LinkBorderType type;
- double width;
- double *dash;
- int dashLength;
- double r, g, b;
-};
-
-//------------------------------------------------------------------------
// Link
//------------------------------------------------------------------------
@@ -364,14 +328,10 @@ public:
void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
{ *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
- // Get the border style info.
- LinkBorderStyle *getBorderStyle() { return borderStyle; }
-
private:
double x1, y1; // lower left corner
double x2, y2; // upper right corner
- LinkBorderStyle *borderStyle; // border style
LinkAction *action; // action
GBool ok; // is link valid?
};
diff --git a/Build/source/libs/xpdf/xpdf/OutputDev.cc b/Build/source/libs/xpdf/xpdf/OutputDev.cc
index cfa41619e04..8d4763b7d83 100644
--- a/Build/source/libs/xpdf/xpdf/OutputDev.cc
+++ b/Build/source/libs/xpdf/xpdf/OutputDev.cc
@@ -55,6 +55,7 @@ void OutputDev::updateAll(GfxState *state) {
updateLineCap(state);
updateMiterLimit(state);
updateLineWidth(state);
+ updateStrokeAdjust(state);
updateFillColorSpace(state);
updateFillColor(state);
updateStrokeColorSpace(state);
@@ -64,6 +65,7 @@ void OutputDev::updateAll(GfxState *state) {
updateStrokeOpacity(state);
updateFillOverprint(state);
updateStrokeOverprint(state);
+ updateTransfer(state);
updateFont(state);
}
diff --git a/Build/source/libs/xpdf/xpdf/OutputDev.h b/Build/source/libs/xpdf/xpdf/OutputDev.h
index fdb0edcbe18..27dc0dd9c16 100644
--- a/Build/source/libs/xpdf/xpdf/OutputDev.h
+++ b/Build/source/libs/xpdf/xpdf/OutputDev.h
@@ -20,14 +20,18 @@
class GString;
class GfxState;
+struct GfxColor;
class GfxColorSpace;
class GfxImageColorMap;
class GfxFunctionShading;
class GfxAxialShading;
class GfxRadialShading;
class Stream;
+class Links;
class Link;
class Catalog;
+class Page;
+class Function;
//------------------------------------------------------------------------
// OutputDev
@@ -61,6 +65,10 @@ public:
// will be reduced to a series of other drawing operations.
virtual GBool useShadedFills() { return gFalse; }
+ // Does this device use drawForm()? If this returns false,
+ // form-type XObjects will be interpreted (i.e., unrolled).
+ virtual GBool useDrawForm() { return gFalse; }
+
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() = 0;
@@ -73,6 +81,18 @@ public:
// Set default transform matrix.
virtual void setDefaultCTM(double *ctm);
+ // Check to see if a page slice should be displayed. If this
+ // returns false, the page display is aborted. Typically, an
+ // OutputDev will use some alternate means to display the page
+ // before returning false.
+ virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI,
+ int rotate, GBool useMediaBox, GBool crop,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ GBool printing, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL)
+ { return gTrue; }
+
// Start a page.
virtual void startPage(int pageNum, GfxState *state) {}
@@ -91,9 +111,6 @@ public:
double *getDefCTM() { return defCTM; }
double *getDefICTM() { return defICTM; }
- //----- link borders
- virtual void drawLink(Link *link, Catalog *catalog) {}
-
//----- save/restore graphics state
virtual void saveState(GfxState *state) {}
virtual void restoreState(GfxState *state) {}
@@ -108,6 +125,7 @@ public:
virtual void updateLineCap(GfxState *state) {}
virtual void updateMiterLimit(GfxState *state) {}
virtual void updateLineWidth(GfxState *state) {}
+ virtual void updateStrokeAdjust(GfxState *state) {}
virtual void updateFillColorSpace(GfxState *state) {}
virtual void updateStrokeColorSpace(GfxState *state) {}
virtual void updateFillColor(GfxState *state) {}
@@ -117,6 +135,7 @@ public:
virtual void updateStrokeOpacity(GfxState *state) {}
virtual void updateFillOverprint(GfxState *state) {}
virtual void updateStrokeOverprint(GfxState *state) {}
+ virtual void updateTransfer(GfxState *state) {}
//----- update text state
virtual void updateFont(GfxState *state) {}
@@ -138,14 +157,18 @@ public:
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
double xStep, double yStep) {}
- virtual void functionShadedFill(GfxState *state,
- GfxFunctionShading *shading) {}
- virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading) {}
- virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading) {}
+ virtual GBool functionShadedFill(GfxState *state,
+ GfxFunctionShading *shading)
+ { return gFalse; }
+ virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading)
+ { return gFalse; }
+ virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading)
+ { return gFalse; }
//----- path clipping
virtual void clip(GfxState *state) {}
virtual void eoClip(GfxState *state) {}
+ virtual void clipToStrokePath(GfxState *state) {}
//----- text drawing
virtual void beginStringOp(GfxState *state) {}
@@ -193,9 +216,31 @@ public:
virtual void type3D1(GfxState *state, double wx, double wy,
double llx, double lly, double urx, double ury) {}
+ //----- form XObjects
+ virtual void drawForm(Ref id) {}
+
//----- PostScript XObjects
virtual void psXObject(Stream *psStream, Stream *level1Stream) {}
+ //----- transparency groups and soft masks
+ virtual void beginTransparencyGroup(GfxState *state, double *bbox,
+ GfxColorSpace *blendingColorSpace,
+ GBool isolated, GBool knockout,
+ GBool forSoftMask) {}
+ virtual void endTransparencyGroup(GfxState *state) {}
+ virtual void paintTransparencyGroup(GfxState *state, double *bbox) {}
+ virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha,
+ Function *transferFunc, GfxColor *backdropColor) {}
+ virtual void clearSoftMask(GfxState *state) {}
+
+ //----- links
+ virtual void processLink(Link *link, Catalog *catalog) {}
+
+#if 1 //~tmp: turn off anti-aliasing temporarily
+ virtual GBool getVectorAntialias() { return gFalse; }
+ virtual void setVectorAntialias(GBool vaa) {}
+#endif
+
private:
double defCTM[6]; // default coordinate transform matrix
diff --git a/Build/source/libs/xpdf/xpdf/PDFDoc.cc b/Build/source/libs/xpdf/xpdf/PDFDoc.cc
index 92863e49e0e..c559eefcfb7 100644
--- a/Build/source/libs/xpdf/xpdf/PDFDoc.cc
+++ b/Build/source/libs/xpdf/xpdf/PDFDoc.cc
@@ -61,7 +61,6 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
str = NULL;
xref = NULL;
catalog = NULL;
- links = NULL;
#ifndef DISABLE_OUTLINE
outline = NULL;
#endif
@@ -119,7 +118,6 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword,
str = NULL;
xref = NULL;
catalog = NULL;
- links = NULL;
#ifndef DISABLE_OUTLINE
outline = NULL;
#endif
@@ -164,12 +162,15 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
ok = gFalse;
errCode = errNone;
guiData = guiDataA;
- fileName = NULL;
+ if (strA->getFileName()) {
+ fileName = strA->getFileName()->copy();
+ } else {
+ fileName = NULL;
+ }
file = NULL;
str = strA;
xref = NULL;
catalog = NULL;
- links = NULL;
#ifndef DISABLE_OUTLINE
outline = NULL;
#endif
@@ -234,9 +235,6 @@ PDFDoc::~PDFDoc() {
if (fileName) {
delete fileName;
}
- if (links) {
- delete links;
- }
}
// Check for a PDF header on this stream. Skip past some garbage
@@ -288,7 +286,8 @@ GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) {
secHdlr->getOwnerPasswordOk(),
secHdlr->getFileKey(),
secHdlr->getFileKeyLength(),
- secHdlr->getEncVersion());
+ secHdlr->getEncVersion(),
+ secHdlr->getEncAlgorithm());
ret = gTrue;
} else {
// authorization failed
@@ -307,73 +306,51 @@ GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) {
return ret;
}
-void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- GBool doLinks,
+void PDFDoc::displayPage(OutputDev *out, int page,
+ double hDPI, double vDPI, int rotate,
+ GBool useMediaBox, GBool crop, GBool printing,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
- Page *p;
-
if (globalParams->getPrintCommands()) {
printf("***** page %d *****\n", page);
}
- p = catalog->getPage(page);
- if (doLinks) {
- if (links) {
- delete links;
- }
- getLinks(p);
- p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, links, catalog,
- abortCheckCbk, abortCheckCbkData);
- } else {
- p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, NULL, catalog,
- abortCheckCbk, abortCheckCbkData);
- }
+ catalog->getPage(page)->display(out, hDPI, vDPI,
+ rotate, useMediaBox, crop, printing, catalog,
+ abortCheckCbk, abortCheckCbkData);
}
void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
+ GBool useMediaBox, GBool crop, GBool printing,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
int page;
for (page = firstPage; page <= lastPage; ++page) {
- displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, doLinks,
+ displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, printing,
abortCheckCbk, abortCheckCbkData);
}
}
void PDFDoc::displayPageSlice(OutputDev *out, int page,
double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
+ GBool useMediaBox, GBool crop, GBool printing,
int sliceX, int sliceY, int sliceW, int sliceH,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
- Page *p;
-
- p = catalog->getPage(page);
- if (doLinks) {
- if (links) {
- delete links;
- }
- getLinks(p);
- p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- links, catalog, abortCheckCbk, abortCheckCbkData);
- } else {
- p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- sliceX, sliceY, sliceW, sliceH,
- NULL, catalog, abortCheckCbk, abortCheckCbkData);
- }
+ catalog->getPage(page)->displaySlice(out, hDPI, vDPI,
+ rotate, useMediaBox, crop,
+ sliceX, sliceY, sliceW, sliceH,
+ printing, catalog,
+ abortCheckCbk, abortCheckCbkData);
}
-Links *PDFDoc::takeLinks() {
- Links *ret;
+Links *PDFDoc::getLinks(int page) {
+ return catalog->getPage(page)->getLinks(catalog);
+}
- ret = links;
- links = NULL;
- return ret;
+void PDFDoc::processLinks(OutputDev *out, int page) {
+ catalog->getPage(page)->processLinks(out, catalog);
}
GBool PDFDoc::isLinearized() {
@@ -385,7 +362,8 @@ GBool PDFDoc::isLinearized() {
obj1.initNull();
parser = new Parser(xref,
new Lexer(xref,
- str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
+ str->makeSubStream(str->getStart(), gFalse, 0, &obj1)),
+ gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
@@ -422,10 +400,3 @@ GBool PDFDoc::saveAs(GString *name) {
fclose(f);
return gTrue;
}
-
-void PDFDoc::getLinks(Page *page) {
- Object obj;
-
- links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
- obj.free();
-}
diff --git a/Build/source/libs/xpdf/xpdf/PDFDoc.h b/Build/source/libs/xpdf/xpdf/PDFDoc.h
index a1f42c08d94..208b61efa97 100644
--- a/Build/source/libs/xpdf/xpdf/PDFDoc.h
+++ b/Build/source/libs/xpdf/xpdf/PDFDoc.h
@@ -86,23 +86,23 @@ public:
Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
// Display a page.
- void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
- int rotate, GBool useMediaBox, GBool crop,
- GBool doLinks,
+ void displayPage(OutputDev *out, int page,
+ double hDPI, double vDPI, int rotate,
+ GBool useMediaBox, GBool crop, GBool printing,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
+ GBool useMediaBox, GBool crop, GBool printing,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
// Display part of a page.
void displayPageSlice(OutputDev *out, int page,
double hDPI, double vDPI, int rotate,
- GBool useMediaBox, GBool crop, GBool doLinks,
+ GBool useMediaBox, GBool crop, GBool printing,
int sliceX, int sliceY, int sliceW, int sliceH,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
@@ -113,13 +113,16 @@ public:
// Returns the links for the current page, transferring ownership to
// the caller.
- Links *takeLinks();
+ Links *getLinks(int page);
// Find a named destination. Returns the link destination, or
// NULL if <name> is not a destination.
LinkDest *findDest(GString *name)
{ return catalog->findDest(name); }
+ // Process the links for a page.
+ void processLinks(OutputDev *out, int page);
+
#ifndef DISABLE_OUTLINE
// Return the outline object.
Outline *getOutline() { return outline; }
@@ -160,7 +163,6 @@ private:
GBool setup(GString *ownerPassword, GString *userPassword);
void checkHeader();
GBool checkEncryption(GString *ownerPassword, GString *userPassword);
- void getLinks(Page *page);
GString *fileName;
FILE *file;
@@ -169,7 +171,6 @@ private:
double pdfVersion;
XRef *xref;
Catalog *catalog;
- Links *links;
#ifndef DISABLE_OUTLINE
Outline *outline;
#endif
diff --git a/Build/source/libs/xpdf/xpdf/PSTokenizer.cc b/Build/source/libs/xpdf/xpdf/PSTokenizer.cc
index a65c3241c0f..0ad37618563 100644
--- a/Build/source/libs/xpdf/xpdf/PSTokenizer.cc
+++ b/Build/source/libs/xpdf/xpdf/PSTokenizer.cc
@@ -95,7 +95,7 @@ GBool PSTokenizer::getToken(char *buf, int size, int *length) {
} else if (c == '<') {
while ((c = lookChar()) != EOF) {
getChar();
- if (i < size - 1) {
+ if (i < size - 1 && specialChars[c] != 1) {
buf[i++] = c;
}
if (c == '>') {
diff --git a/Build/source/libs/xpdf/xpdf/Page.cc b/Build/source/libs/xpdf/xpdf/Page.cc
index 47171571cff..2a7540b06c0 100644
--- a/Build/source/libs/xpdf/xpdf/Page.cc
+++ b/Build/source/libs/xpdf/xpdf/Page.cc
@@ -2,7 +2,7 @@
//
// Page.cc
//
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
//
//========================================================================
@@ -26,9 +26,37 @@
#include "Annot.h"
#endif
#include "Error.h"
+#include "Catalog.h"
#include "Page.h"
//------------------------------------------------------------------------
+// PDFRectangle
+//------------------------------------------------------------------------
+
+void PDFRectangle::clipTo(PDFRectangle *rect) {
+ if (x1 < rect->x1) {
+ x1 = rect->x1;
+ } else if (x1 > rect->x2) {
+ x1 = rect->x2;
+ }
+ if (x2 < rect->x1) {
+ x2 = rect->x1;
+ } else if (x2 > rect->x2) {
+ x2 = rect->x2;
+ }
+ if (y1 < rect->y1) {
+ y1 = rect->y1;
+ } else if (y1 > rect->y2) {
+ y1 = rect->y2;
+ }
+ if (y2 < rect->y1) {
+ y2 = rect->y1;
+ } else if (y2 > rect->y2) {
+ y2 = rect->y2;
+ }
+}
+
+//------------------------------------------------------------------------
// PageAttrs
//------------------------------------------------------------------------
@@ -74,6 +102,12 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
artBox = cropBox;
readBox(dict, "ArtBox", &artBox);
+ // clip all other boxes to the media box
+ cropBox.clipTo(&mediaBox);
+ bleedBox.clipTo(&mediaBox);
+ trimBox.clipTo(&mediaBox);
+ artBox.clipTo(&mediaBox);
+
// rotate
dict->lookup("Rotate", &obj1);
if (obj1.isInt()) {
@@ -213,32 +247,47 @@ Page::~Page() {
contents.free();
}
+Links *Page::getLinks(Catalog *catalog) {
+ Links *links;
+ Object obj;
+
+ links = new Links(getAnnots(&obj), catalog->getBaseURI());
+ obj.free();
+ return links;
+}
+
void Page::display(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
- Links *links, Catalog *catalog,
+ GBool printing, Catalog *catalog,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
- -1, -1, -1, -1, links, catalog,
+ -1, -1, -1, -1, printing, catalog,
abortCheckCbk, abortCheckCbkData);
}
void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
int sliceX, int sliceY, int sliceW, int sliceH,
- Links *links, Catalog *catalog,
+ GBool printing, Catalog *catalog,
GBool (*abortCheckCbk)(void *data),
void *abortCheckCbkData) {
#ifndef PDF_PARSER_ONLY
- PDFRectangle *mediaBox, *cropBox, *baseBox;
+ PDFRectangle *mediaBox, *cropBox;
PDFRectangle box;
Gfx *gfx;
Object obj;
- Link *link;
Annots *annotList;
- double kx, ky;
+ Dict *acroForm;
int i;
+ if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop,
+ sliceX, sliceY, sliceW, sliceH,
+ printing, catalog,
+ abortCheckCbk, abortCheckCbkData)) {
+ return;
+ }
+
rotate += getRotate();
if (rotate >= 360) {
rotate -= 360;
@@ -246,61 +295,12 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
rotate += 360;
}
- mediaBox = getMediaBox();
+ makeBox(hDPI, vDPI, rotate, useMediaBox, out->upsideDown(),
+ sliceX, sliceY, sliceW, sliceH, &box, &crop);
cropBox = getCropBox();
- if (sliceW >= 0 && sliceH >= 0) {
- baseBox = useMediaBox ? mediaBox : cropBox;
- kx = 72.0 / hDPI;
- ky = 72.0 / vDPI;
- if (rotate == 90) {
- if (out->upsideDown()) {
- box.x1 = baseBox->x1 + ky * sliceY;
- box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
- } else {
- box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
- box.x2 = baseBox->x2 - ky * sliceY;
- }
- box.y1 = baseBox->y1 + kx * sliceX;
- box.y2 = baseBox->y1 + kx * (sliceX + sliceW);
- } else if (rotate == 180) {
- box.x1 = baseBox->x2 - kx * (sliceX + sliceW);
- box.x2 = baseBox->x2 - kx * sliceX;
- if (out->upsideDown()) {
- box.y1 = baseBox->y1 + ky * sliceY;
- box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
- } else {
- box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
- box.y2 = baseBox->y2 - ky * sliceY;
- }
- } else if (rotate == 270) {
- if (out->upsideDown()) {
- box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
- box.x2 = baseBox->x2 - ky * sliceY;
- } else {
- box.x1 = baseBox->x1 + ky * sliceY;
- box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
- }
- box.y1 = baseBox->y2 - kx * (sliceX + sliceW);
- box.y2 = baseBox->y2 - kx * sliceX;
- } else {
- box.x1 = baseBox->x1 + kx * sliceX;
- box.x2 = baseBox->x1 + kx * (sliceX + sliceW);
- if (out->upsideDown()) {
- box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
- box.y2 = baseBox->y2 - ky * sliceY;
- } else {
- box.y1 = baseBox->y1 + ky * sliceY;
- box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
- }
- }
- } else if (useMediaBox) {
- box = *mediaBox;
- } else {
- box = *cropBox;
- crop = gFalse;
- }
if (globalParams->getPrintCommands()) {
+ mediaBox = getMediaBox();
printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2);
printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
@@ -319,26 +319,25 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
}
obj.free();
- // draw links
- if (links) {
- gfx->saveState();
- for (i = 0; i < links->getNumLinks(); ++i) {
- link = links->getLink(i);
- out->drawLink(link, catalog);
+ // draw annotations
+ annotList = new Annots(xref, catalog, getAnnots(&obj));
+ obj.free();
+ acroForm = catalog->getAcroForm()->isDict() ?
+ catalog->getAcroForm()->getDict() : NULL;
+ if (acroForm) {
+ if (acroForm->lookup("NeedAppearances", &obj)) {
+ if (obj.isBool() && obj.getBool()) {
+ annotList->generateAppearances(acroForm);
+ }
}
- gfx->restoreState();
- out->dump();
+ obj.free();
}
-
- // draw non-link annotations
- annotList = new Annots(xref, catalog, annots.fetch(xref, &obj));
- obj.free();
if (annotList->getNumAnnots() > 0) {
if (globalParams->getPrintCommands()) {
printf("***** Annotations\n");
}
for (i = 0; i < annotList->getNumAnnots(); ++i) {
- annotList->getAnnot(i)->draw(gfx);
+ annotList->getAnnot(i)->draw(gfx, printing);
}
out->dump();
}
@@ -348,9 +347,82 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
#endif
}
-void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
- int rotate, GBool upsideDown) {
+void Page::makeBox(double hDPI, double vDPI, int rotate,
+ GBool useMediaBox, GBool upsideDown,
+ double sliceX, double sliceY, double sliceW, double sliceH,
+ PDFRectangle *box, GBool *crop) {
+ PDFRectangle *mediaBox, *cropBox, *baseBox;
+ double kx, ky;
+
+ mediaBox = getMediaBox();
+ cropBox = getCropBox();
+ if (sliceW >= 0 && sliceH >= 0) {
+ baseBox = useMediaBox ? mediaBox : cropBox;
+ kx = 72.0 / hDPI;
+ ky = 72.0 / vDPI;
+ if (rotate == 90) {
+ if (upsideDown) {
+ box->x1 = baseBox->x1 + ky * sliceY;
+ box->x2 = baseBox->x1 + ky * (sliceY + sliceH);
+ } else {
+ box->x1 = baseBox->x2 - ky * (sliceY + sliceH);
+ box->x2 = baseBox->x2 - ky * sliceY;
+ }
+ box->y1 = baseBox->y1 + kx * sliceX;
+ box->y2 = baseBox->y1 + kx * (sliceX + sliceW);
+ } else if (rotate == 180) {
+ box->x1 = baseBox->x2 - kx * (sliceX + sliceW);
+ box->x2 = baseBox->x2 - kx * sliceX;
+ if (upsideDown) {
+ box->y1 = baseBox->y1 + ky * sliceY;
+ box->y2 = baseBox->y1 + ky * (sliceY + sliceH);
+ } else {
+ box->y1 = baseBox->y2 - ky * (sliceY + sliceH);
+ box->y2 = baseBox->y2 - ky * sliceY;
+ }
+ } else if (rotate == 270) {
+ if (upsideDown) {
+ box->x1 = baseBox->x2 - ky * (sliceY + sliceH);
+ box->x2 = baseBox->x2 - ky * sliceY;
+ } else {
+ box->x1 = baseBox->x1 + ky * sliceY;
+ box->x2 = baseBox->x1 + ky * (sliceY + sliceH);
+ }
+ box->y1 = baseBox->y2 - kx * (sliceX + sliceW);
+ box->y2 = baseBox->y2 - kx * sliceX;
+ } else {
+ box->x1 = baseBox->x1 + kx * sliceX;
+ box->x2 = baseBox->x1 + kx * (sliceX + sliceW);
+ if (upsideDown) {
+ box->y1 = baseBox->y2 - ky * (sliceY + sliceH);
+ box->y2 = baseBox->y2 - ky * sliceY;
+ } else {
+ box->y1 = baseBox->y1 + ky * sliceY;
+ box->y2 = baseBox->y1 + ky * (sliceY + sliceH);
+ }
+ }
+ } else if (useMediaBox) {
+ *box = *mediaBox;
+ } else {
+ *box = *cropBox;
+ *crop = gFalse;
+ }
+}
+
+void Page::processLinks(OutputDev *out, Catalog *catalog) {
+ Links *links;
+ int i;
+
+ links = getLinks(catalog);
+ for (i = 0; i < links->getNumLinks(); ++i) {
+ out->processLink(links->getLink(i), catalog);
+ }
+ delete links;
+}
+
#ifndef PDF_PARSER_ONLY
+void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
+ int rotate, GBool useMediaBox, GBool upsideDown) {
GfxState *state;
int i;
@@ -360,10 +432,12 @@ void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
} else if (rotate < 0) {
rotate += 360;
}
- state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown);
+ state = new GfxState(hDPI, vDPI,
+ useMediaBox ? getMediaBox() : getCropBox(),
+ rotate, upsideDown);
for (i = 0; i < 6; ++i) {
ctm[i] = state->getCTM()[i];
}
delete state;
-#endif
}
+#endif
diff --git a/Build/source/libs/xpdf/xpdf/Page.h b/Build/source/libs/xpdf/xpdf/Page.h
index 36f96e1ad60..cacc0d164bf 100644
--- a/Build/source/libs/xpdf/xpdf/Page.h
+++ b/Build/source/libs/xpdf/xpdf/Page.h
@@ -33,6 +33,7 @@ public:
PDFRectangle(double x1A, double y1A, double x2A, double y2A)
{ x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
+ void clipTo(PDFRectangle *rect);
};
//------------------------------------------------------------------------
@@ -112,6 +113,7 @@ public:
GBool isOk() { return ok; }
// Get page parameters.
+ int getNum() { return num; }
PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
PDFRectangle *getCropBox() { return attrs->getCropBox(); }
GBool isCropped() { return attrs->isCropped(); }
@@ -140,13 +142,16 @@ public:
// Get annotations array.
Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
+ // Return a list of links.
+ Links *getLinks(Catalog *catalog);
+
// Get contents.
Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
// Display a page.
void display(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
- Links *links, Catalog *catalog,
+ GBool printing, Catalog *catalog,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
@@ -154,13 +159,22 @@ public:
void displaySlice(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
int sliceX, int sliceY, int sliceW, int sliceH,
- Links *links, Catalog *catalog,
+ GBool printing, Catalog *catalog,
GBool (*abortCheckCbk)(void *data) = NULL,
void *abortCheckCbkData = NULL);
+ void makeBox(double hDPI, double vDPI, int rotate,
+ GBool useMediaBox, GBool upsideDown,
+ double sliceX, double sliceY, double sliceW, double sliceH,
+ PDFRectangle *box, GBool *crop);
+
+ void processLinks(OutputDev *out, Catalog *catalog);
+
+#ifndef PDF_PARSER_ONLY
// Get the page's default CTM.
void getDefaultCTM(double *ctm, double hDPI, double vDPI,
- int rotate, GBool upsideDown);
+ int rotate, GBool useMediaBox, GBool upsideDown);
+#endif
private:
diff --git a/Build/source/libs/xpdf/xpdf/Parser.cc b/Build/source/libs/xpdf/xpdf/Parser.cc
index af7c933114a..c1fc715219f 100644
--- a/Build/source/libs/xpdf/xpdf/Parser.cc
+++ b/Build/source/libs/xpdf/xpdf/Parser.cc
@@ -16,15 +16,16 @@
#include "Object.h"
#include "Array.h"
#include "Dict.h"
+#include "Decrypt.h"
#include "Parser.h"
#include "XRef.h"
#include "Error.h"
-#include "Decrypt.h"
-Parser::Parser(XRef *xrefA, Lexer *lexerA) {
+Parser::Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA) {
xref = xrefA;
lexer = lexerA;
inlineImg = 0;
+ allowStreams = allowStreamsA;
lexer->getObj(&buf1);
lexer->getObj(&buf2);
}
@@ -35,17 +36,16 @@ Parser::~Parser() {
delete lexer;
}
-Object *Parser::getObj(Object *obj,
- Guchar *fileKey, int keyLength,
+Object *Parser::getObj(Object *obj, Guchar *fileKey,
+ CryptAlgorithm encAlgorithm, int keyLength,
int objNum, int objGen) {
char *key;
Stream *str;
Object obj2;
int num;
- Decrypt *decrypt;
- GString *s;
- char *p;
- int i;
+ DecryptStream *decrypt;
+ GString *s, *s2;
+ int c;
// refill buffer after inline image data
if (inlineImg == 2) {
@@ -61,7 +61,8 @@ Object *Parser::getObj(Object *obj,
shift();
obj->initArray(xref);
while (!buf1.isCmd("]") && !buf1.isEOF())
- obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
+ obj->arrayAdd(getObj(&obj2, fileKey, encAlgorithm, keyLength,
+ objNum, objGen));
if (buf1.isEOF())
error(getPos(), "End of file inside array");
shift();
@@ -81,18 +82,18 @@ Object *Parser::getObj(Object *obj,
gfree(key);
break;
}
- obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
+ obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength,
+ objNum, objGen));
}
}
if (buf1.isEOF())
error(getPos(), "End of file inside dictionary");
- if (buf2.isCmd("stream")) {
- if ((str = makeStream(obj))) {
+ // stream objects are not allowed inside content streams or
+ // object streams
+ if (allowStreams && buf2.isCmd("stream")) {
+ if ((str = makeStream(obj, fileKey, encAlgorithm, keyLength,
+ objNum, objGen))) {
obj->initStream(str);
- if (fileKey) {
- str->getBaseStream()->doDecryption(fileKey, keyLength,
- objNum, objGen);
- }
} else {
obj->free();
obj->initError();
@@ -115,15 +116,19 @@ Object *Parser::getObj(Object *obj,
// string
} else if (buf1.isString() && fileKey) {
- buf1.copy(obj);
- s = obj->getString();
- decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
- for (i = 0, p = obj->getString()->getCString();
- i < s->getLength();
- ++i, ++p) {
- *p = decrypt->decryptByte(*p);
+ s = buf1.getString();
+ s2 = new GString();
+ obj2.initNull();
+ decrypt = new DecryptStream(new MemStream(s->getCString(), 0,
+ s->getLength(), &obj2),
+ fileKey, encAlgorithm, keyLength,
+ objNum, objGen);
+ decrypt->reset();
+ while ((c = decrypt->getChar()) != EOF) {
+ s2->append((char)c);
}
delete decrypt;
+ obj->initString(s2);
shift();
// simple object
@@ -135,7 +140,9 @@ Object *Parser::getObj(Object *obj,
return obj;
}
-Stream *Parser::makeStream(Object *dict) {
+Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
+ CryptAlgorithm encAlgorithm, int keyLength,
+ int objNum, int objGen) {
Object obj;
BaseStream *baseStr;
Stream *str;
@@ -186,6 +193,12 @@ Stream *Parser::makeStream(Object *dict) {
// make base stream
str = baseStr->makeSubStream(pos, gTrue, length, dict);
+ // handle decryption
+ if (fileKey) {
+ str = new DecryptStream(str, fileKey, encAlgorithm, keyLength,
+ objNum, objGen);
+ }
+
// get filters
str = str->addFilters(dict);
diff --git a/Build/source/libs/xpdf/xpdf/Parser.h b/Build/source/libs/xpdf/xpdf/Parser.h
index b583baf6398..a109558b026 100644
--- a/Build/source/libs/xpdf/xpdf/Parser.h
+++ b/Build/source/libs/xpdf/xpdf/Parser.h
@@ -25,14 +25,14 @@ class Parser {
public:
// Constructor.
- Parser(XRef *xrefA, Lexer *lexerA);
+ Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA);
// Destructor.
~Parser();
// Get the next object from the input stream.
- Object *getObj(Object *obj,
- Guchar *fileKey = NULL, int keyLength = 0,
+ Object *getObj(Object *obj, Guchar *fileKey = NULL,
+ CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0,
int objNum = 0, int objGen = 0);
// Get stream.
@@ -45,10 +45,13 @@ private:
XRef *xref; // the xref table for this PDF file
Lexer *lexer; // input stream
+ GBool allowStreams; // parse stream objects?
Object buf1, buf2; // next two tokens
int inlineImg; // set when inline image data is encountered
- Stream *makeStream(Object *dict);
+ Stream *makeStream(Object *dict, Guchar *fileKey,
+ CryptAlgorithm encAlgorithm, int keyLength,
+ int objNum, int objGen);
void shift();
};
diff --git a/Build/source/libs/xpdf/xpdf/SecurityHandler.cc b/Build/source/libs/xpdf/xpdf/SecurityHandler.cc
index 40e9f59fb15..ea0f9341dd3 100644
--- a/Build/source/libs/xpdf/xpdf/SecurityHandler.cc
+++ b/Build/source/libs/xpdf/xpdf/SecurityHandler.cc
@@ -153,6 +153,7 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
permObj.isInt()) {
encVersion = versionObj.getInt();
encRevision = revisionObj.getInt();
+ encAlgorithm = cryptRC4;
// revision 2 forces a 40-bit key - some buggy PDF generators
// set the Length value incorrectly
if (encRevision == 2 || !lengthObj.isInt()) {
@@ -172,7 +173,8 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
!strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
&cryptFilterObj)->isDict()) {
- if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) {
+ cryptFilterObj.dictLookup("CFM", &cfmObj);
+ if (cfmObj.isName("V2")) {
encVersion = 2;
encRevision = 3;
if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
@@ -180,6 +182,15 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
fileKeyLength = cfLengthObj.getInt();
}
cfLengthObj.free();
+ } else if (cfmObj.isName("AESV2")) {
+ encVersion = 2;
+ encRevision = 3;
+ encAlgorithm = cryptAES;
+ if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
+ //~ according to the spec, this should be cfLengthObj / 8
+ fileKeyLength = cfLengthObj.getInt();
+ }
+ cfLengthObj.free();
}
cfmObj.free();
}
@@ -312,6 +323,7 @@ ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA,
{
encryptDictA->copy(&encryptDict);
xsh = xshA;
+ encAlgorithm = cryptRC4; //~ this should be obtained via getKey
ok = gFalse;
if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA,
diff --git a/Build/source/libs/xpdf/xpdf/SecurityHandler.h b/Build/source/libs/xpdf/xpdf/SecurityHandler.h
index 127acb7695e..a27868c249d 100644
--- a/Build/source/libs/xpdf/xpdf/SecurityHandler.h
+++ b/Build/source/libs/xpdf/xpdf/SecurityHandler.h
@@ -74,6 +74,7 @@ public:
virtual Guchar *getFileKey() = 0;
virtual int getFileKeyLength() = 0;
virtual int getEncVersion() = 0;
+ virtual CryptAlgorithm getEncAlgorithm() = 0;
protected:
@@ -100,6 +101,7 @@ public:
virtual Guchar *getFileKey() { return fileKey; }
virtual int getFileKeyLength() { return fileKeyLength; }
virtual int getEncVersion() { return encVersion; }
+ virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; }
private:
@@ -109,6 +111,7 @@ private:
int fileKeyLength;
int encVersion;
int encRevision;
+ CryptAlgorithm encAlgorithm;
GBool encryptMetadata;
GString *ownerKey, *userKey;
@@ -138,6 +141,7 @@ public:
virtual Guchar *getFileKey() { return fileKey; }
virtual int getFileKeyLength() { return fileKeyLength; }
virtual int getEncVersion() { return encVersion; }
+ virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; }
private:
@@ -148,6 +152,7 @@ private:
Guchar fileKey[16];
int fileKeyLength;
int encVersion;
+ CryptAlgorithm encAlgorithm;
GBool ok;
};
#endif // ENABLE_PLUGINS
diff --git a/Build/source/libs/xpdf/xpdf/Stream.cc b/Build/source/libs/xpdf/xpdf/Stream.cc
index 5fa7791c436..68abafa7b8d 100644
--- a/Build/source/libs/xpdf/xpdf/Stream.cc
+++ b/Build/source/libs/xpdf/xpdf/Stream.cc
@@ -27,7 +27,6 @@
#include "Error.h"
#include "Object.h"
#include "Lexer.h"
-#include "Decrypt.h"
#include "GfxState.h"
#include "Stream.h"
#include "JBIG2Stream.h"
@@ -142,6 +141,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
int encoding;
GBool endOfLine, byteAlign, endOfBlock, black;
int columns, rows;
+ int colorXform;
Object globals, obj;
if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
@@ -227,7 +227,14 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
columns, rows, endOfBlock, black);
} else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
- str = new DCTStream(str);
+ colorXform = -1;
+ if (params->isDict()) {
+ if (params->dictLookup("ColorTransform", &obj)->isInt()) {
+ colorXform = obj.getInt();
+ }
+ obj.free();
+ }
+ str = new DCTStream(str, colorXform);
} else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
pred = 1;
columns = 1;
@@ -273,18 +280,10 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
BaseStream::BaseStream(Object *dictA) {
dict = *dictA;
- decrypt = NULL;
}
BaseStream::~BaseStream() {
dict.free();
- if (decrypt)
- delete decrypt;
-}
-
-void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen) {
- decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
}
//------------------------------------------------------------------------
@@ -402,8 +401,6 @@ void ImageStream::skipLine() {
StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
int widthA, int nCompsA, int nBitsA) {
- int totalBits;
-
str = strA;
predictor = predictorA;
width = widthA;
@@ -413,7 +410,6 @@ StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
ok = gFalse;
nVals = width * nComps;
- totalBits = nVals * nBits;
if (width <= 0 || nComps <= 0 || nBits <= 0 ||
nComps >= INT_MAX / nBits ||
width >= INT_MAX / nComps / nBits ||
@@ -421,8 +417,8 @@ StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
return;
}
pixBytes = (nComps * nBits + 7) >> 3;
- rowBytes = ((totalBits + 7) >> 3) + pixBytes;
- if (rowBytes < 0) {
+ rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
+ if (rowBytes <= 0) {
return;
}
predLine = (Guchar *)gmalloc(rowBytes);
@@ -550,8 +546,8 @@ GBool StreamPredictor::getNextLine() {
inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
inBits += 8;
}
- upLeftBuf[kk] = (upLeftBuf[kk] +
- (inBuf >> (inBits - nBits))) & bitMask;
+ upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] +
+ (inBuf >> (inBits - nBits))) & bitMask);
inBits -= nBits;
outBuf = (outBuf << nBits) | upLeftBuf[kk];
outBits += nBits;
@@ -614,8 +610,6 @@ void FileStream::reset() {
saved = gTrue;
bufPtr = bufEnd = buf;
bufPos = start;
- if (decrypt)
- decrypt->reset();
}
void FileStream::close() {
@@ -633,7 +627,6 @@ void FileStream::close() {
GBool FileStream::fillBuf() {
int n;
- char *p;
bufPos += bufEnd - buf;
bufPtr = bufEnd = buf;
@@ -650,11 +643,6 @@ GBool FileStream::fillBuf() {
if (bufPtr >= bufEnd) {
return gFalse;
}
- if (decrypt) {
- for (p = buf; p < bufEnd; ++p) {
- *p = (char)decrypt->decryptByte((Guchar)*p);
- }
- }
return gTrue;
}
@@ -743,9 +731,6 @@ Stream *MemStream::makeSubStream(Guint startA, GBool limited,
void MemStream::reset() {
bufPtr = buf + start;
- if (decrypt) {
- decrypt->reset();
- }
}
void MemStream::close() {
@@ -773,25 +758,6 @@ void MemStream::moveStart(int delta) {
bufPtr = buf + start;
}
-void MemStream::doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen) {
- char *newBuf;
- char *p, *q;
-
- this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
- if (decrypt) {
- newBuf = (char *)gmalloc(length);
- for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
- *q = (char)decrypt->decryptByte((Guchar)*p);
- }
- bufEnd = newBuf + length;
- bufPtr = newBuf + (bufPtr - (buf + start));
- start = 0;
- buf = newBuf;
- needFree = gTrue;
- }
-}
-
//------------------------------------------------------------------------
// EmbedStream
//------------------------------------------------------------------------
@@ -1286,8 +1252,8 @@ CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
rows = rowsA;
endOfBlock = endOfBlockA;
black = blackA;
- refLine = (short *)gmallocn(columns + 4, sizeof(short));
- codingLine = (short *)gmallocn(columns + 3, sizeof(short));
+ refLine = (short *)gmallocn(columns + 3, sizeof(short));
+ codingLine = (short *)gmallocn(columns + 2, sizeof(short));
eof = gFalse;
row = 0;
@@ -1315,7 +1281,7 @@ void CCITTFaxStream::reset() {
nextLine2D = encoding < 0;
inputBits = 0;
codingLine[0] = 0;
- codingLine[1] = refLine[2] = columns;
+ codingLine[1] = columns;
a0 = 1;
buf = EOF;
@@ -1351,8 +1317,27 @@ int CCITTFaxStream::lookChar() {
// 2-D encoding
if (nextLine2D) {
- for (i = 0; codingLine[i] < columns; ++i)
+ // state:
+ // a0New = current position in coding line (0 <= a0New <= columns)
+ // codingLine[a0] = last change in coding line
+ // (black-to-white if a0 is even,
+ // white-to-black if a0 is odd)
+ // refLine[b1] = next change in reference line of opposite color
+ // to a0
+ // invariants:
+ // 0 <= codingLine[a0] <= a0New
+ // <= refLine[b1] <= refLine[b1+1] <= columns
+ // 0 <= a0 <= columns+1
+ // refLine[0] = 0
+ // refLine[n] = refLine[n+1] = columns
+ // -- for some 1 <= n <= columns+1
+ // end condition:
+ // 0 = codingLine[0] <= codingLine[1] < codingLine[2] < ...
+ // < codingLine[n-1] < codingLine[n] = columns
+ // -- where 1 <= n <= columns+1
+ for (i = 0; codingLine[i] < columns; ++i) {
refLine[i] = codingLine[i];
+ }
refLine[i] = refLine[i + 1] = columns;
b1 = 1;
a0New = codingLine[a0 = 0] = 0;
@@ -1384,68 +1369,93 @@ int CCITTFaxStream::lookChar() {
} while (code3 >= 64);
}
if (code1 > 0 || code2 > 0) {
- codingLine[a0 + 1] = a0New + code1;
+ if (a0New + code1 <= columns) {
+ codingLine[a0 + 1] = a0New + code1;
+ } else {
+ codingLine[a0 + 1] = columns;
+ }
++a0;
- a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
+ if (codingLine[a0] + code2 <= columns) {
+ codingLine[a0 + 1] = codingLine[a0] + code2;
+ } else {
+ codingLine[a0 + 1] = columns;
+ }
++a0;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ a0New = codingLine[a0];
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
}
break;
case twoDimVert0:
- a0New = codingLine[++a0] = refLine[b1];
if (refLine[b1] < columns) {
+ a0New = codingLine[++a0] = refLine[b1];
++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
+ } else {
+ a0New = codingLine[++a0] = columns;
}
break;
case twoDimVertR1:
- a0New = codingLine[++a0] = refLine[b1] + 1;
- if (refLine[b1] < columns) {
+ if (refLine[b1] + 1 < columns) {
+ a0New = codingLine[++a0] = refLine[b1] + 1;
++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
+ } else {
+ a0New = codingLine[++a0] = columns;
}
break;
case twoDimVertL1:
- if (a0 == 0 || refLine[b1] - 1 > a0New) {
+ if (refLine[b1] - 1 > a0New || (a0 == 0 && refLine[b1] == 1)) {
a0New = codingLine[++a0] = refLine[b1] - 1;
--b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
}
break;
case twoDimVertR2:
- a0New = codingLine[++a0] = refLine[b1] + 2;
- if (refLine[b1] < columns) {
+ if (refLine[b1] + 2 < columns) {
+ a0New = codingLine[++a0] = refLine[b1] + 2;
++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
+ } else {
+ a0New = codingLine[++a0] = columns;
}
break;
case twoDimVertL2:
- if (a0 == 0 || refLine[b1] - 2 > a0New) {
+ if (refLine[b1] - 2 > a0New || (a0 == 0 && refLine[b1] == 2)) {
a0New = codingLine[++a0] = refLine[b1] - 2;
--b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
}
break;
case twoDimVertR3:
- a0New = codingLine[++a0] = refLine[b1] + 3;
- if (refLine[b1] < columns) {
+ if (refLine[b1] + 3 < columns) {
+ a0New = codingLine[++a0] = refLine[b1] + 3;
++b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
+ } else {
+ a0New = codingLine[++a0] = columns;
}
break;
case twoDimVertL3:
- if (a0 == 0 || refLine[b1] - 3 > a0New) {
+ if (refLine[b1] - 3 > a0New || (a0 == 0 && refLine[b1] == 3)) {
a0New = codingLine[++a0] = refLine[b1] - 3;
--b1;
- while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ while (refLine[b1] <= a0New && refLine[b1] < columns) {
b1 += 2;
+ }
}
break;
case EOF:
@@ -1469,16 +1479,18 @@ int CCITTFaxStream::lookChar() {
} while (code3 >= 64);
codingLine[a0+1] = codingLine[a0] + code1;
++a0;
- if (codingLine[a0] >= columns)
+ if (codingLine[a0] >= columns) {
break;
+ }
code2 = 0;
do {
code2 += code3 = getBlackCode();
} while (code3 >= 64);
codingLine[a0+1] = codingLine[a0] + code2;
++a0;
- if (codingLine[a0] >= columns)
+ if (codingLine[a0] >= columns) {
break;
+ }
}
}
@@ -1859,10 +1871,11 @@ static int dctZigZag[64] = {
63
};
-DCTStream::DCTStream(Stream *strA):
+DCTStream::DCTStream(Stream *strA, GBool colorXformA):
FilterStream(strA) {
int i, j;
+ colorXform = colorXformA;
progressive = interleaved = gFalse;
width = height = 0;
mcuWidth = mcuHeight = 0;
@@ -1888,20 +1901,8 @@ DCTStream::DCTStream(Stream *strA):
}
DCTStream::~DCTStream() {
- int i, j;
-
+ close();
delete str;
- if (progressive || !interleaved) {
- for (i = 0; i < numComps; ++i) {
- gfree(frameBuf[i]);
- }
- } else {
- for (i = 0; i < numComps; ++i) {
- for (j = 0; j < mcuHeight; ++j) {
- gfree(rowBuf[i][j]);
- }
- }
- }
}
void DCTStream::reset() {
@@ -1915,7 +1916,6 @@ void DCTStream::reset() {
numQuantTables = 0;
numDCHuffTables = 0;
numACHuffTables = 0;
- colorXform = 0;
gotJFIFMarker = gFalse;
gotAdobeMarker = gFalse;
restartInterval = 0;
@@ -1943,14 +1943,18 @@ void DCTStream::reset() {
mcuHeight *= 8;
// figure out color transform
- if (!gotAdobeMarker && numComps == 3) {
- if (gotJFIFMarker) {
- colorXform = 1;
- } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
- compInfo[2].id == 66) { // ASCII "RGB"
- colorXform = 0;
+ if (colorXform == -1) {
+ if (numComps == 3) {
+ if (gotJFIFMarker) {
+ colorXform = 1;
+ } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
+ compInfo[2].id == 66) { // ASCII "RGB"
+ colorXform = 0;
+ } else {
+ colorXform = 1;
+ }
} else {
- colorXform = 1;
+ colorXform = 0;
}
}
@@ -2000,6 +2004,20 @@ void DCTStream::reset() {
}
}
+void DCTStream::close() {
+ int i, j;
+
+ 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;
+ }
+ FilterStream::close();
+}
+
int DCTStream::getChar() {
int c;
@@ -2924,11 +2942,8 @@ GBool DCTStream::readBaselineSOF() {
width = read16();
numComps = str->getChar();
if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream", prec);
- return gFalse;
- }
- if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream", prec);
+ error(getPos(), "Bad number of components in DCT stream");
+ numComps = 0;
return gFalse;
}
if (prec != 8) {
@@ -2962,11 +2977,6 @@ GBool DCTStream::readProgressiveSOF() {
numComps = 0;
return gFalse;
}
- if (numComps <= 0 || numComps > 4) {
- error(getPos(), "Bad number of components in DCT stream");
- numComps = 0;
- return gFalse;
- }
if (prec != 8) {
error(getPos(), "Bad DCT precision %d", prec);
return gFalse;
@@ -3884,6 +3894,7 @@ FlateStream::FlateStream(Stream *strA, int predictor, int columns,
}
litCodeTab.codes = NULL;
distCodeTab.codes = NULL;
+ memset(buf, 0, flateWindow);
}
FlateStream::~FlateStream() {
@@ -4444,33 +4455,61 @@ void ASCII85Encoder::reset() {
GBool ASCII85Encoder::fillBuf() {
Gulong t;
char buf1[5];
- int c;
+ int c0, c1, c2, c3;
int n, i;
- if (eof)
+ if (eof) {
return gFalse;
- t = 0;
- for (n = 0; n < 4; ++n) {
- if ((c = str->getChar()) == EOF)
- break;
- t = (t << 8) + c;
}
+ c0 = str->getChar();
+ c1 = str->getChar();
+ c2 = str->getChar();
+ c3 = str->getChar();
bufPtr = bufEnd = buf;
- if (n > 0) {
- if (n == 4 && t == 0) {
+ if (c3 == EOF) {
+ if (c0 == EOF) {
+ n = 0;
+ t = 0;
+ } else {
+ if (c1 == EOF) {
+ n = 1;
+ t = c0 << 24;
+ } else if (c2 == EOF) {
+ n = 2;
+ t = (c0 << 24) | (c1 << 16);
+ } else {
+ n = 3;
+ t = (c0 << 24) | (c1 << 16) | (c2 << 8);
+ }
+ for (i = 4; i >= 0; --i) {
+ buf1[i] = (char)(t % 85 + 0x21);
+ t /= 85;
+ }
+ for (i = 0; i <= n; ++i) {
+ *bufEnd++ = buf1[i];
+ if (++lineLen == 65) {
+ *bufEnd++ = '\n';
+ lineLen = 0;
+ }
+ }
+ }
+ *bufEnd++ = '~';
+ *bufEnd++ = '>';
+ eof = gTrue;
+ } else {
+ t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
+ if (t == 0) {
*bufEnd++ = 'z';
if (++lineLen == 65) {
*bufEnd++ = '\n';
lineLen = 0;
}
} else {
- if (n < 4)
- t <<= 8 * (4 - n);
for (i = 4; i >= 0; --i) {
buf1[i] = (char)(t % 85 + 0x21);
t /= 85;
}
- for (i = 0; i <= n; ++i) {
+ for (i = 0; i <= 4; ++i) {
*bufEnd++ = buf1[i];
if (++lineLen == 65) {
*bufEnd++ = '\n';
@@ -4479,12 +4518,7 @@ GBool ASCII85Encoder::fillBuf() {
}
}
}
- if (n < 4) {
- *bufEnd++ = '~';
- *bufEnd++ = '>';
- eof = gTrue;
- }
- return bufPtr < bufEnd;
+ return gTrue;
}
//------------------------------------------------------------------------
diff --git a/Build/source/libs/xpdf/xpdf/Stream.h b/Build/source/libs/xpdf/xpdf/Stream.h
index e1e7bae4282..85a84691bd9 100644
--- a/Build/source/libs/xpdf/xpdf/Stream.h
+++ b/Build/source/libs/xpdf/xpdf/Stream.h
@@ -19,7 +19,6 @@
#include "gtypes.h"
#include "Object.h"
-class Decrypt;
class BaseStream;
//------------------------------------------------------------------------
@@ -46,6 +45,15 @@ enum StreamColorSpaceMode {
};
//------------------------------------------------------------------------
+
+// This is in Stream.h instead of Decrypt.h to avoid really annoying
+// include file dependency loops.
+enum CryptAlgorithm {
+ cryptRC4,
+ cryptAES
+};
+
+//------------------------------------------------------------------------
// Stream (base class)
//------------------------------------------------------------------------
@@ -101,6 +109,10 @@ public:
// Get the BaseStream of this stream.
virtual BaseStream *getBaseStream() = 0;
+ // Get the stream after the last decoder (this may be a BaseStream
+ // or a DecryptStream).
+ virtual Stream *getUndecodedStream() = 0;
+
// Get the dictionary associated with this stream.
virtual Dict *getDict() = 0;
@@ -111,6 +123,9 @@ public:
virtual void getImageParams(int *bitsPerComponent,
StreamColorSpaceMode *csMode) {}
+ // Return the next stream in the "stack".
+ virtual Stream *getNextStream() { return NULL; }
+
// Add filters to this stream according to the parameters in <dict>.
// Returns the new stream.
Stream *addFilters(Object *dict);
@@ -138,20 +153,14 @@ public:
virtual void setPos(Guint pos, int dir = 0) = 0;
virtual GBool isBinary(GBool last = gTrue) { return last; }
virtual BaseStream *getBaseStream() { return this; }
+ virtual Stream *getUndecodedStream() { return this; }
virtual Dict *getDict() { return dict.getDict(); }
+ virtual GString *getFileName() { return NULL; }
// Get/set position of first byte of stream within the file.
virtual Guint getStart() = 0;
virtual void moveStart(int delta) = 0;
- // Set decryption for this stream.
- virtual void doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen);
-
-protected:
-
- Decrypt *decrypt;
-
private:
Object dict;
@@ -172,7 +181,9 @@ public:
virtual int getPos() { return str->getPos(); }
virtual void setPos(Guint pos, int dir = 0);
virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
+ virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); }
virtual Dict *getDict() { return str->getDict(); }
+ virtual Stream *getNextStream() { return str; }
protected:
@@ -318,8 +329,6 @@ public:
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
- virtual void doDecryption(Guchar *fileKey, int keyLength,
- int objNum, int objGen);
private:
@@ -530,7 +539,7 @@ private:
short getWhiteCode();
short getBlackCode();
short lookBits(int n);
- void eatBits(int n) { inputBits -= n; }
+ void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; }
};
//------------------------------------------------------------------------
@@ -566,10 +575,11 @@ struct DCTHuffTable {
class DCTStream: public FilterStream {
public:
- DCTStream(Stream *strA);
+ DCTStream(Stream *strA, int colorXformA);
virtual ~DCTStream();
virtual StreamKind getKind() { return strDCT; }
virtual void reset();
+ virtual void close();
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent);
@@ -586,7 +596,9 @@ private:
DCTCompInfo compInfo[4]; // info for each component
DCTScanInfo scanInfo; // info for the current scan
int numComps; // number of components in image
- int colorXform; // need YCbCr-to-RGB transform?
+ int colorXform; // color transform: -1 = unspecified
+ // 0 = none
+ // 1 = YUV/YUVK -> RGB/CMYK
GBool gotJFIFMarker; // set if APP0 JFIF marker was present
GBool gotAdobeMarker; // set if APP14 Adobe marker was present
int restartInterval; // restart interval, in MCUs
diff --git a/Build/source/libs/xpdf/xpdf/XRef.cc b/Build/source/libs/xpdf/xpdf/XRef.cc
index c5a6aca8a6f..367f99b2fe2 100644
--- a/Build/source/libs/xpdf/xpdf/XRef.cc
+++ b/Build/source/libs/xpdf/xpdf/XRef.cc
@@ -90,7 +90,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
objStr.streamReset();
obj1.initNull();
str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
- parser = new Parser(xref, new Lexer(xref, str));
+ parser = new Parser(xref, new Lexer(xref, str), gFalse);
for (i = 0; i < nObjects; ++i) {
parser->getObj(&obj1);
parser->getObj(&obj2);
@@ -131,7 +131,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
str = new EmbedStream(objStr.getStream(), &obj1, gTrue,
offsets[i+1] - offsets[i]);
}
- parser = new Parser(xref, new Lexer(xref, str));
+ parser = new Parser(xref, new Lexer(xref, str), gFalse);
parser->getObj(&objs[i]);
while (str->getChar() != EOF) ;
delete parser;
@@ -283,7 +283,8 @@ GBool XRef::readXRef(Guint *pos) {
obj.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
- str->makeSubStream(start + *pos, gFalse, 0, &obj)));
+ str->makeSubStream(start + *pos, gFalse, 0, &obj)),
+ gTrue);
parser->getObj(&obj);
// parse an old-style xref table
@@ -624,7 +625,7 @@ GBool XRef::constructXRef() {
size = 0;
entries = NULL;
- error(0, "PDF file is damaged - attempting to reconstruct xref table...");
+ error(-1, "PDF file is damaged - attempting to reconstruct xref table...");
gotRoot = gFalse;
streamEndsLen = streamEndsSize = 0;
@@ -636,12 +637,16 @@ GBool XRef::constructXRef() {
}
p = buf;
+ // skip whitespace
+ while (*p && Lexer::isSpace(*p & 0xff)) ++p;
+
// got trailer dictionary
if (!strncmp(p, "trailer", 7)) {
obj.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
- str->makeSubStream(pos + 7, gFalse, 0, &obj)));
+ str->makeSubStream(pos + 7, gFalse, 0, &obj)),
+ gFalse);
parser->getObj(&newTrailerDict);
if (newTrailerDict.isDict()) {
newTrailerDict.dictLookupNF("Root", &obj);
@@ -724,7 +729,8 @@ GBool XRef::constructXRef() {
}
void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA,
- Guchar *fileKeyA, int keyLengthA, int encVersionA) {
+ Guchar *fileKeyA, int keyLengthA, int encVersionA,
+ CryptAlgorithm encAlgorithmA) {
int i;
encrypted = gTrue;
@@ -739,6 +745,7 @@ void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA,
fileKey[i] = fileKeyA[i];
}
encVersion = encVersionA;
+ encAlgorithm = encAlgorithmA;
}
GBool XRef::okToPrint(GBool ignoreOwnerPW) {
@@ -777,7 +784,8 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
obj1.initNull();
parser = new Parser(this,
new Lexer(this,
- str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));
+ str->makeSubStream(start + e->offset, gFalse, 0, &obj1)),
+ gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
@@ -790,8 +798,8 @@ Object *XRef::fetch(int num, int gen, Object *obj) {
delete parser;
goto err;
}
- parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
- num, gen);
+ parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL,
+ encAlgorithm, keyLength, num, gen);
obj1.free();
obj2.free();
obj3.free();
diff --git a/Build/source/libs/xpdf/xpdf/XRef.h b/Build/source/libs/xpdf/xpdf/XRef.h
index 91cf28403e2..6eb32b92ae8 100644
--- a/Build/source/libs/xpdf/xpdf/XRef.h
+++ b/Build/source/libs/xpdf/xpdf/XRef.h
@@ -85,7 +85,8 @@ public:
// Set the encryption parameters.
void setEncryption(int permFlagsA, GBool ownerPasswordOkA,
- Guchar *fileKeyA, int keyLengthA, int encVersionA);
+ Guchar *fileKeyA, int keyLengthA, int encVersionA,
+ CryptAlgorithm encAlgorithmA);
// Is the file encrypted?
GBool isEncrypted() { return encrypted; }
@@ -147,7 +148,8 @@ private:
GBool ownerPasswordOk; // true if owner password is correct
Guchar fileKey[16]; // file decryption key
int keyLength; // length of key, in bytes
- int encVersion; // encryption algorithm
+ int encVersion; // encryption version
+ CryptAlgorithm encAlgorithm; // encryption algorithm
Guint getStartXref();
GBool readXRef(Guint *pos);
diff --git a/Build/source/libs/xpdf/xpdf/config.h b/Build/source/libs/xpdf/xpdf/config.h
index 0bd5541c2b0..81d4dd071b5 100644
--- a/Build/source/libs/xpdf/xpdf/config.h
+++ b/Build/source/libs/xpdf/xpdf/config.h
@@ -2,7 +2,7 @@
//
// config.h
//
-// Copyright 1996-2005 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
//
//========================================================================
@@ -14,26 +14,25 @@
//------------------------------------------------------------------------
// xpdf version
-#define xpdfVersion "3.01"
-#define xpdfVersionNum 3.01
+#define xpdfVersion "3.02"
+#define xpdfVersionNum 3.02
#define xpdfMajorVersion 3
-#define xpdfMinorVersion 1
+#define xpdfMinorVersion 2
#define xpdfUpdateVersion 0
#define xpdfMajorVersionStr "3"
-#define xpdfMinorVersionStr "1"
+#define xpdfMinorVersionStr "2"
#define xpdfUpdateVersionStr "0"
// supported PDF version
-// xpdf says only 1.5, but 1.7 is the same for pdfTeX's purpose
#define supportedPDFVersionStr "1.7"
#define supportedPDFVersionNum 1.7
// copyright notice
-#define xpdfCopyright "Copyright 1996-2005 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2007 Glyph & Cog, LLC"
// Windows resource file stuff
-#define winxpdfVersion "WinXpdf 3.01"
-#define xpdfCopyrightAmp "Copyright 1996-2005 Glyph && Cog, LLC"
+#define winxpdfVersion "WinXpdf 3.02"
+#define xpdfCopyrightAmp "Copyright 1996-2007 Glyph && Cog, LLC"
//------------------------------------------------------------------------
// paper size